Instagram Feed - Version 2.4

Version Description

  • New: Email alerts for critical issues. If there's an issue with an Instagram feed on your website which hasn't been resolved yet then you'll receive an email notification to let you know. This is sent once per week until the issue is resolved. These emails can be disabled by using the following setting: Instagram Feed > Customize > Advanced > Misc > Feed Issue Email Report.
  • New: Admin notifications for critical issues. If there is an error with the feed, admins will see notices in the dashboard and on the front-end of the site along with instructions on how to resolve the issue. Front-end admin notifications can be disabled by using the following setting: Instagram Feed > Customize > Advanced > Misc > Disable Admin Error Notice.
  • New: Added a WordPress 'Site Health' integration. If there is a critical error with your feeds, it will now be flagged in the site health page.
  • New: Added "About Us" page for those who would like to learn more about Smash Balloon and our other products. Go to Instagram Feed -> About Us in the dashboard.
  • New: Added support for an Instagram Feed widget. When on the widgets menu, look for the widget "Instagram Feed" to add your feed to a widget area.
Download this release

Release Info

Developer smashballoon
Plugin Icon 128x128 Instagram Feed
Version 2.4
Comparing to
See all releases

Code changes from version 2.2.2 to 2.4

Files changed (45) hide show
  1. README.txt +15 -1
  2. css/sb-blocks.css +3 -0
  3. css/sb-instagram-2-2.css +818 -818
  4. css/sb-instagram-admin.css +719 -1
  5. css/sb-instagram.css +818 -818
  6. img/about/api-error.png +0 -0
  7. img/about/icon-full.svg +1 -0
  8. img/about/icon-none.svg +1 -0
  9. img/about/icon-partial.svg +1 -0
  10. img/about/plugin-fb.png +0 -0
  11. img/about/plugin-mi.png +0 -0
  12. img/about/plugin-om.png +0 -0
  13. img/about/plugin-rp.png +0 -0
  14. img/about/plugin-seo.png +0 -0
  15. img/about/plugin-smtp.png +0 -0
  16. img/about/plugin-tw.jpg +0 -0
  17. img/about/plugin-wpforms.png +0 -0
  18. img/about/plugin-yt.png +0 -0
  19. img/about/steps.png +0 -0
  20. img/about/team.jpg +0 -0
  21. img/balloon-120.png +0 -0
  22. img/insta-logo.png +0 -0
  23. img/sbi-icon-offer.png +0 -0
  24. inc/admin/PluginSilentUpgrader.php +576 -0
  25. inc/admin/PluginSilentUpgraderSkin.php +57 -0
  26. inc/admin/actions.php +1283 -1182
  27. inc/admin/addon-functions.php +175 -0
  28. inc/admin/blocks/class-sbi-blocks.php +149 -0
  29. inc/admin/class-install-skin.php +27 -0
  30. inc/admin/class-sbi-about.php +1317 -0
  31. inc/admin/class-sbi-sitehealth.php +82 -0
  32. inc/admin/main.php +2847 -2732
  33. inc/class-sb-instagram-api-connect.php +421 -379
  34. inc/class-sb-instagram-cron-updater.php +225 -225
  35. inc/class-sb-instagram-display-elements.php +360 -360
  36. inc/class-sb-instagram-education.php +130 -0
  37. inc/class-sb-instagram-feed.php +1476 -1448
  38. inc/class-sb-instagram-parse.php +313 -313
  39. inc/class-sb-instagram-post-set.php +187 -187
  40. inc/class-sb-instagram-post.php +546 -546
  41. inc/class-sb-instagram-posts-manager.php +524 -448
  42. inc/class-sb-instagram-settings.php +603 -597
  43. inc/class-sb-instagram-token-refresher.php +175 -175
  44. inc/email.php +102 -0
  45. inc/if-functions.php +915 -1022
README.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: smashballoon, craig-at-smash-balloon
3
  Tags: Instagram, Instagram feed, Instagram photos, Instagram widget, Instagram gallery
4
  Requires at least: 3.4
5
  Tested up to: 5.4
6
- Stable tag: 2.2.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -26,6 +26,7 @@ Display Instagram posts from your Instagram accounts, either in the same single
26
  * Display a **beautiful header** at the top of your feed
27
  * Display your Instagram photos chronologically or in random order
28
  * Add your own Custom CSS and JavaScript for even deeper customizations
 
29
 
30
  = Benefits =
31
  * **Increase Social Engagement** - Increase engagement between you and your Instagram followers. Increase your number of followers by displaying your Instagram content directly on your site.
@@ -324,6 +325,19 @@ We understand that sometimes you need help, have issues or just have questions.
324
  * Plus more customization options added all the time!
325
 
326
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  = 2.2.2 =
328
  * Tested with upcoming WordPress 5.4 update.
329
  * Tweak: Language files updated to account for all new strings.
3
  Tags: Instagram, Instagram feed, Instagram photos, Instagram widget, Instagram gallery
4
  Requires at least: 3.4
5
  Tested up to: 5.4
6
+ Stable tag: 2.4
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
26
  * Display a **beautiful header** at the top of your feed
27
  * Display your Instagram photos chronologically or in random order
28
  * Add your own Custom CSS and JavaScript for even deeper customizations
29
+ * Handy block for easily adding your feed to posts and pages using the block editor
30
 
31
  = Benefits =
32
  * **Increase Social Engagement** - Increase engagement between you and your Instagram followers. Increase your number of followers by displaying your Instagram content directly on your site.
325
  * Plus more customization options added all the time!
326
 
327
  == Changelog ==
328
+ = 2.4 =
329
+ * New: Email alerts for critical issues. If there's an issue with an Instagram feed on your website which hasn't been resolved yet then you'll receive an email notification to let you know. This is sent once per week until the issue is resolved. These emails can be disabled by using the following setting: Instagram Feed > Customize > Advanced > Misc > Feed Issue Email Report.
330
+ * New: Admin notifications for critical issues. If there is an error with the feed, admins will see notices in the dashboard and on the front-end of the site along with instructions on how to resolve the issue. Front-end admin notifications can be disabled by using the following setting: Instagram Feed > Customize > Advanced > Misc > Disable Admin Error Notice.
331
+ * New: Added a WordPress 'Site Health' integration. If there is a critical error with your feeds, it will now be flagged in the site health page.
332
+ * New: Added "About Us" page for those who would like to learn more about Smash Balloon and our other products. Go to Instagram Feed -> About Us in the dashboard.
333
+ * New: Added support for an Instagram Feed widget. When on the widgets menu, look for the widget "Instagram Feed" to add your feed to a widget area.
334
+
335
+ = 2.3.1 =
336
+ * Fix: Added workaround for personal account connection error and header display issue due to an Instagram API bug. After updating, click "Save Changes" on the Instagram Feed settings page, "Configure" tab to clear your cache.
337
+
338
+ = 2.3 =
339
+ * New: Added an "Instagram Feed" Gutenberg block to use in the block editor, allowing you to easily add a feed to posts and pages.
340
+
341
  = 2.2.2 =
342
  * Tested with upcoming WordPress 5.4 update.
343
  * Tweak: Language files updated to account for all new strings.
css/sb-blocks.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ .sbi {
2
+ pointer-events: none !important;
3
+ }
css/sb-instagram-2-2.css CHANGED
@@ -1,819 +1,819 @@
1
- /**************/
2
- /*** LAYOUT ***/
3
- /**************/
4
-
5
- /* Feed container */
6
- #sb_instagram {
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
- #sb_instagram:after{
15
- content: "";
16
- display: table;
17
- clear: both;
18
- }
19
-
20
- /*********************/
21
- /*** STYLE OPTIONS ***/
22
- /*********************/
23
- #sb_instagram.sbi_fixed_height{
24
- overflow: hidden;
25
- overflow-y: auto;
26
- -webkit-box-sizing: border-box;
27
- -moz-box-sizing: border-box;
28
- box-sizing: border-box;
29
- }
30
- #sb_instagram #sbi_images{
31
- width: 100%;
32
- float: left;
33
- line-height: 0;
34
-
35
- -webkit-box-sizing: border-box;
36
- -moz-box-sizing: border-box;
37
- box-sizing: border-box;
38
- }
39
- /* Remove header shadow/border */
40
- #sb_instagram .sbi_header_link {
41
- -webkit-box-shadow: none;
42
- box-shadow: none;
43
- }
44
- #sb_instagram .sbi_header_link:hover {
45
- border: none;
46
- }
47
-
48
- /* Items */
49
- #sb_instagram #sbi_images .sbi_item{
50
- display: -moz-inline-stack;
51
- display: inline-block;
52
- float: left;
53
- vertical-align: top;
54
- zoom: 1;
55
- *display: inline;
56
-
57
- max-height: 1000px;
58
- padding: inherit !important;
59
- margin: 0 !important;
60
- text-decoration: none;
61
- opacity: 1;
62
- overflow: hidden;
63
-
64
- -webkit-box-sizing: border-box;
65
- -moz-box-sizing: border-box;
66
- box-sizing: border-box;
67
-
68
- -webkit-transition: all 0.5s ease;
69
- -moz-transition: all 0.5s ease;
70
- -o-transition: all 0.5s ease;
71
- -ms-transition: all 0.5s ease;
72
- transition: all 0.5s ease;
73
- }
74
- /* Transition items in */
75
- #sb_instagram #sbi_images .sbi_item.sbi_transition{
76
- opacity: 0;
77
- max-height: 0;
78
- }
79
-
80
- /* Cols */
81
- #sb_instagram.sbi_col_1 #sbi_images .sbi_item{ width: 100%; }
82
- #sb_instagram.sbi_col_2 #sbi_images .sbi_item{ width: 50%; }
83
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item{ width: 33.33%; }
84
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item{ width: 25%; }
85
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item{ width: 20%; }
86
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item{ width: 16.66%; }
87
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item{ width: 14.28%; }
88
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item{ width: 12.5%; }
89
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item{ width: 11.11%; }
90
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{ width: 10%; }
91
-
92
- /* Disable mobile layout */
93
- #sb_instagram.sbi_col_1.sbi_disable_mobile #sbi_images .sbi_item{ width: 100%; }
94
- #sb_instagram.sbi_col_2.sbi_disable_mobile #sbi_images .sbi_item{ width: 50%; }
95
- #sb_instagram.sbi_col_3.sbi_disable_mobile #sbi_images .sbi_item{ width: 33.33%; }
96
- #sb_instagram.sbi_col_4.sbi_disable_mobile #sbi_images .sbi_item{ width: 25%; }
97
- #sb_instagram.sbi_col_5.sbi_disable_mobile #sbi_images .sbi_item{ width: 20%; }
98
- #sb_instagram.sbi_col_6.sbi_disable_mobile #sbi_images .sbi_item{ width: 16.66%; }
99
- #sb_instagram.sbi_col_7.sbi_disable_mobile #sbi_images .sbi_item{ width: 14.28%; }
100
- #sb_instagram.sbi_col_8.sbi_disable_mobile #sbi_images .sbi_item{ width: 12.5%; }
101
- #sb_instagram.sbi_col_9.sbi_disable_mobile #sbi_images .sbi_item{ width: 11.11%; }
102
- #sb_instagram.sbi_col_10.sbi_disable_mobile #sbi_images .sbi_item{ width: 10%; }
103
-
104
- /* Photos */
105
- #sb_instagram .sbi_photo_wrap{
106
- position: relative;
107
- }
108
- #sb_instagram .sbi_photo{
109
- display: block;
110
- text-decoration: none;
111
- }
112
- #sb_instagram .sbi_photo img{
113
- width: 100%;
114
- height: auto;
115
- }
116
- #sb_instagram .sbi_no_js img{
117
- display: none;
118
- }
119
- #sb_instagram a,
120
- #sb_instagram a:hover,
121
- #sb_instagram a:focus,
122
- #sb_instagram a:active{
123
- outline: none;
124
- }
125
- #sb_instagram img{
126
- display: block;
127
- padding: 0 !important;
128
- margin: 0 !important;
129
- max-width: 100% !important;
130
- opacity: 1 !important;
131
- }
132
- #sb_instagram .sbi_link{
133
- display: none;
134
- position: absolute;
135
- bottom: 0;
136
- right: 0;
137
-
138
- width: 100%;
139
- padding: 10px 0;
140
- background: rgba(0,0,0,0.5);
141
- text-align: center;
142
- color: #fff;
143
- font-size: 12px;
144
- line-height: 1.1;
145
- }
146
- #sb_instagram .sbi_link a{
147
- padding: 0 6px;
148
- text-decoration: none;
149
- color: #fff;
150
- font-size: 12px;
151
- line-height: 1.1;
152
-
153
- display: -moz-inline-stack;
154
- display: inline-block;
155
- vertical-align: top;
156
- zoom: 1;
157
- *display: inline;
158
- }
159
- #sb_instagram .sbi_link .sbi_lightbox_link{
160
- padding-bottom: 5px;
161
- }
162
- #sb_instagram .sbi_link a:hover,
163
- #sb_instagram .sbi_link a:focus{
164
- text-decoration: underline;
165
- }
166
- #sb_instagram .sbi_photo_wrap:hover .sbi_link,
167
- #sb_instagram .sbi_photo_wrap:focus .sbi_link{
168
- display: block;
169
- }
170
-
171
- /* Videos */
172
- #sb_instagram svg:not(:root).svg-inline--fa {
173
- height: 1em;
174
- display: inline-block;
175
- }
176
-
177
- #sb_instagram .sbi_type_video .sbi_playbtn,
178
- #sb_instagram .sbi_type_carousel .sbi_playbtn,
179
- .sbi_type_carousel .fa-clone,
180
- #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play,
181
- #sb_instagram .sbi_type_video .svg-inline--fa.fa-play{
182
- display: block !important;
183
- position: absolute;
184
- z-index: 1;
185
-
186
- color: #fff;
187
- color: rgba(255,255,255,0.9);
188
- font-style: normal !important;
189
- text-shadow: 0 0 8px rgba(0,0,0,0.8);
190
- }
191
- #sb_instagram .sbi_type_video .sbi_playbtn,
192
- #sb_instagram .sbi_type_carousel .sbi_playbtn {
193
- z-index: 2;
194
- top: 50%;
195
- left: 50%;
196
- margin-top: -24px;
197
- margin-left: -19px;
198
- padding: 0;
199
- font-size: 48px;
200
- }
201
- #sb_instagram .sbi_type_carousel .fa-clone{
202
- right: 12px;
203
- top: 12px;
204
- font-size: 24px;
205
- text-shadow: 0 0 8px rgba(0,0,0,0.3);
206
- }
207
- .sbi_type_carousel svg.fa-clone,
208
- #sb_instagram .sbi_type_video .svg-inline--fa.fa-play,
209
- #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play{
210
- -webkit-filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
211
- filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
212
- }
213
-
214
- /* Loader */
215
- #sb_instagram .sbi_loader{
216
- width: 20px;
217
- height: 20px;
218
-
219
- position: relative;
220
- top: 50%;
221
- left: 50%;
222
- margin: -10px 0 0 -10px;
223
- background-color: #000;
224
- background-color: rgba(0,0,0,0.5);
225
-
226
- border-radius: 100%;
227
- -webkit-animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
228
- animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
229
- }
230
- #sb_instagram br {
231
- display: none;
232
- }
233
- #sbi_load p {
234
- display: inline;
235
- padding: 0;
236
- margin: 0;
237
- }
238
- /* Loader in button */
239
- #sb_instagram #sbi_load .sbi_loader{
240
- position: absolute;
241
- margin-top: -11px;
242
- background-color: #fff;
243
- opacity: 1;
244
- }
245
- @-webkit-keyframes sbi-sk-scaleout {
246
- 0% { -webkit-transform: scale(0) }
247
- 100% {
248
- -webkit-transform: scale(1.0);
249
- opacity: 0;
250
- }
251
- }
252
- @keyframes sbi-sk-scaleout {
253
- 0% {
254
- -webkit-transform: scale(0);
255
- -ms-transform: scale(0);
256
- transform: scale(0);
257
- } 100% {
258
- -webkit-transform: scale(1.0);
259
- -ms-transform: scale(1.0);
260
- transform: scale(1.0);
261
- opacity: 0;
262
- }
263
- }
264
-
265
- #sb_instagram .fa-spin,
266
- #sbi_lightbox .fa-spin{
267
- -webkit-animation: fa-spin 2s infinite linear;
268
- animation: fa-spin 2s infinite linear
269
- }
270
-
271
- #sb_instagram .fa-pulse,
272
- #sbi_lightbox .fa-pulse{
273
- -webkit-animation: fa-spin 1s infinite steps(8);
274
- animation: fa-spin 1s infinite steps(8)
275
- }
276
-
277
- @-webkit-keyframes fa-spin {
278
- 0% {
279
- -webkit-transform: rotate(0deg);
280
- transform: rotate(0deg)
281
- }
282
- 100% {
283
- -webkit-transform: rotate(359deg);
284
- transform: rotate(359deg)
285
- }
286
- }
287
-
288
- @keyframes fa-spin {
289
- 0% {
290
- -webkit-transform: rotate(0deg);
291
- transform: rotate(0deg)
292
- }
293
- 100% {
294
- -webkit-transform: rotate(359deg);
295
- transform: rotate(359deg)
296
- }
297
- }
298
- /* Screen reader */
299
- .sbi-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;text-align: left !important; }
300
-
301
- /* HEADER */
302
- #sb_instagram .sb_instagram_header{
303
- float: left;
304
- clear: both;
305
- margin: 0 0 15px 0;
306
- padding: 0;
307
- line-height: 1.2;
308
- width: 100%;
309
- }
310
- #sb_instagram .sb_instagram_header a{
311
- float: left;
312
- display: block;
313
- /*width: 100%;*/
314
- min-width: 100%\9;
315
- text-decoration: none;
316
- transition: color 0.5s ease;
317
- }
318
- .sbi_no_avatar .sbi_header_img{
319
- background: #333;
320
- color: #fff;
321
- width: 50px;
322
- height: 50px;
323
- position: relative;
324
- }
325
- .sbi_no_avatar .sbi_header_hashtag_icon {
326
- display: block;
327
- color: #fff;
328
- opacity: .9;
329
- -webkit-transition: background .6s linear,color .6s linear;
330
- -moz-transition: background .6s linear,color .6s linear;
331
- -ms-transition: background .6s linear,color .6s linear;
332
- -o-transition: background .6s linear,color .6s linear;
333
- transition: background .6s linear,color .6s linear
334
- }
335
-
336
- .sbi_no_avatar:hover .sbi_header_hashtag_icon {
337
- display: block;
338
- opacity: 1;
339
- -webkit-transition: background .2s linear,color .2s linear;
340
- -moz-transition: background .2s linear,color .2s linear;
341
- -ms-transition: background .2s linear,color .2s linear;
342
- -o-transition: background .2s linear,color .2s linear;
343
- transition: background .2s linear,color .2s linear
344
- }
345
- /** Medium Header */
346
- /* Only use medium & large headers on devices above 480px */
347
- @media all and (min-width: 480px){
348
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img {
349
- width: 80px;
350
- height: 80px;
351
- border-radius: 40px;
352
- }
353
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img img {
354
- width: 80px;
355
- height: 80px;
356
- border-radius: 40px;
357
- }
358
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3 {
359
- font-size: 20px;
360
- }
361
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
362
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
363
- font-size: 14px;
364
- }
365
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3,
366
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
367
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
368
- margin-left: 95px !important;
369
- line-height: 1.4
370
- }
371
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3{
372
- margin-right: -85px !important;
373
- }
374
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info{
375
- margin-top: 4px !important;
376
- }
377
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text.sbi_no_bio h3{
378
- padding-top: 20px !important;
379
- }
380
- /** Large Header */
381
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img {
382
- width: 120px;
383
- height: 120px;
384
- border-radius: 60px;
385
- }
386
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img img {
387
- width: 120px;
388
- height: 120px;
389
- border-radius: 60px;
390
- }
391
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3 {
392
- font-size: 28px;
393
- }
394
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
395
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
396
- font-size: 16px;
397
- }
398
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3,
399
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
400
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
401
- margin-left: 140px !important;
402
- line-height: 1.5;
403
- }
404
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3{
405
- margin-right: -120px !important;
406
- }
407
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info{
408
- margin-top: 12px !important;
409
- }
410
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text.sbi_no_bio h3{
411
- padding-top: 32px !important;
412
- }
413
- }
414
-
415
- /* Header profile pic */
416
- #sb_instagram .sb_instagram_header .sbi_header_img{
417
- float: left;
418
- position: relative;
419
- width: 50px;
420
- margin: 0 0 0 -100% !important;
421
- overflow: hidden;
422
-
423
- -moz-border-radius: 40px;
424
- -webkit-border-radius: 40px;
425
- border-radius: 40px;
426
- }
427
- #sb_instagram .sb_instagram_header .sbi_header_img img{
428
- float: left;
429
- margin: 0 !important;
430
- padding: 0 !important;
431
- border: none !important;
432
-
433
- -moz-border-radius: 40px;
434
- -webkit-border-radius: 40px;
435
- border-radius: 40px;
436
- }
437
- /* Profile pic hover */
438
- /* Profile pic hover */
439
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
440
- opacity: 0;
441
- position: absolute;
442
- width: 100%;
443
- top: 0;
444
- bottom: 0;
445
- left: 0;
446
- text-align: center;
447
- color: #fff;
448
- background: rgba(0,0,0,0.75);
449
- }
450
-
451
- #sb_instagram .sb_instagram_header .sbi_header_img_hover .sbi_new_logo,
452
- #sb_instagram .sb_instagram_header .sbi_header_hashtag_icon .sbi_new_logo{
453
- position: absolute;
454
- top: 50%;
455
- left: 50%;
456
- margin-top: -12px;
457
- margin-left: -12px;
458
- width: 24px;
459
- height: 24px;
460
- font-size: 24px;
461
- }
462
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo,
463
- .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo{
464
- margin-top: -18px;
465
- margin-left: -18px;
466
- width: 36px;
467
- height: 36px;
468
- font-size: 36px
469
- }
470
-
471
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo,
472
- .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo {
473
- margin-top: -24px;
474
- margin-left: -24px;
475
- width: 48px;
476
- height: 48px;
477
- font-size: 48px
478
- }
479
- #sb_instagram .sb_instagram_header .sbi_header_img_hover i {
480
- overflow: hidden;
481
- background: url('../img/small-logo.png') no-repeat 0 0;
482
- }
483
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
484
- z-index: 2;
485
- transition: opacity 0.4s ease-in-out;
486
- }
487
- #sb_instagram .sb_instagram_header .sbi_fade_in{
488
- opacity: 1;
489
- transition: opacity 0.2s ease-in-out;
490
- }
491
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
492
- position: absolute;
493
- width: 100%;
494
- top: 0;
495
- bottom: 0;
496
- left: 0;
497
- text-align: center;
498
- color: #fff;
499
- background: rgba(0,0,0,0.75);
500
-
501
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
502
- filter: alpha(opacity=0);
503
- -moz-opacity: 0;
504
- -khtml-opacity: 0;
505
- opacity: 0;
506
- border-radius: 40px;
507
- transition: opacity 0.2s;
508
- }
509
- /* Fade the Instagram icon in when hovering on the header */
510
- #sb_instagram .sb_instagram_header a:hover .sbi_header_img_hover,
511
- #sb_instagram .sb_instagram_header a:focus .sbi_header_img_hover{
512
- opacity: 1;
513
- }
514
- /* Header text */
515
- #sb_instagram .sb_instagram_header .sbi_header_text{
516
- float: left;
517
- width: 100%;
518
- padding-top: 5px;
519
- }
520
- #sb_instagram .sb_instagram_header a{
521
- text-decoration: none;
522
- }
523
- #sb_instagram .sb_instagram_header .sbi_header_text .sbi_bio,
524
- #sb_instagram .sb_instagram_header .sbi_header_text h3{
525
- float: left;
526
- clear: both;
527
- width: auto;
528
- margin: 0 0 0 60px !important;
529
- padding: 0 !important;
530
- }
531
- #sb_instagram .sb_instagram_header h3{
532
- font-size: 16px;
533
- line-height: 1.3;
534
- }
535
- #sb_instagram .sb_instagram_header p{
536
- font-size: 13px;
537
- line-height: 1.3;
538
- margin: 0;
539
- padding: 0;
540
- }
541
- #sb_instagram p:empty { display: none; }
542
- #sb_instagram .sb_instagram_header .sbi_header_text img.emoji{
543
- margin-right: 3px !important;
544
- }
545
-
546
- /* No bio */
547
- #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio h3{
548
- padding-top: 9px !important;
549
- }
550
- #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio .sbi_bio_info{
551
- clear: both;
552
- }
553
-
554
-
555
- /* Buttons */
556
- #sb_instagram #sbi_load{
557
- float: left;
558
- clear: both;
559
- width: 100%;
560
- text-align: center;
561
- }
562
- #sb_instagram #sbi_load .fa-spinner{
563
- display: none;
564
- position: absolute;
565
- top: 50%;
566
- left: 50%;
567
- margin: -8px 0 0 -7px;
568
- font-size: 15px;
569
- }
570
- #sb_instagram #sbi_load{
571
- opacity: 1;
572
- transition: all 0.5s ease-in;
573
- }
574
- #sb_instagram .sbi_load_btn .sbi_btn_text, #sb_instagram .sbi_load_btn .sbi_loader{
575
- opacity: 1;
576
- transition: all 0.1s ease-in;
577
- }
578
- #sb_instagram .sbi_hidden{
579
- opacity: 0 !important;
580
- }
581
- #sb_instagram #sbi_load .sbi_load_btn,
582
- #sb_instagram .sbi_follow_btn a{
583
- display: -moz-inline-stack;
584
- display: inline-block;
585
- vertical-align: top;
586
- zoom: 1;
587
- *display: inline;
588
-
589
- padding: 7px 14px;
590
- margin: 5px auto 0 auto;
591
- background: #333;
592
- color: #eee;
593
- border: none;
594
- color: #fff;
595
- text-decoration: none;
596
- font-size: 13px;
597
- line-height: 1.5;
598
-
599
- -moz-border-radius: 4px;
600
- -webkit-border-radius: 4px;
601
- border-radius: 4px;
602
-
603
- -webkit-box-sizing: border-box;
604
- -moz-box-sizing: border-box;
605
- box-sizing: border-box;
606
- }
607
- #sb_instagram #sbi_load .sbi_load_btn {
608
- position: relative;
609
- }
610
- /* Follow button */
611
- #sb_instagram .sbi_follow_btn{
612
- display: -moz-inline-stack;
613
- display: inline-block;
614
- vertical-align: top;
615
- zoom: 1;
616
- *display: inline;
617
- text-align: center;
618
- }
619
- #sb_instagram .sbi_follow_btn.sbi_top{
620
- display: block;
621
- margin-bottom: 5px;
622
- }
623
- #sb_instagram .sbi_follow_btn a{
624
- background: #408bd1;
625
- color: #fff;
626
- }
627
- #sb_instagram .sbi_follow_btn a,
628
- #sb_instagram .sbi_follow_btn a,
629
- #sb_instagram #sbi_load .sbi_load_btn{
630
- transition: all 0.1s ease-in;
631
- }
632
- /* Hover state for default colors */
633
- #sb_instagram #sbi_load .sbi_load_btn:hover{
634
- outline: none;
635
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
636
- }
637
- #sb_instagram .sbi_follow_btn a:hover,
638
- #sb_instagram .sbi_follow_btn a:focus{
639
- outline: none;
640
- box-shadow: inset 0 0 10px 20px #359dff;
641
- }
642
- /* If a custom color is applied then just use opacity for the hover effect */
643
- #sb_instagram .sbi_follow_btn.sbi_custom a:hover,
644
- #sb_instagram .sbi_follow_btn.sbi_custom a:focus,
645
- #sb_instagram #sbi_load .sbi_load_btn.sbi_custom:hover{
646
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
647
- }
648
- /* Active state */
649
- #sb_instagram .sbi_follow_btn a:active,
650
- #sb_instagram #sbi_load .sbi_load_btn:active{
651
- box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
652
- }
653
-
654
- #sb_instagram .sbi_follow_btn .fa,
655
- #sb_instagram .sbi_follow_btn svg{
656
- margin-bottom: -1px;
657
- margin-right: 7px;
658
- font-size: 15px;
659
- }
660
- #sb_instagram .sbi_follow_btn svg{
661
- vertical-align: -.125em;
662
- }
663
- #sb_instagram #sbi_load .sbi_follow_btn{
664
- margin-left: 5px;
665
- }
666
-
667
- /* Error messages */
668
- #sb_instagram .sb_instagram_error{
669
- width: 100%;
670
- text-align: center;
671
- line-height: 1.4;
672
- }
673
-
674
- /* Mod only error msgs */
675
- #sbi_mod_error{
676
- display: none;
677
- border: 1px solid #ddd;
678
- background: #eee;
679
- color: #333;
680
- margin: 10px 0 0;
681
- padding: 10px 15px;
682
- font-size: 13px;
683
- text-align: center;
684
- clear: both;
685
-
686
- -moz-border-radius: 4px;
687
- -webkit-border-radius: 4px;
688
- border-radius: 4px;
689
- }
690
- #sbi_mod_error br {
691
- display: initial !important;
692
- }
693
- #sbi_mod_error p{
694
- padding: 5px 0 !important;
695
- margin: 0 !important;
696
- line-height: 1.3 !important;
697
- }
698
- #sbi_mod_error ol,
699
- #sbi_mod_error ul{
700
- padding: 5px 0 5px 20px !important;
701
- margin: 0 !important;
702
- }
703
- #sbi_mod_error li{
704
- padding: 1px 0 !important;
705
- margin: 0 !important;
706
- }
707
- #sbi_mod_error span{
708
- font-size: 12px;
709
- }
710
-
711
- /* Medium */
712
- #sb_instagram.sbi_medium .sbi_playbtn,
713
- #sb_instagram.sbi_medium .sbi_photo_wrap .svg-inline--fa.fa-play{
714
- margin-top: -12px;
715
- margin-left: -9px;
716
- font-size: 23px;
717
- }
718
- #sb_instagram.sbi_medium .sbi_type_carousel .sbi_photo_wrap .fa-clone{
719
- right: 8px;
720
- top: 8px;
721
- font-size: 18px;
722
- }
723
- /* Small */
724
- #sb_instagram.sbi_small .sbi_playbtn,
725
- #sb_instagram.sbi_small .sbi_photo_wrap .svg-inline--fa.fa-play{
726
- margin-top: -9px;
727
- margin-left: -7px;
728
- font-size: 18px;
729
- }
730
- #sb_instagram.sbi_small .sbi_type_carousel .sbi_photo_wrap .fa-clone{
731
- right: 5px;
732
- top: 5px;
733
- font-size: 12px;
734
- }
735
-
736
- /* Media queries */
737
- @media all and (max-width: 640px){
738
- /* Make 3-6 cols into 2 col */
739
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
740
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
741
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
742
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item{
743
- width: 50%;
744
- }
745
- /* Make 7-10 cols into 4 col */
746
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
747
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
748
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
749
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
750
- width: 25%;
751
- }
752
- /* On mobile make the min-width 100% */
753
- #sb_instagram.sbi_width_resp{
754
- width: 100% !important;
755
- }
756
- }
757
- @media all and (max-width: 480px){
758
- /* Make all cols into 1 col */
759
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
760
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
761
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
762
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item,
763
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
764
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
765
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
766
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
767
- width: 100%;
768
- }
769
- }
770
-
771
- /* NO JS */
772
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap{
773
- box-sizing: border-box;
774
- position: relative;
775
- overflow: hidden;
776
- }
777
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap:before {
778
- content: "";
779
- display: block;
780
- padding-top: 100%;
781
- z-index: -300;
782
- }
783
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo {
784
- position: absolute;
785
- top: 0;
786
- left: 0;
787
- bottom: 0;
788
- right: 0;
789
- }
790
- #sb_instagram.sbi_no_js #sbi_images .sbi_item.sbi_transition {
791
- opacity: 1;
792
- max-height: 640px;
793
- }
794
- #sb_instagram.sbi_no_js .sbi_photo img,
795
- #sb_instagram.sbi_no_js .sbi_load_btn{
796
- display: none;
797
- }
798
- #sb_instagram #sbi_images .sbi_js_load_disabled .sbi_imgLiquid_ready.sbi_photo {
799
- padding-bottom: 0 !important;
800
- }
801
- #sb_instagram #sbi_mod_error .sb_frontend_btn {
802
- display: inline-block;
803
- padding: 6px 10px;
804
- background: #ddd;
805
- background: rgba(0,0,0,.1);
806
- text-decoration: none;
807
- border-radius: 5px;
808
- margin-top: 10px;
809
- color: #444
810
- }
811
-
812
- #sb_instagram #sbi_mod_error .sb_frontend_btn:hover {
813
- background: #ccc;
814
- background: rgba(0,0,0,.15)
815
- }
816
-
817
- #sb_instagram #sbi_mod_error .sb_frontend_btn .fa {
818
- margin-right: 2px
819
  }
1
+ /**************/
2
+ /*** LAYOUT ***/
3
+ /**************/
4
+
5
+ /* Feed container */
6
+ #sb_instagram {
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
+ #sb_instagram:after{
15
+ content: "";
16
+ display: table;
17
+ clear: both;
18
+ }
19
+
20
+ /*********************/
21
+ /*** STYLE OPTIONS ***/
22
+ /*********************/
23
+ #sb_instagram.sbi_fixed_height{
24
+ overflow: hidden;
25
+ overflow-y: auto;
26
+ -webkit-box-sizing: border-box;
27
+ -moz-box-sizing: border-box;
28
+ box-sizing: border-box;
29
+ }
30
+ #sb_instagram #sbi_images{
31
+ width: 100%;
32
+ float: left;
33
+ line-height: 0;
34
+
35
+ -webkit-box-sizing: border-box;
36
+ -moz-box-sizing: border-box;
37
+ box-sizing: border-box;
38
+ }
39
+ /* Remove header shadow/border */
40
+ #sb_instagram .sbi_header_link {
41
+ -webkit-box-shadow: none;
42
+ box-shadow: none;
43
+ }
44
+ #sb_instagram .sbi_header_link:hover {
45
+ border: none;
46
+ }
47
+
48
+ /* Items */
49
+ #sb_instagram #sbi_images .sbi_item{
50
+ display: -moz-inline-stack;
51
+ display: inline-block;
52
+ float: left;
53
+ vertical-align: top;
54
+ zoom: 1;
55
+ *display: inline;
56
+
57
+ max-height: 1000px;
58
+ padding: inherit !important;
59
+ margin: 0 !important;
60
+ text-decoration: none;
61
+ opacity: 1;
62
+ overflow: hidden;
63
+
64
+ -webkit-box-sizing: border-box;
65
+ -moz-box-sizing: border-box;
66
+ box-sizing: border-box;
67
+
68
+ -webkit-transition: all 0.5s ease;
69
+ -moz-transition: all 0.5s ease;
70
+ -o-transition: all 0.5s ease;
71
+ -ms-transition: all 0.5s ease;
72
+ transition: all 0.5s ease;
73
+ }
74
+ /* Transition items in */
75
+ #sb_instagram #sbi_images .sbi_item.sbi_transition{
76
+ opacity: 0;
77
+ max-height: 0;
78
+ }
79
+
80
+ /* Cols */
81
+ #sb_instagram.sbi_col_1 #sbi_images .sbi_item{ width: 100%; }
82
+ #sb_instagram.sbi_col_2 #sbi_images .sbi_item{ width: 50%; }
83
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item{ width: 33.33%; }
84
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item{ width: 25%; }
85
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item{ width: 20%; }
86
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item{ width: 16.66%; }
87
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item{ width: 14.28%; }
88
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item{ width: 12.5%; }
89
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item{ width: 11.11%; }
90
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{ width: 10%; }
91
+
92
+ /* Disable mobile layout */
93
+ #sb_instagram.sbi_col_1.sbi_disable_mobile #sbi_images .sbi_item{ width: 100%; }
94
+ #sb_instagram.sbi_col_2.sbi_disable_mobile #sbi_images .sbi_item{ width: 50%; }
95
+ #sb_instagram.sbi_col_3.sbi_disable_mobile #sbi_images .sbi_item{ width: 33.33%; }
96
+ #sb_instagram.sbi_col_4.sbi_disable_mobile #sbi_images .sbi_item{ width: 25%; }
97
+ #sb_instagram.sbi_col_5.sbi_disable_mobile #sbi_images .sbi_item{ width: 20%; }
98
+ #sb_instagram.sbi_col_6.sbi_disable_mobile #sbi_images .sbi_item{ width: 16.66%; }
99
+ #sb_instagram.sbi_col_7.sbi_disable_mobile #sbi_images .sbi_item{ width: 14.28%; }
100
+ #sb_instagram.sbi_col_8.sbi_disable_mobile #sbi_images .sbi_item{ width: 12.5%; }
101
+ #sb_instagram.sbi_col_9.sbi_disable_mobile #sbi_images .sbi_item{ width: 11.11%; }
102
+ #sb_instagram.sbi_col_10.sbi_disable_mobile #sbi_images .sbi_item{ width: 10%; }
103
+
104
+ /* Photos */
105
+ #sb_instagram .sbi_photo_wrap{
106
+ position: relative;
107
+ }
108
+ #sb_instagram .sbi_photo{
109
+ display: block;
110
+ text-decoration: none;
111
+ }
112
+ #sb_instagram .sbi_photo img{
113
+ width: 100%;
114
+ height: auto;
115
+ }
116
+ #sb_instagram .sbi_no_js img{
117
+ display: none;
118
+ }
119
+ #sb_instagram a,
120
+ #sb_instagram a:hover,
121
+ #sb_instagram a:focus,
122
+ #sb_instagram a:active{
123
+ outline: none;
124
+ }
125
+ #sb_instagram img{
126
+ display: block;
127
+ padding: 0 !important;
128
+ margin: 0 !important;
129
+ max-width: 100% !important;
130
+ opacity: 1 !important;
131
+ }
132
+ #sb_instagram .sbi_link{
133
+ display: none;
134
+ position: absolute;
135
+ bottom: 0;
136
+ right: 0;
137
+
138
+ width: 100%;
139
+ padding: 10px 0;
140
+ background: rgba(0,0,0,0.5);
141
+ text-align: center;
142
+ color: #fff;
143
+ font-size: 12px;
144
+ line-height: 1.1;
145
+ }
146
+ #sb_instagram .sbi_link a{
147
+ padding: 0 6px;
148
+ text-decoration: none;
149
+ color: #fff;
150
+ font-size: 12px;
151
+ line-height: 1.1;
152
+
153
+ display: -moz-inline-stack;
154
+ display: inline-block;
155
+ vertical-align: top;
156
+ zoom: 1;
157
+ *display: inline;
158
+ }
159
+ #sb_instagram .sbi_link .sbi_lightbox_link{
160
+ padding-bottom: 5px;
161
+ }
162
+ #sb_instagram .sbi_link a:hover,
163
+ #sb_instagram .sbi_link a:focus{
164
+ text-decoration: underline;
165
+ }
166
+ #sb_instagram .sbi_photo_wrap:hover .sbi_link,
167
+ #sb_instagram .sbi_photo_wrap:focus .sbi_link{
168
+ display: block;
169
+ }
170
+
171
+ /* Videos */
172
+ #sb_instagram svg:not(:root).svg-inline--fa {
173
+ height: 1em;
174
+ display: inline-block;
175
+ }
176
+
177
+ #sb_instagram .sbi_type_video .sbi_playbtn,
178
+ #sb_instagram .sbi_type_carousel .sbi_playbtn,
179
+ .sbi_type_carousel .fa-clone,
180
+ #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play,
181
+ #sb_instagram .sbi_type_video .svg-inline--fa.fa-play{
182
+ display: block !important;
183
+ position: absolute;
184
+ z-index: 1;
185
+
186
+ color: #fff;
187
+ color: rgba(255,255,255,0.9);
188
+ font-style: normal !important;
189
+ text-shadow: 0 0 8px rgba(0,0,0,0.8);
190
+ }
191
+ #sb_instagram .sbi_type_video .sbi_playbtn,
192
+ #sb_instagram .sbi_type_carousel .sbi_playbtn {
193
+ z-index: 2;
194
+ top: 50%;
195
+ left: 50%;
196
+ margin-top: -24px;
197
+ margin-left: -19px;
198
+ padding: 0;
199
+ font-size: 48px;
200
+ }
201
+ #sb_instagram .sbi_type_carousel .fa-clone{
202
+ right: 12px;
203
+ top: 12px;
204
+ font-size: 24px;
205
+ text-shadow: 0 0 8px rgba(0,0,0,0.3);
206
+ }
207
+ .sbi_type_carousel svg.fa-clone,
208
+ #sb_instagram .sbi_type_video .svg-inline--fa.fa-play,
209
+ #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play{
210
+ -webkit-filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
211
+ filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
212
+ }
213
+
214
+ /* Loader */
215
+ #sb_instagram .sbi_loader{
216
+ width: 20px;
217
+ height: 20px;
218
+
219
+ position: relative;
220
+ top: 50%;
221
+ left: 50%;
222
+ margin: -10px 0 0 -10px;
223
+ background-color: #000;
224
+ background-color: rgba(0,0,0,0.5);
225
+
226
+ border-radius: 100%;
227
+ -webkit-animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
228
+ animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
229
+ }
230
+ #sb_instagram br {
231
+ display: none;
232
+ }
233
+ #sbi_load p {
234
+ display: inline;
235
+ padding: 0;
236
+ margin: 0;
237
+ }
238
+ /* Loader in button */
239
+ #sb_instagram #sbi_load .sbi_loader{
240
+ position: absolute;
241
+ margin-top: -11px;
242
+ background-color: #fff;
243
+ opacity: 1;
244
+ }
245
+ @-webkit-keyframes sbi-sk-scaleout {
246
+ 0% { -webkit-transform: scale(0) }
247
+ 100% {
248
+ -webkit-transform: scale(1.0);
249
+ opacity: 0;
250
+ }
251
+ }
252
+ @keyframes sbi-sk-scaleout {
253
+ 0% {
254
+ -webkit-transform: scale(0);
255
+ -ms-transform: scale(0);
256
+ transform: scale(0);
257
+ } 100% {
258
+ -webkit-transform: scale(1.0);
259
+ -ms-transform: scale(1.0);
260
+ transform: scale(1.0);
261
+ opacity: 0;
262
+ }
263
+ }
264
+
265
+ #sb_instagram .fa-spin,
266
+ #sbi_lightbox .fa-spin{
267
+ -webkit-animation: fa-spin 2s infinite linear;
268
+ animation: fa-spin 2s infinite linear
269
+ }
270
+
271
+ #sb_instagram .fa-pulse,
272
+ #sbi_lightbox .fa-pulse{
273
+ -webkit-animation: fa-spin 1s infinite steps(8);
274
+ animation: fa-spin 1s infinite steps(8)
275
+ }
276
+
277
+ @-webkit-keyframes fa-spin {
278
+ 0% {
279
+ -webkit-transform: rotate(0deg);
280
+ transform: rotate(0deg)
281
+ }
282
+ 100% {
283
+ -webkit-transform: rotate(359deg);
284
+ transform: rotate(359deg)
285
+ }
286
+ }
287
+
288
+ @keyframes fa-spin {
289
+ 0% {
290
+ -webkit-transform: rotate(0deg);
291
+ transform: rotate(0deg)
292
+ }
293
+ 100% {
294
+ -webkit-transform: rotate(359deg);
295
+ transform: rotate(359deg)
296
+ }
297
+ }
298
+ /* Screen reader */
299
+ .sbi-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;text-align: left !important; }
300
+
301
+ /* HEADER */
302
+ #sb_instagram .sb_instagram_header{
303
+ float: left;
304
+ clear: both;
305
+ margin: 0 0 15px 0;
306
+ padding: 0;
307
+ line-height: 1.2;
308
+ width: 100%;
309
+ }
310
+ #sb_instagram .sb_instagram_header a{
311
+ float: left;
312
+ display: block;
313
+ /*width: 100%;*/
314
+ min-width: 100%\9;
315
+ text-decoration: none;
316
+ transition: color 0.5s ease;
317
+ }
318
+ .sbi_no_avatar .sbi_header_img{
319
+ background: #333;
320
+ color: #fff;
321
+ width: 50px;
322
+ height: 50px;
323
+ position: relative;
324
+ }
325
+ .sbi_no_avatar .sbi_header_hashtag_icon {
326
+ display: block;
327
+ color: #fff;
328
+ opacity: .9;
329
+ -webkit-transition: background .6s linear,color .6s linear;
330
+ -moz-transition: background .6s linear,color .6s linear;
331
+ -ms-transition: background .6s linear,color .6s linear;
332
+ -o-transition: background .6s linear,color .6s linear;
333
+ transition: background .6s linear,color .6s linear
334
+ }
335
+
336
+ .sbi_no_avatar:hover .sbi_header_hashtag_icon {
337
+ display: block;
338
+ opacity: 1;
339
+ -webkit-transition: background .2s linear,color .2s linear;
340
+ -moz-transition: background .2s linear,color .2s linear;
341
+ -ms-transition: background .2s linear,color .2s linear;
342
+ -o-transition: background .2s linear,color .2s linear;
343
+ transition: background .2s linear,color .2s linear
344
+ }
345
+ /** Medium Header */
346
+ /* Only use medium & large headers on devices above 480px */
347
+ @media all and (min-width: 480px){
348
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img {
349
+ width: 80px;
350
+ height: 80px;
351
+ border-radius: 40px;
352
+ }
353
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img img {
354
+ width: 80px;
355
+ height: 80px;
356
+ border-radius: 40px;
357
+ }
358
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3 {
359
+ font-size: 20px;
360
+ }
361
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
362
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
363
+ font-size: 14px;
364
+ }
365
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3,
366
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
367
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
368
+ margin-left: 95px !important;
369
+ line-height: 1.4
370
+ }
371
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3{
372
+ margin-right: -85px !important;
373
+ }
374
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info{
375
+ margin-top: 4px !important;
376
+ }
377
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text.sbi_no_bio h3{
378
+ padding-top: 20px !important;
379
+ }
380
+ /** Large Header */
381
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img {
382
+ width: 120px;
383
+ height: 120px;
384
+ border-radius: 60px;
385
+ }
386
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img img {
387
+ width: 120px;
388
+ height: 120px;
389
+ border-radius: 60px;
390
+ }
391
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3 {
392
+ font-size: 28px;
393
+ }
394
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
395
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
396
+ font-size: 16px;
397
+ }
398
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3,
399
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
400
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
401
+ margin-left: 140px !important;
402
+ line-height: 1.5;
403
+ }
404
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3{
405
+ margin-right: -120px !important;
406
+ }
407
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info{
408
+ margin-top: 12px !important;
409
+ }
410
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text.sbi_no_bio h3{
411
+ padding-top: 32px !important;
412
+ }
413
+ }
414
+
415
+ /* Header profile pic */
416
+ #sb_instagram .sb_instagram_header .sbi_header_img{
417
+ float: left;
418
+ position: relative;
419
+ width: 50px;
420
+ margin: 0 0 0 -100% !important;
421
+ overflow: hidden;
422
+
423
+ -moz-border-radius: 40px;
424
+ -webkit-border-radius: 40px;
425
+ border-radius: 40px;
426
+ }
427
+ #sb_instagram .sb_instagram_header .sbi_header_img img{
428
+ float: left;
429
+ margin: 0 !important;
430
+ padding: 0 !important;
431
+ border: none !important;
432
+
433
+ -moz-border-radius: 40px;
434
+ -webkit-border-radius: 40px;
435
+ border-radius: 40px;
436
+ }
437
+ /* Profile pic hover */
438
+ /* Profile pic hover */
439
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
440
+ opacity: 0;
441
+ position: absolute;
442
+ width: 100%;
443
+ top: 0;
444
+ bottom: 0;
445
+ left: 0;
446
+ text-align: center;
447
+ color: #fff;
448
+ background: rgba(0,0,0,0.75);
449
+ }
450
+
451
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover .sbi_new_logo,
452
+ #sb_instagram .sb_instagram_header .sbi_header_hashtag_icon .sbi_new_logo{
453
+ position: absolute;
454
+ top: 50%;
455
+ left: 50%;
456
+ margin-top: -12px;
457
+ margin-left: -12px;
458
+ width: 24px;
459
+ height: 24px;
460
+ font-size: 24px;
461
+ }
462
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo,
463
+ .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo{
464
+ margin-top: -18px;
465
+ margin-left: -18px;
466
+ width: 36px;
467
+ height: 36px;
468
+ font-size: 36px
469
+ }
470
+
471
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo,
472
+ .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo {
473
+ margin-top: -24px;
474
+ margin-left: -24px;
475
+ width: 48px;
476
+ height: 48px;
477
+ font-size: 48px
478
+ }
479
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover i {
480
+ overflow: hidden;
481
+ background: url('../img/small-logo.png') no-repeat 0 0;
482
+ }
483
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
484
+ z-index: 2;
485
+ transition: opacity 0.4s ease-in-out;
486
+ }
487
+ #sb_instagram .sb_instagram_header .sbi_fade_in{
488
+ opacity: 1;
489
+ transition: opacity 0.2s ease-in-out;
490
+ }
491
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
492
+ position: absolute;
493
+ width: 100%;
494
+ top: 0;
495
+ bottom: 0;
496
+ left: 0;
497
+ text-align: center;
498
+ color: #fff;
499
+ background: rgba(0,0,0,0.75);
500
+
501
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
502
+ filter: alpha(opacity=0);
503
+ -moz-opacity: 0;
504
+ -khtml-opacity: 0;
505
+ opacity: 0;
506
+ border-radius: 40px;
507
+ transition: opacity 0.2s;
508
+ }
509
+ /* Fade the Instagram icon in when hovering on the header */
510
+ #sb_instagram .sb_instagram_header a:hover .sbi_header_img_hover,
511
+ #sb_instagram .sb_instagram_header a:focus .sbi_header_img_hover{
512
+ opacity: 1;
513
+ }
514
+ /* Header text */
515
+ #sb_instagram .sb_instagram_header .sbi_header_text{
516
+ float: left;
517
+ width: 100%;
518
+ padding-top: 5px;
519
+ }
520
+ #sb_instagram .sb_instagram_header a{
521
+ text-decoration: none;
522
+ }
523
+ #sb_instagram .sb_instagram_header .sbi_header_text .sbi_bio,
524
+ #sb_instagram .sb_instagram_header .sbi_header_text h3{
525
+ float: left;
526
+ clear: both;
527
+ width: auto;
528
+ margin: 0 0 0 60px !important;
529
+ padding: 0 !important;
530
+ }
531
+ #sb_instagram .sb_instagram_header h3{
532
+ font-size: 16px;
533
+ line-height: 1.3;
534
+ }
535
+ #sb_instagram .sb_instagram_header p{
536
+ font-size: 13px;
537
+ line-height: 1.3;
538
+ margin: 0;
539
+ padding: 0;
540
+ }
541
+ #sb_instagram p:empty { display: none; }
542
+ #sb_instagram .sb_instagram_header .sbi_header_text img.emoji{
543
+ margin-right: 3px !important;
544
+ }
545
+
546
+ /* No bio */
547
+ #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio h3{
548
+ padding-top: 9px !important;
549
+ }
550
+ #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio .sbi_bio_info{
551
+ clear: both;
552
+ }
553
+
554
+
555
+ /* Buttons */
556
+ #sb_instagram #sbi_load{
557
+ float: left;
558
+ clear: both;
559
+ width: 100%;
560
+ text-align: center;
561
+ }
562
+ #sb_instagram #sbi_load .fa-spinner{
563
+ display: none;
564
+ position: absolute;
565
+ top: 50%;
566
+ left: 50%;
567
+ margin: -8px 0 0 -7px;
568
+ font-size: 15px;
569
+ }
570
+ #sb_instagram #sbi_load{
571
+ opacity: 1;
572
+ transition: all 0.5s ease-in;
573
+ }
574
+ #sb_instagram .sbi_load_btn .sbi_btn_text, #sb_instagram .sbi_load_btn .sbi_loader{
575
+ opacity: 1;
576
+ transition: all 0.1s ease-in;
577
+ }
578
+ #sb_instagram .sbi_hidden{
579
+ opacity: 0 !important;
580
+ }
581
+ #sb_instagram #sbi_load .sbi_load_btn,
582
+ #sb_instagram .sbi_follow_btn a{
583
+ display: -moz-inline-stack;
584
+ display: inline-block;
585
+ vertical-align: top;
586
+ zoom: 1;
587
+ *display: inline;
588
+
589
+ padding: 7px 14px;
590
+ margin: 5px auto 0 auto;
591
+ background: #333;
592
+ color: #eee;
593
+ border: none;
594
+ color: #fff;
595
+ text-decoration: none;
596
+ font-size: 13px;
597
+ line-height: 1.5;
598
+
599
+ -moz-border-radius: 4px;
600
+ -webkit-border-radius: 4px;
601
+ border-radius: 4px;
602
+
603
+ -webkit-box-sizing: border-box;
604
+ -moz-box-sizing: border-box;
605
+ box-sizing: border-box;
606
+ }
607
+ #sb_instagram #sbi_load .sbi_load_btn {
608
+ position: relative;
609
+ }
610
+ /* Follow button */
611
+ #sb_instagram .sbi_follow_btn{
612
+ display: -moz-inline-stack;
613
+ display: inline-block;
614
+ vertical-align: top;
615
+ zoom: 1;
616
+ *display: inline;
617
+ text-align: center;
618
+ }
619
+ #sb_instagram .sbi_follow_btn.sbi_top{
620
+ display: block;
621
+ margin-bottom: 5px;
622
+ }
623
+ #sb_instagram .sbi_follow_btn a{
624
+ background: #408bd1;
625
+ color: #fff;
626
+ }
627
+ #sb_instagram .sbi_follow_btn a,
628
+ #sb_instagram .sbi_follow_btn a,
629
+ #sb_instagram #sbi_load .sbi_load_btn{
630
+ transition: all 0.1s ease-in;
631
+ }
632
+ /* Hover state for default colors */
633
+ #sb_instagram #sbi_load .sbi_load_btn:hover{
634
+ outline: none;
635
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
636
+ }
637
+ #sb_instagram .sbi_follow_btn a:hover,
638
+ #sb_instagram .sbi_follow_btn a:focus{
639
+ outline: none;
640
+ box-shadow: inset 0 0 10px 20px #359dff;
641
+ }
642
+ /* If a custom color is applied then just use opacity for the hover effect */
643
+ #sb_instagram .sbi_follow_btn.sbi_custom a:hover,
644
+ #sb_instagram .sbi_follow_btn.sbi_custom a:focus,
645
+ #sb_instagram #sbi_load .sbi_load_btn.sbi_custom:hover{
646
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
647
+ }
648
+ /* Active state */
649
+ #sb_instagram .sbi_follow_btn a:active,
650
+ #sb_instagram #sbi_load .sbi_load_btn:active{
651
+ box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
652
+ }
653
+
654
+ #sb_instagram .sbi_follow_btn .fa,
655
+ #sb_instagram .sbi_follow_btn svg{
656
+ margin-bottom: -1px;
657
+ margin-right: 7px;
658
+ font-size: 15px;
659
+ }
660
+ #sb_instagram .sbi_follow_btn svg{
661
+ vertical-align: -.125em;
662
+ }
663
+ #sb_instagram #sbi_load .sbi_follow_btn{
664
+ margin-left: 5px;
665
+ }
666
+
667
+ /* Error messages */
668
+ #sb_instagram .sb_instagram_error{
669
+ width: 100%;
670
+ text-align: center;
671
+ line-height: 1.4;
672
+ }
673
+
674
+ /* Mod only error msgs */
675
+ #sbi_mod_error{
676
+ display: none;
677
+ border: 1px solid #ddd;
678
+ background: #eee;
679
+ color: #333;
680
+ margin: 10px 0 0;
681
+ padding: 10px 15px;
682
+ font-size: 13px;
683
+ text-align: center;
684
+ clear: both;
685
+
686
+ -moz-border-radius: 4px;
687
+ -webkit-border-radius: 4px;
688
+ border-radius: 4px;
689
+ }
690
+ #sbi_mod_error br {
691
+ display: initial !important;
692
+ }
693
+ #sbi_mod_error p{
694
+ padding: 5px 0 !important;
695
+ margin: 0 !important;
696
+ line-height: 1.3 !important;
697
+ }
698
+ #sbi_mod_error ol,
699
+ #sbi_mod_error ul{
700
+ padding: 5px 0 5px 20px !important;
701
+ margin: 0 !important;
702
+ }
703
+ #sbi_mod_error li{
704
+ padding: 1px 0 !important;
705
+ margin: 0 !important;
706
+ }
707
+ #sbi_mod_error span{
708
+ font-size: 12px;
709
+ }
710
+
711
+ /* Medium */
712
+ #sb_instagram.sbi_medium .sbi_playbtn,
713
+ #sb_instagram.sbi_medium .sbi_photo_wrap .svg-inline--fa.fa-play{
714
+ margin-top: -12px;
715
+ margin-left: -9px;
716
+ font-size: 23px;
717
+ }
718
+ #sb_instagram.sbi_medium .sbi_type_carousel .sbi_photo_wrap .fa-clone{
719
+ right: 8px;
720
+ top: 8px;
721
+ font-size: 18px;
722
+ }
723
+ /* Small */
724
+ #sb_instagram.sbi_small .sbi_playbtn,
725
+ #sb_instagram.sbi_small .sbi_photo_wrap .svg-inline--fa.fa-play{
726
+ margin-top: -9px;
727
+ margin-left: -7px;
728
+ font-size: 18px;
729
+ }
730
+ #sb_instagram.sbi_small .sbi_type_carousel .sbi_photo_wrap .fa-clone{
731
+ right: 5px;
732
+ top: 5px;
733
+ font-size: 12px;
734
+ }
735
+
736
+ /* Media queries */
737
+ @media all and (max-width: 640px){
738
+ /* Make 3-6 cols into 2 col */
739
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
740
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
741
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
742
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item{
743
+ width: 50%;
744
+ }
745
+ /* Make 7-10 cols into 4 col */
746
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
747
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
748
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
749
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
750
+ width: 25%;
751
+ }
752
+ /* On mobile make the min-width 100% */
753
+ #sb_instagram.sbi_width_resp{
754
+ width: 100% !important;
755
+ }
756
+ }
757
+ @media all and (max-width: 480px){
758
+ /* Make all cols into 1 col */
759
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
760
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
761
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
762
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item,
763
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
764
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
765
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
766
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
767
+ width: 100%;
768
+ }
769
+ }
770
+
771
+ /* NO JS */
772
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap{
773
+ box-sizing: border-box;
774
+ position: relative;
775
+ overflow: hidden;
776
+ }
777
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap:before {
778
+ content: "";
779
+ display: block;
780
+ padding-top: 100%;
781
+ z-index: -300;
782
+ }
783
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo {
784
+ position: absolute;
785
+ top: 0;
786
+ left: 0;
787
+ bottom: 0;
788
+ right: 0;
789
+ }
790
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item.sbi_transition {
791
+ opacity: 1;
792
+ max-height: 640px;
793
+ }
794
+ #sb_instagram.sbi_no_js .sbi_photo img,
795
+ #sb_instagram.sbi_no_js .sbi_load_btn{
796
+ display: none;
797
+ }
798
+ #sb_instagram #sbi_images .sbi_js_load_disabled .sbi_imgLiquid_ready.sbi_photo {
799
+ padding-bottom: 0 !important;
800
+ }
801
+ #sb_instagram #sbi_mod_error .sb_frontend_btn {
802
+ display: inline-block;
803
+ padding: 6px 10px;
804
+ background: #ddd;
805
+ background: rgba(0,0,0,.1);
806
+ text-decoration: none;
807
+ border-radius: 5px;
808
+ margin-top: 10px;
809
+ color: #444
810
+ }
811
+
812
+ #sb_instagram #sbi_mod_error .sb_frontend_btn:hover {
813
+ background: #ccc;
814
+ background: rgba(0,0,0,.15)
815
+ }
816
+
817
+ #sb_instagram #sbi_mod_error .sb_frontend_btn .fa {
818
+ margin-right: 2px
819
  }
css/sb-instagram-admin.css CHANGED
@@ -102,7 +102,8 @@
102
  font-size: 12px;
103
  font-style: italic;
104
  }
105
- #sbi_admin .sbi_note{
 
106
  margin-left: 10px;
107
  }
108
  #sbi_admin table.sbi_shortcode_table{
@@ -376,6 +377,13 @@
376
  -webkit-border-radius: 3px;
377
  border-radius: 3px;
378
  }
 
 
 
 
 
 
 
379
  .sb_instagram_notice .sb_instagram_notice_title{
380
  font-size: 18px;
381
  padding-bottom: 5px;
@@ -1526,4 +1534,714 @@
1526
  text-align: center;
1527
  width: 20px;
1528
  -webkit-font-smoothing: antialiased
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1529
  }
102
  font-size: 12px;
103
  font-style: italic;
104
  }
105
+ #sbi_admin .sbi_note,
106
+ #sbi_admin .sbi-space-left{
107
  margin-left: 10px;
108
  }
109
  #sbi_admin table.sbi_shortcode_table{
377
  -webkit-border-radius: 3px;
378
  border-radius: 3px;
379
  }
380
+ #sbi_admin .sbi-goto {
381
+ border: 1px solid #e89a2e;
382
+ background-color: rgba(232, 154, 46, .2);
383
+ }
384
+ #sbi_admin .sbi-goto th {
385
+ padding-left: 4px;
386
+ }
387
  .sb_instagram_notice .sb_instagram_notice_title{
388
  font-size: 18px;
389
  padding-bottom: 5px;
1534
  text-align: center;
1535
  width: 20px;
1536
  -webkit-font-smoothing: antialiased
1537
+ }
1538
+
1539
+ /* About */
1540
+ #sbi-admin-about *,#sbi-admin-about *::before,#sbi-admin-about *::after {
1541
+ -webkit-box-sizing: border-box;
1542
+ -moz-box-sizing: border-box;
1543
+ box-sizing: border-box
1544
+ }
1545
+
1546
+ #sbi-admin-about .sbi-admin-about-section {
1547
+ position: relative;
1548
+ margin: 0 20px 20px;
1549
+ padding: 30px;
1550
+ background: #fff;
1551
+ border: 1px solid #DDDDDD;
1552
+ line-height: 2;
1553
+ }
1554
+
1555
+ #sbi-admin-about .sbi-admin-about-section h1,#sbi-admin-about .sbi-admin-about-section h2,#sbi-admin-about .sbi-admin-about-section h3,#sbi-admin-about .sbi-admin-about-section h4,#sbi-admin-about .sbi-admin-about-section h5 {
1556
+ margin-top: 0;
1557
+ padding-top: 0;
1558
+ line-height: 1.6
1559
+ }
1560
+
1561
+ #sbi-admin-about .sbi-admin-about-section h2 {
1562
+ font-size: 24px
1563
+ }
1564
+
1565
+ #sbi-admin-about .sbi-admin-about-section h3 {
1566
+ font-size: 18px;
1567
+ margin-bottom: 30px;
1568
+ color: #23282C
1569
+ }
1570
+
1571
+ #sbi-admin-about .sbi-admin-about-section ul,#sbi-admin-about .sbi-admin-about-section p {
1572
+ font-size: 16px
1573
+ }
1574
+
1575
+ #sbi-admin-about .sbi-admin-about-section p {
1576
+ margin-bottom: 20px
1577
+ }
1578
+
1579
+ #sbi-admin-about .sbi-admin-about-section p.bigger {
1580
+ font-size: 18px
1581
+ }
1582
+
1583
+ #sbi-admin-about .sbi-admin-about-section p.smaller {
1584
+ font-size: 14px
1585
+ }
1586
+
1587
+ #sbi-admin-about .sbi-admin-about-section p:last-child {
1588
+ margin-bottom: 0
1589
+ }
1590
+
1591
+ #sbi-admin-about .sbi-admin-about-section hr {
1592
+ margin: 30px 0
1593
+ }
1594
+
1595
+ #sbi-admin-about .sbi-admin-about-section figure {
1596
+ margin: 0
1597
+ }
1598
+
1599
+ #sbi-admin-about .sbi-admin-about-section figure img {
1600
+ width: 100%
1601
+ }
1602
+
1603
+ #sbi-admin-about .sbi-admin-about-section figure figcaption {
1604
+ font-size: 13px;
1605
+ color: #888888;
1606
+ margin-top: -10px;
1607
+ text-align: center;
1608
+ line-height: initial
1609
+ }
1610
+
1611
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-column-40 {
1612
+ padding-left: 15px
1613
+ }
1614
+
1615
+ @media (max-width: 767px) {
1616
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-column-40 {
1617
+ width:100%;
1618
+ padding-left: 0;
1619
+ padding-top: 20px
1620
+ }
1621
+ }
1622
+
1623
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-column-60 {
1624
+ padding-right: 15px
1625
+ }
1626
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-about-text{
1627
+ padding-right: 400px;
1628
+ }
1629
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-about-image{
1630
+ position: absolute;
1631
+ width: 340px;
1632
+ top: 20px;
1633
+ right: 20px;
1634
+ }
1635
+
1636
+ @media (max-width: 767px) {
1637
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-column-60,
1638
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-about-text,
1639
+ #sbi-admin-about .sbi-admin-about-section .sbi-admin-about-image {
1640
+ position: relative;
1641
+ width:100%;
1642
+ padding-right: 0
1643
+ }
1644
+ }
1645
+
1646
+ #sbi-admin-about .sbi-admin-about-section ul.list-plain {
1647
+ margin-top: 0;
1648
+ margin-bottom: 0
1649
+ }
1650
+
1651
+ #sbi-admin-about .sbi-admin-about-section ul.list-plain li {
1652
+ margin-bottom: 0
1653
+ }
1654
+
1655
+ #sbi-admin-about .sbi-admin-about-section ul.list-features li .fa {
1656
+ color: #2a9b39;
1657
+ margin: 0 8px 0 0
1658
+ }
1659
+
1660
+ #sbi-admin-about .sbi-admin-about-section .fa-star {
1661
+ color: gold
1662
+ }
1663
+
1664
+ #sbi-admin-about .sbi-admin-about-section .no-margin {
1665
+ margin: 0 !important
1666
+ }
1667
+
1668
+ #sbi-admin-about .sbi-admin-about-section .no-padding {
1669
+ padding: 0 !important
1670
+ }
1671
+
1672
+ #sbi-admin-about .sbi-admin-about-section .centered {
1673
+ text-align: center !important
1674
+ }
1675
+
1676
+ #sbi-admin-about .sbi-admin-about-section-first-form {
1677
+ display: flex
1678
+ }
1679
+
1680
+ @media (max-width: 767px) {
1681
+ #sbi-admin-about .sbi-admin-about-section-first-form {
1682
+ display:block !important
1683
+ }
1684
+ }
1685
+
1686
+ #sbi-admin-about .sbi-admin-about-section-first-form .sbi-admin-about-section-first-form-text {
1687
+ flex: 1;
1688
+ padding-right: 30px
1689
+ }
1690
+
1691
+ @media (max-width: 767px) {
1692
+ #sbi-admin-about .sbi-admin-about-section-first-form .sbi-admin-about-section-first-form-text {
1693
+ flex:none
1694
+ }
1695
+ }
1696
+
1697
+ #sbi-admin-about .sbi-admin-about-section-first-form .sbi-admin-about-section-first-form-video iframe {
1698
+ border: 1px solid #DDDDDD
1699
+ }
1700
+
1701
+ @media (max-width: 767px) {
1702
+ #sbi-admin-about .sbi-admin-about-section-first-form .sbi-admin-about-section-first-form-video {
1703
+ padding-top:20px
1704
+ }
1705
+ }
1706
+
1707
+ #sbi-admin-about .sbi-admin-about-section-hero {
1708
+ padding: 0
1709
+ }
1710
+
1711
+ #sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-main,#sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-extra {
1712
+ padding: 30px
1713
+ }
1714
+
1715
+ @media (max-width: 767px) {
1716
+ #sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-extra .sbi-admin-column-50 {
1717
+ float:none;
1718
+ width: 100%
1719
+ }
1720
+ }
1721
+
1722
+ #sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-main {
1723
+ background-color: #FAFAFA;
1724
+ border-bottom: 1px solid #DDDDDD
1725
+ }
1726
+
1727
+ #sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-main.no-border {
1728
+ border-bottom: 0
1729
+ }
1730
+
1731
+ #sbi-admin-about .sbi-admin-about-section-hero .sbi-admin-about-section-hero-main p {
1732
+ color: #666
1733
+ }
1734
+
1735
+ #sbi-admin-about .sbi-admin-about-section-hero h3.call-to-action {
1736
+ margin-bottom: -10px
1737
+ }
1738
+
1739
+ #sbi-admin-about .sbi-admin-about-section-hero span.price-20-off {
1740
+ color: #6AB255
1741
+ }
1742
+
1743
+ #sbi-admin-about .sbi-admin-about-section-squashed {
1744
+ margin-bottom: 0
1745
+ }
1746
+
1747
+ #sbi-admin-about .sbi-admin-about-section-squashed:not(:last-of-type) {
1748
+ border-bottom: 0
1749
+ }
1750
+
1751
+ #sbi-admin-about .sbi-admin-about-section-post h2 {
1752
+ margin-bottom: -10px
1753
+ }
1754
+
1755
+ #sbi-admin-about .sbi-admin-about-section-post h3 {
1756
+ margin-bottom: 15px
1757
+ }
1758
+
1759
+ #sbi-admin-about .sbi-admin-about-section-post p:last-of-type {
1760
+ margin-bottom: 30px
1761
+ }
1762
+
1763
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-20 {
1764
+ padding-right: 20px;
1765
+ width: auto
1766
+ }
1767
+
1768
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-20 img {
1769
+ width: 270px
1770
+ }
1771
+
1772
+ @media (max-width: 767px) {
1773
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-20 {
1774
+ width:20%
1775
+ }
1776
+
1777
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-20 img {
1778
+ width: auto;
1779
+ max-width: 100%
1780
+ }
1781
+ }
1782
+
1783
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-80 {
1784
+ padding-left: 20px;
1785
+ width: calc(100% - 20px - 270px)
1786
+ }
1787
+
1788
+ @media (max-width: 767px) {
1789
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-column-80 {
1790
+ width:80%
1791
+ }
1792
+ }
1793
+
1794
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-about-section-post-link {
1795
+ padding: 10px 15px;
1796
+ background-color: #DF7739;
1797
+ color: #fff;
1798
+ border-radius: 3px;
1799
+ text-decoration: none;
1800
+ margin-top: 15px;
1801
+ font-size: 14px
1802
+ }
1803
+
1804
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-about-section-post-link:hover {
1805
+ background-color: #B85A1B
1806
+ }
1807
+
1808
+ #sbi-admin-about .sbi-admin-about-section-post .sbi-admin-about-section-post-link .fa {
1809
+ color: #EDBA9E;
1810
+ vertical-align: middle;
1811
+ margin-left: 8px
1812
+ }
1813
+
1814
+ #sbi-admin-about .sbi-admin-about-section-table table {
1815
+ border-collapse: collapse
1816
+ }
1817
+
1818
+ #sbi-admin-about .sbi-admin-about-section-table table tr td {
1819
+ border-bottom: 1px solid #DDDDDD;
1820
+ border-right: 1px solid #DDDDDD;
1821
+ padding: 30px;
1822
+ vertical-align: top
1823
+ }
1824
+
1825
+ #sbi-admin-about .sbi-admin-about-section-table table tr td:last-of-type {
1826
+ border-right: 0
1827
+ }
1828
+
1829
+ #sbi-admin-about .sbi-admin-about-section-table table tr:last-child td {
1830
+ border-bottom: none
1831
+ }
1832
+
1833
+ #sbi-admin-about .sbi-admin-about-section-table table p {
1834
+ background-repeat: no-repeat;
1835
+ background-size: 15px auto;
1836
+ background-position: 0 6px;
1837
+ margin: 0
1838
+ }
1839
+
1840
+ #sbi-admin-about .sbi-admin-about-section-table table p.features-full {
1841
+ padding-left: 30px;
1842
+ background-image: url(../img/about/icon-full.svg)
1843
+ }
1844
+
1845
+ #sbi-admin-about .sbi-admin-about-section-table table p.features-none {
1846
+ padding-left: 30px;
1847
+ background-image: url(../img/about/icon-none.svg)
1848
+ }
1849
+
1850
+ #sbi-admin-about .sbi-admin-about-section-table table p.features-partial {
1851
+ padding-left: 30px;
1852
+ background-position: -3px 0;
1853
+ background-size: 23px auto;
1854
+ background-image: url(../img/about/icon-partial.svg)
1855
+ }
1856
+
1857
+ #sbi-admin-about .sbi-admin-about-section-table .sbi-admin-about-section-hero-main {
1858
+ padding: 0
1859
+ }
1860
+
1861
+ #sbi-admin-about .sbi-admin-about-section-table .sbi-admin-about-section-hero-main h3 {
1862
+ padding: 30px 30px 30px 60px
1863
+ }
1864
+
1865
+ #sbi-admin-about .sbi-admin-about-section-table .sbi-admin-about-section-hero-main .sbi-admin-column-33:first-child h3 {
1866
+ padding: 30px
1867
+ }
1868
+
1869
+ #sbi-admin-about #sbi-admin-addons {
1870
+ padding: 0 30px
1871
+ }
1872
+
1873
+ #sbi-admin-about #sbi-admin-addons .addon-container {
1874
+ padding: 0 10px
1875
+ }
1876
+
1877
+ #sbi-admin-about #sbi-admin-addons .addon-item .details {
1878
+ padding: 20px
1879
+ }
1880
+
1881
+ #sbi-admin-about #sbi-admin-addons .addon-item img {
1882
+ padding: 10px
1883
+ }
1884
+
1885
+ #sbi-admin-about #sbi-admin-addons .addon-item img[src*="-mi"] {
1886
+ padding: 13px
1887
+ }
1888
+
1889
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button {
1890
+ display: inline-block;
1891
+ text-decoration: none;
1892
+ font-size: 13px;
1893
+ line-height: 26px;
1894
+ height: 28px;
1895
+ margin: 0;
1896
+ padding: 0 10px 1px;
1897
+ cursor: pointer;
1898
+ -webkit-appearance: none;
1899
+ border-radius: 3px;
1900
+ border: 1px solid #cccccc;
1901
+ background: #f7f7f7;
1902
+ box-shadow: 0 1px 0 #cccccc;
1903
+ font-weight: normal
1904
+ }
1905
+
1906
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button:hover,#sbi-admin-about #sbi-admin-addons .addon-item .action-button .button:focus {
1907
+ background: #fafafa;
1908
+ border-color: #999;
1909
+ color: #23282d
1910
+ }
1911
+
1912
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-primary {
1913
+ background: #0085ba;
1914
+ border-color: #0073aa #006799 #006799;
1915
+ box-shadow: 0 1px 0 #006799;
1916
+ color: #fff;
1917
+ text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799
1918
+ }
1919
+
1920
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-primary:hover,#sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-primary:focus {
1921
+ background: #008ec2;
1922
+ border-color: #006799;
1923
+ color: #fff
1924
+ }
1925
+
1926
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-primary .fa-spinner {
1927
+ color: #fff
1928
+ }
1929
+
1930
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-secondary {
1931
+ color: #555;
1932
+ border-color: #cccccc;
1933
+ background: #f7f7f7;
1934
+ box-shadow: 0 1px 0 #cccccc
1935
+ }
1936
+
1937
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-secondary:hover,#sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.button-secondary:focus {
1938
+ background: #fafafa;
1939
+ border-color: #999;
1940
+ color: #23282d
1941
+ }
1942
+
1943
+ #sbi-admin-about #sbi-admin-addons .addon-item .action-button .button.disabled {
1944
+ cursor: default
1945
+ }
1946
+
1947
+ /* AW columns */
1948
+ .sbi-admin-columns>div[class*="-column-"] {
1949
+ float: left
1950
+ }
1951
+
1952
+ .sbi-admin-columns .sbi-admin-column-20 {
1953
+ width: 20%
1954
+ }
1955
+
1956
+ .sbi-admin-columns .sbi-admin-column-33 {
1957
+ width: 33.33333%
1958
+ }
1959
+
1960
+ .sbi-admin-columns .sbi-admin-column-40 {
1961
+ width: 40%
1962
+ }
1963
+
1964
+ .sbi-admin-columns .sbi-admin-column-50 {
1965
+ width: 50%
1966
+ }
1967
+
1968
+ .sbi-admin-columns .sbi-admin-column-60 {
1969
+ width: 60%
1970
+ }
1971
+
1972
+ .sbi-admin-columns .sbi-admin-column-80 {
1973
+ width: 80%
1974
+ }
1975
+
1976
+ .sbi-admin-columns .sbi-admin-column-last {
1977
+ float: right !important
1978
+ }
1979
+
1980
+ .sbi-admin-columns:after {
1981
+ content: "";
1982
+ display: table;
1983
+ clear: both
1984
+ }
1985
+
1986
+ /* AW Addons */
1987
+ #sbi-admin-addons h3 {
1988
+ padding: 10px 10px 0 10px;
1989
+ clear: left;
1990
+ }
1991
+ #sbi-admin-addons *,#sbi-admin-addons *::before,#sbi-admin-addons *::after {
1992
+ -webkit-box-sizing: border-box;
1993
+ -moz-box-sizing: border-box;
1994
+ box-sizing: border-box
1995
+ }
1996
+
1997
+ #sbi-admin-addons .addons-container {
1998
+ margin-left: -20px;
1999
+ margin-right: -20px
2000
+ }
2001
+
2002
+ #sbi-admin-addons .unlock-msg {
2003
+ padding: 0 20px;
2004
+ margin-top: -20px;
2005
+ clear: both
2006
+ }
2007
+
2008
+ #sbi-admin-addons #sbi-admin-addons-search {
2009
+ background-color: #fff;
2010
+ border: 1px solid #ddd;
2011
+ border-radius: 3px;
2012
+ box-shadow: none;
2013
+ color: #333;
2014
+ vertical-align: middle;
2015
+ padding: 7px 12px;
2016
+ margin: -3px 10px 0 0;
2017
+ width: 200px;
2018
+ min-height: 35px;
2019
+ float: right
2020
+ }
2021
+
2022
+ #sbi-admin-addons #sbi-admin-addons-search:focus {
2023
+ border-color: #bbb
2024
+ }
2025
+
2026
+ #sbi-admin-addons .addon-container {
2027
+ padding: 0 20px;
2028
+ float: left;
2029
+ width: 33.333333%;
2030
+ margin-bottom: 20px
2031
+ }
2032
+
2033
+ @media (max-width: 1249px) {
2034
+ #sbi-admin-addons .addon-container {
2035
+ width:50%
2036
+ }
2037
+ }
2038
+
2039
+ @media (max-width: 767px) {
2040
+ #sbi-admin-addons .addon-container {
2041
+ width:100%;
2042
+ margin-bottom: 20px
2043
+ }
2044
+ }
2045
+
2046
+ #sbi-admin-addons h4 {
2047
+ font-size: 17px;
2048
+ font-weight: 700
2049
+ }
2050
+
2051
+ #sbi-admin-addons .addon-item {
2052
+ background-color: #fff;
2053
+ border: 1px solid #ddd;
2054
+ border-radius: 3px;
2055
+ margin: 0
2056
+ }
2057
+
2058
+ @media (max-width: 767px) {
2059
+ #sbi-admin-addons .addon-item {
2060
+ margin:0 0
2061
+ }
2062
+ }
2063
+
2064
+ #sbi-admin-addons .addon-item img {
2065
+ border: 1px solid #eee;
2066
+ float: left;
2067
+ max-width: 75px
2068
+ }
2069
+
2070
+ #sbi-admin-addons .addon-item h5 {
2071
+ margin: 0 0 10px 100px;
2072
+ font-size: 16px
2073
+ }
2074
+
2075
+ #sbi-admin-addons .addon-item p {
2076
+ margin: 0 0 0 100px
2077
+ }
2078
+
2079
+ #sbi-admin-addons .addon-item .details {
2080
+ padding: 30px 20px
2081
+ }
2082
+
2083
+ #sbi-admin-addons .addon-item .actions {
2084
+ background-color: #f7f7f7;
2085
+ border-top: 1px solid #ddd;
2086
+ padding: 20px;
2087
+ position: relative
2088
+ }
2089
+
2090
+ #sbi-admin-addons .addon-item .actions .msg {
2091
+ background-color: #f7f7f7;
2092
+ position: absolute;
2093
+ text-align: center;
2094
+ font-weight: 600;
2095
+ top: 0;
2096
+ left: 0;
2097
+ height: 100%;
2098
+ width: 100%;
2099
+ z-index: 99;
2100
+ padding: 20px;
2101
+ display: -webkit-box;
2102
+ display: -moz-box;
2103
+ display: -ms-flexbox;
2104
+ display: -webkit-flex;
2105
+ display: flex;
2106
+ -webkit-align-items: center;
2107
+ -ms-align-items: center;
2108
+ align-items: center;
2109
+ justify-content: center
2110
+ }
2111
+
2112
+ #sbi-admin-addons .addon-item .actions .msg.success {
2113
+ color: #2a9b39
2114
+ }
2115
+
2116
+ #sbi-admin-addons .addon-item .actions .msg.error {
2117
+ color: red
2118
+ }
2119
+
2120
+ #sbi-admin-addons .addon-item .status {
2121
+ float: left;
2122
+ padding-top: 8px
2123
+ }
2124
+
2125
+ #sbi-admin-addons .addon-item .status .status-inactive {
2126
+ color: red
2127
+ }
2128
+
2129
+ #sbi-admin-addons .addon-item .status .status-download {
2130
+ color: #666
2131
+ }
2132
+
2133
+ #sbi-admin-addons .addon-item .status .status-active {
2134
+ color: #2a9b39
2135
+ }
2136
+
2137
+ #sbi-admin-addons .addon-item .upgrade-button {
2138
+ text-align: center
2139
+ }
2140
+
2141
+ #sbi-admin-addons .addon-item .upgrade-button a {
2142
+ font-weight: 600;
2143
+ width: 140px;
2144
+ text-align: center;
2145
+ padding: 8px 5px
2146
+ }
2147
+
2148
+ #sbi-admin-addons .addon-item .action-button {
2149
+ float: right
2150
+ }
2151
+
2152
+ #sbi-admin-addons .addon-item .action-button button {
2153
+ background: none;
2154
+ border: 1px solid #ddd;
2155
+ border-radius: 3px;
2156
+ box-shadow: none;
2157
+ cursor: pointer;
2158
+ font-weight: 600;
2159
+ width: 140px;
2160
+ text-align: center;
2161
+ padding: 8px 5px
2162
+ }
2163
+
2164
+ #sbi-admin-addons .addon-item .action-button button:hover,#sbi-admin-addons .addon-item .action-button button.loading {
2165
+ background-color: #e9e9e9
2166
+ }
2167
+
2168
+ #sbi-admin-addons .addon-item .action-button button .fa {
2169
+ margin-right: 8px
2170
+ }
2171
+
2172
+ #sbi-admin-addons .addon-item .action-button button .fa.fa-spinner {
2173
+ margin-right: 0
2174
+ }
2175
+
2176
+ #sbi-admin-addons .addon-item .action-button button.status-active .fa {
2177
+ color: #2a9b39
2178
+ }
2179
+
2180
+ #sbi-admin-addons .addon-item .action-button button.status-inactive .fa {
2181
+ color: red
2182
+ }
2183
+
2184
+ #sbi-admin-addons .addon-item .action-button button.status-download .fa {
2185
+ color: #999
2186
+ }
2187
+
2188
+ #sbi-admin-addons .addon-item .action-button button.disabled {
2189
+ cursor: default
2190
+ }
2191
+
2192
+ #sbi-admin-addons .addon-item .action-button button.loading .fa {
2193
+ color: #666
2194
+ }
2195
+
2196
+ /* Tabs */
2197
+ .sbi-admin-tabs {
2198
+ background-color: #fff;
2199
+ margin: 0 0 20px 0;
2200
+ padding: 0 20px;
2201
+ list-style: none;
2202
+ overflow: auto;
2203
+ font-size: 14px
2204
+ }
2205
+
2206
+ .sbi-admin-tabs li {
2207
+ margin: 0 30px 0 0;
2208
+ padding: 0;
2209
+ float: left
2210
+ }
2211
+
2212
+ .sbi-admin-tabs li:last-of-type {
2213
+ margin: 0
2214
+ }
2215
+
2216
+ .sbi-admin-tabs li a {
2217
+ color: #666;
2218
+ display: block;
2219
+ padding: 20px 0 18px 0;
2220
+ text-decoration: none;
2221
+ border-bottom: 2px solid #fff;
2222
+ box-shadow: none
2223
+ }
2224
+
2225
+ .sbi-admin-tabs li a:hover {
2226
+ border-color: #999
2227
+ }
2228
+
2229
+ .sbi-admin-tabs li a.active {
2230
+ border-color: #e27730
2231
+ }
2232
+
2233
+ .sbi-admin-tabs li a:focus {
2234
+ box-shadow: none
2235
+ }
2236
+
2237
+ /* Clear */
2238
+ .sbi-clear:before {
2239
+ content: " ";
2240
+ display: table
2241
+ }
2242
+
2243
+ .sbi-clear:after {
2244
+ clear: both;
2245
+ content: " ";
2246
+ display: table
2247
  }
css/sb-instagram.css CHANGED
@@ -1,819 +1,819 @@
1
- /**************/
2
- /*** LAYOUT ***/
3
- /**************/
4
-
5
- /* Feed container */
6
- #sb_instagram {
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
- #sb_instagram:after{
15
- content: "";
16
- display: table;
17
- clear: both;
18
- }
19
-
20
- /*********************/
21
- /*** STYLE OPTIONS ***/
22
- /*********************/
23
- #sb_instagram.sbi_fixed_height{
24
- overflow: hidden;
25
- overflow-y: auto;
26
- -webkit-box-sizing: border-box;
27
- -moz-box-sizing: border-box;
28
- box-sizing: border-box;
29
- }
30
- #sb_instagram #sbi_images{
31
- width: 100%;
32
- float: left;
33
- line-height: 0;
34
-
35
- -webkit-box-sizing: border-box;
36
- -moz-box-sizing: border-box;
37
- box-sizing: border-box;
38
- }
39
- /* Remove header shadow/border */
40
- #sb_instagram .sbi_header_link {
41
- -webkit-box-shadow: none;
42
- box-shadow: none;
43
- }
44
- #sb_instagram .sbi_header_link:hover {
45
- border: none;
46
- }
47
-
48
- /* Items */
49
- #sb_instagram #sbi_images .sbi_item{
50
- display: -moz-inline-stack;
51
- display: inline-block;
52
- float: left;
53
- vertical-align: top;
54
- zoom: 1;
55
- *display: inline;
56
-
57
- max-height: 1000px;
58
- padding: inherit !important;
59
- margin: 0 !important;
60
- text-decoration: none;
61
- opacity: 1;
62
- overflow: hidden;
63
-
64
- -webkit-box-sizing: border-box;
65
- -moz-box-sizing: border-box;
66
- box-sizing: border-box;
67
-
68
- -webkit-transition: all 0.5s ease;
69
- -moz-transition: all 0.5s ease;
70
- -o-transition: all 0.5s ease;
71
- -ms-transition: all 0.5s ease;
72
- transition: all 0.5s ease;
73
- }
74
- /* Transition items in */
75
- #sb_instagram #sbi_images .sbi_item.sbi_transition{
76
- opacity: 0;
77
- max-height: 0;
78
- }
79
-
80
- /* Cols */
81
- #sb_instagram.sbi_col_1 #sbi_images .sbi_item{ width: 100%; }
82
- #sb_instagram.sbi_col_2 #sbi_images .sbi_item{ width: 50%; }
83
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item{ width: 33.33%; }
84
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item{ width: 25%; }
85
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item{ width: 20%; }
86
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item{ width: 16.66%; }
87
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item{ width: 14.28%; }
88
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item{ width: 12.5%; }
89
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item{ width: 11.11%; }
90
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{ width: 10%; }
91
-
92
- /* Disable mobile layout */
93
- #sb_instagram.sbi_col_1.sbi_disable_mobile #sbi_images .sbi_item{ width: 100%; }
94
- #sb_instagram.sbi_col_2.sbi_disable_mobile #sbi_images .sbi_item{ width: 50%; }
95
- #sb_instagram.sbi_col_3.sbi_disable_mobile #sbi_images .sbi_item{ width: 33.33%; }
96
- #sb_instagram.sbi_col_4.sbi_disable_mobile #sbi_images .sbi_item{ width: 25%; }
97
- #sb_instagram.sbi_col_5.sbi_disable_mobile #sbi_images .sbi_item{ width: 20%; }
98
- #sb_instagram.sbi_col_6.sbi_disable_mobile #sbi_images .sbi_item{ width: 16.66%; }
99
- #sb_instagram.sbi_col_7.sbi_disable_mobile #sbi_images .sbi_item{ width: 14.28%; }
100
- #sb_instagram.sbi_col_8.sbi_disable_mobile #sbi_images .sbi_item{ width: 12.5%; }
101
- #sb_instagram.sbi_col_9.sbi_disable_mobile #sbi_images .sbi_item{ width: 11.11%; }
102
- #sb_instagram.sbi_col_10.sbi_disable_mobile #sbi_images .sbi_item{ width: 10%; }
103
-
104
- /* Photos */
105
- #sb_instagram .sbi_photo_wrap{
106
- position: relative;
107
- }
108
- #sb_instagram .sbi_photo{
109
- display: block;
110
- text-decoration: none;
111
- }
112
- #sb_instagram .sbi_photo img{
113
- width: 100%;
114
- height: auto;
115
- }
116
- #sb_instagram .sbi_no_js img{
117
- display: none;
118
- }
119
- #sb_instagram a,
120
- #sb_instagram a:hover,
121
- #sb_instagram a:focus,
122
- #sb_instagram a:active{
123
- outline: none;
124
- }
125
- #sb_instagram img{
126
- display: block;
127
- padding: 0 !important;
128
- margin: 0 !important;
129
- max-width: 100% !important;
130
- opacity: 1 !important;
131
- }
132
- #sb_instagram .sbi_link{
133
- display: none;
134
- position: absolute;
135
- bottom: 0;
136
- right: 0;
137
-
138
- width: 100%;
139
- padding: 10px 0;
140
- background: rgba(0,0,0,0.5);
141
- text-align: center;
142
- color: #fff;
143
- font-size: 12px;
144
- line-height: 1.1;
145
- }
146
- #sb_instagram .sbi_link a{
147
- padding: 0 6px;
148
- text-decoration: none;
149
- color: #fff;
150
- font-size: 12px;
151
- line-height: 1.1;
152
-
153
- display: -moz-inline-stack;
154
- display: inline-block;
155
- vertical-align: top;
156
- zoom: 1;
157
- *display: inline;
158
- }
159
- #sb_instagram .sbi_link .sbi_lightbox_link{
160
- padding-bottom: 5px;
161
- }
162
- #sb_instagram .sbi_link a:hover,
163
- #sb_instagram .sbi_link a:focus{
164
- text-decoration: underline;
165
- }
166
- #sb_instagram .sbi_photo_wrap:hover .sbi_link,
167
- #sb_instagram .sbi_photo_wrap:focus .sbi_link{
168
- display: block;
169
- }
170
-
171
- /* Videos */
172
- #sb_instagram svg:not(:root).svg-inline--fa {
173
- height: 1em;
174
- display: inline-block;
175
- }
176
-
177
- #sb_instagram .sbi_type_video .sbi_playbtn,
178
- #sb_instagram .sbi_type_carousel .sbi_playbtn,
179
- .sbi_type_carousel .fa-clone,
180
- #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play,
181
- #sb_instagram .sbi_type_video .svg-inline--fa.fa-play{
182
- display: block !important;
183
- position: absolute;
184
- z-index: 1;
185
-
186
- color: #fff;
187
- color: rgba(255,255,255,0.9);
188
- font-style: normal !important;
189
- text-shadow: 0 0 8px rgba(0,0,0,0.8);
190
- }
191
- #sb_instagram .sbi_type_video .sbi_playbtn,
192
- #sb_instagram .sbi_type_carousel .sbi_playbtn {
193
- z-index: 2;
194
- top: 50%;
195
- left: 50%;
196
- margin-top: -24px;
197
- margin-left: -19px;
198
- padding: 0;
199
- font-size: 48px;
200
- }
201
- #sb_instagram .sbi_type_carousel .fa-clone{
202
- right: 12px;
203
- top: 12px;
204
- font-size: 24px;
205
- text-shadow: 0 0 8px rgba(0,0,0,0.3);
206
- }
207
- .sbi_type_carousel svg.fa-clone,
208
- #sb_instagram .sbi_type_video .svg-inline--fa.fa-play,
209
- #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play{
210
- -webkit-filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
211
- filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
212
- }
213
-
214
- /* Loader */
215
- #sb_instagram .sbi_loader{
216
- width: 20px;
217
- height: 20px;
218
-
219
- position: relative;
220
- top: 50%;
221
- left: 50%;
222
- margin: -10px 0 0 -10px;
223
- background-color: #000;
224
- background-color: rgba(0,0,0,0.5);
225
-
226
- border-radius: 100%;
227
- -webkit-animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
228
- animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
229
- }
230
- #sb_instagram br {
231
- display: none;
232
- }
233
- #sbi_load p {
234
- display: inline;
235
- padding: 0;
236
- margin: 0;
237
- }
238
- /* Loader in button */
239
- #sb_instagram #sbi_load .sbi_loader{
240
- position: absolute;
241
- margin-top: -11px;
242
- background-color: #fff;
243
- opacity: 1;
244
- }
245
- @-webkit-keyframes sbi-sk-scaleout {
246
- 0% { -webkit-transform: scale(0) }
247
- 100% {
248
- -webkit-transform: scale(1.0);
249
- opacity: 0;
250
- }
251
- }
252
- @keyframes sbi-sk-scaleout {
253
- 0% {
254
- -webkit-transform: scale(0);
255
- -ms-transform: scale(0);
256
- transform: scale(0);
257
- } 100% {
258
- -webkit-transform: scale(1.0);
259
- -ms-transform: scale(1.0);
260
- transform: scale(1.0);
261
- opacity: 0;
262
- }
263
- }
264
-
265
- #sb_instagram .fa-spin,
266
- #sbi_lightbox .fa-spin{
267
- -webkit-animation: fa-spin 2s infinite linear;
268
- animation: fa-spin 2s infinite linear
269
- }
270
-
271
- #sb_instagram .fa-pulse,
272
- #sbi_lightbox .fa-pulse{
273
- -webkit-animation: fa-spin 1s infinite steps(8);
274
- animation: fa-spin 1s infinite steps(8)
275
- }
276
-
277
- @-webkit-keyframes fa-spin {
278
- 0% {
279
- -webkit-transform: rotate(0deg);
280
- transform: rotate(0deg)
281
- }
282
- 100% {
283
- -webkit-transform: rotate(359deg);
284
- transform: rotate(359deg)
285
- }
286
- }
287
-
288
- @keyframes fa-spin {
289
- 0% {
290
- -webkit-transform: rotate(0deg);
291
- transform: rotate(0deg)
292
- }
293
- 100% {
294
- -webkit-transform: rotate(359deg);
295
- transform: rotate(359deg)
296
- }
297
- }
298
- /* Screen reader */
299
- .sbi-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;text-align: left !important; }
300
-
301
- /* HEADER */
302
- #sb_instagram .sb_instagram_header{
303
- float: left;
304
- clear: both;
305
- margin: 0 0 15px 0;
306
- padding: 0;
307
- line-height: 1.2;
308
- width: 100%;
309
- }
310
- #sb_instagram .sb_instagram_header a{
311
- float: left;
312
- display: block;
313
- /*width: 100%;*/
314
- min-width: 100%\9;
315
- text-decoration: none;
316
- transition: color 0.5s ease;
317
- }
318
- .sbi_no_avatar .sbi_header_img{
319
- background: #333;
320
- color: #fff;
321
- width: 50px;
322
- height: 50px;
323
- position: relative;
324
- }
325
- .sbi_no_avatar .sbi_header_hashtag_icon {
326
- display: block;
327
- color: #fff;
328
- opacity: .9;
329
- -webkit-transition: background .6s linear,color .6s linear;
330
- -moz-transition: background .6s linear,color .6s linear;
331
- -ms-transition: background .6s linear,color .6s linear;
332
- -o-transition: background .6s linear,color .6s linear;
333
- transition: background .6s linear,color .6s linear
334
- }
335
-
336
- .sbi_no_avatar:hover .sbi_header_hashtag_icon {
337
- display: block;
338
- opacity: 1;
339
- -webkit-transition: background .2s linear,color .2s linear;
340
- -moz-transition: background .2s linear,color .2s linear;
341
- -ms-transition: background .2s linear,color .2s linear;
342
- -o-transition: background .2s linear,color .2s linear;
343
- transition: background .2s linear,color .2s linear
344
- }
345
- /** Medium Header */
346
- /* Only use medium & large headers on devices above 480px */
347
- @media all and (min-width: 480px){
348
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img {
349
- width: 80px;
350
- height: 80px;
351
- border-radius: 40px;
352
- }
353
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img img {
354
- width: 80px;
355
- height: 80px;
356
- border-radius: 40px;
357
- }
358
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3 {
359
- font-size: 20px;
360
- }
361
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
362
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
363
- font-size: 14px;
364
- }
365
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3,
366
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
367
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
368
- margin-left: 95px !important;
369
- line-height: 1.4
370
- }
371
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3{
372
- margin-right: -85px !important;
373
- }
374
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info{
375
- margin-top: 4px !important;
376
- }
377
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text.sbi_no_bio h3{
378
- padding-top: 20px !important;
379
- }
380
- /** Large Header */
381
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img {
382
- width: 120px;
383
- height: 120px;
384
- border-radius: 60px;
385
- }
386
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img img {
387
- width: 120px;
388
- height: 120px;
389
- border-radius: 60px;
390
- }
391
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3 {
392
- font-size: 28px;
393
- }
394
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
395
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
396
- font-size: 16px;
397
- }
398
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3,
399
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
400
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
401
- margin-left: 140px !important;
402
- line-height: 1.5;
403
- }
404
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3{
405
- margin-right: -120px !important;
406
- }
407
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info{
408
- margin-top: 12px !important;
409
- }
410
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text.sbi_no_bio h3{
411
- padding-top: 32px !important;
412
- }
413
- }
414
-
415
- /* Header profile pic */
416
- #sb_instagram .sb_instagram_header .sbi_header_img{
417
- float: left;
418
- position: relative;
419
- width: 50px;
420
- margin: 0 0 0 -100% !important;
421
- overflow: hidden;
422
-
423
- -moz-border-radius: 40px;
424
- -webkit-border-radius: 40px;
425
- border-radius: 40px;
426
- }
427
- #sb_instagram .sb_instagram_header .sbi_header_img img{
428
- float: left;
429
- margin: 0 !important;
430
- padding: 0 !important;
431
- border: none !important;
432
-
433
- -moz-border-radius: 40px;
434
- -webkit-border-radius: 40px;
435
- border-radius: 40px;
436
- }
437
- /* Profile pic hover */
438
- /* Profile pic hover */
439
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
440
- opacity: 0;
441
- position: absolute;
442
- width: 100%;
443
- top: 0;
444
- bottom: 0;
445
- left: 0;
446
- text-align: center;
447
- color: #fff;
448
- background: rgba(0,0,0,0.75);
449
- }
450
-
451
- #sb_instagram .sb_instagram_header .sbi_header_img_hover .sbi_new_logo,
452
- #sb_instagram .sb_instagram_header .sbi_header_hashtag_icon .sbi_new_logo{
453
- position: absolute;
454
- top: 50%;
455
- left: 50%;
456
- margin-top: -12px;
457
- margin-left: -12px;
458
- width: 24px;
459
- height: 24px;
460
- font-size: 24px;
461
- }
462
- #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo,
463
- .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo{
464
- margin-top: -18px;
465
- margin-left: -18px;
466
- width: 36px;
467
- height: 36px;
468
- font-size: 36px
469
- }
470
-
471
- #sb_instagram .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo,
472
- .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo {
473
- margin-top: -24px;
474
- margin-left: -24px;
475
- width: 48px;
476
- height: 48px;
477
- font-size: 48px
478
- }
479
- #sb_instagram .sb_instagram_header .sbi_header_img_hover i {
480
- overflow: hidden;
481
- background: url('../img/small-logo.png') no-repeat 0 0;
482
- }
483
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
484
- z-index: 2;
485
- transition: opacity 0.4s ease-in-out;
486
- }
487
- #sb_instagram .sb_instagram_header .sbi_fade_in{
488
- opacity: 1;
489
- transition: opacity 0.2s ease-in-out;
490
- }
491
- #sb_instagram .sb_instagram_header .sbi_header_img_hover{
492
- position: absolute;
493
- width: 100%;
494
- top: 0;
495
- bottom: 0;
496
- left: 0;
497
- text-align: center;
498
- color: #fff;
499
- background: rgba(0,0,0,0.75);
500
-
501
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
502
- filter: alpha(opacity=0);
503
- -moz-opacity: 0;
504
- -khtml-opacity: 0;
505
- opacity: 0;
506
- border-radius: 40px;
507
- transition: opacity 0.2s;
508
- }
509
- /* Fade the Instagram icon in when hovering on the header */
510
- #sb_instagram .sb_instagram_header a:hover .sbi_header_img_hover,
511
- #sb_instagram .sb_instagram_header a:focus .sbi_header_img_hover{
512
- opacity: 1;
513
- }
514
- /* Header text */
515
- #sb_instagram .sb_instagram_header .sbi_header_text{
516
- float: left;
517
- width: 100%;
518
- padding-top: 5px;
519
- }
520
- #sb_instagram .sb_instagram_header a{
521
- text-decoration: none;
522
- }
523
- #sb_instagram .sb_instagram_header .sbi_header_text .sbi_bio,
524
- #sb_instagram .sb_instagram_header .sbi_header_text h3{
525
- float: left;
526
- clear: both;
527
- width: auto;
528
- margin: 0 0 0 60px !important;
529
- padding: 0 !important;
530
- }
531
- #sb_instagram .sb_instagram_header h3{
532
- font-size: 16px;
533
- line-height: 1.3;
534
- }
535
- #sb_instagram .sb_instagram_header p{
536
- font-size: 13px;
537
- line-height: 1.3;
538
- margin: 0;
539
- padding: 0;
540
- }
541
- #sb_instagram p:empty { display: none; }
542
- #sb_instagram .sb_instagram_header .sbi_header_text img.emoji{
543
- margin-right: 3px !important;
544
- }
545
-
546
- /* No bio */
547
- #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio h3{
548
- padding-top: 9px !important;
549
- }
550
- #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio .sbi_bio_info{
551
- clear: both;
552
- }
553
-
554
-
555
- /* Buttons */
556
- #sb_instagram #sbi_load{
557
- float: left;
558
- clear: both;
559
- width: 100%;
560
- text-align: center;
561
- }
562
- #sb_instagram #sbi_load .fa-spinner{
563
- display: none;
564
- position: absolute;
565
- top: 50%;
566
- left: 50%;
567
- margin: -8px 0 0 -7px;
568
- font-size: 15px;
569
- }
570
- #sb_instagram #sbi_load{
571
- opacity: 1;
572
- transition: all 0.5s ease-in;
573
- }
574
- #sb_instagram .sbi_load_btn .sbi_btn_text, #sb_instagram .sbi_load_btn .sbi_loader{
575
- opacity: 1;
576
- transition: all 0.1s ease-in;
577
- }
578
- #sb_instagram .sbi_hidden{
579
- opacity: 0 !important;
580
- }
581
- #sb_instagram #sbi_load .sbi_load_btn,
582
- #sb_instagram .sbi_follow_btn a{
583
- display: -moz-inline-stack;
584
- display: inline-block;
585
- vertical-align: top;
586
- zoom: 1;
587
- *display: inline;
588
-
589
- padding: 7px 14px;
590
- margin: 5px auto 0 auto;
591
- background: #333;
592
- color: #eee;
593
- border: none;
594
- color: #fff;
595
- text-decoration: none;
596
- font-size: 13px;
597
- line-height: 1.5;
598
-
599
- -moz-border-radius: 4px;
600
- -webkit-border-radius: 4px;
601
- border-radius: 4px;
602
-
603
- -webkit-box-sizing: border-box;
604
- -moz-box-sizing: border-box;
605
- box-sizing: border-box;
606
- }
607
- #sb_instagram #sbi_load .sbi_load_btn {
608
- position: relative;
609
- }
610
- /* Follow button */
611
- #sb_instagram .sbi_follow_btn{
612
- display: -moz-inline-stack;
613
- display: inline-block;
614
- vertical-align: top;
615
- zoom: 1;
616
- *display: inline;
617
- text-align: center;
618
- }
619
- #sb_instagram .sbi_follow_btn.sbi_top{
620
- display: block;
621
- margin-bottom: 5px;
622
- }
623
- #sb_instagram .sbi_follow_btn a{
624
- background: #408bd1;
625
- color: #fff;
626
- }
627
- #sb_instagram .sbi_follow_btn a,
628
- #sb_instagram .sbi_follow_btn a,
629
- #sb_instagram #sbi_load .sbi_load_btn{
630
- transition: all 0.1s ease-in;
631
- }
632
- /* Hover state for default colors */
633
- #sb_instagram #sbi_load .sbi_load_btn:hover{
634
- outline: none;
635
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
636
- }
637
- #sb_instagram .sbi_follow_btn a:hover,
638
- #sb_instagram .sbi_follow_btn a:focus{
639
- outline: none;
640
- box-shadow: inset 0 0 10px 20px #359dff;
641
- }
642
- /* If a custom color is applied then just use opacity for the hover effect */
643
- #sb_instagram .sbi_follow_btn.sbi_custom a:hover,
644
- #sb_instagram .sbi_follow_btn.sbi_custom a:focus,
645
- #sb_instagram #sbi_load .sbi_load_btn.sbi_custom:hover{
646
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
647
- }
648
- /* Active state */
649
- #sb_instagram .sbi_follow_btn a:active,
650
- #sb_instagram #sbi_load .sbi_load_btn:active{
651
- box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
652
- }
653
-
654
- #sb_instagram .sbi_follow_btn .fa,
655
- #sb_instagram .sbi_follow_btn svg{
656
- margin-bottom: -1px;
657
- margin-right: 7px;
658
- font-size: 15px;
659
- }
660
- #sb_instagram .sbi_follow_btn svg{
661
- vertical-align: -.125em;
662
- }
663
- #sb_instagram #sbi_load .sbi_follow_btn{
664
- margin-left: 5px;
665
- }
666
-
667
- /* Error messages */
668
- #sb_instagram .sb_instagram_error{
669
- width: 100%;
670
- text-align: center;
671
- line-height: 1.4;
672
- }
673
-
674
- /* Mod only error msgs */
675
- #sbi_mod_error{
676
- display: none;
677
- border: 1px solid #ddd;
678
- background: #eee;
679
- color: #333;
680
- margin: 10px 0 0;
681
- padding: 10px 15px;
682
- font-size: 13px;
683
- text-align: center;
684
- clear: both;
685
-
686
- -moz-border-radius: 4px;
687
- -webkit-border-radius: 4px;
688
- border-radius: 4px;
689
- }
690
- #sbi_mod_error br {
691
- display: initial !important;
692
- }
693
- #sbi_mod_error p{
694
- padding: 5px 0 !important;
695
- margin: 0 !important;
696
- line-height: 1.3 !important;
697
- }
698
- #sbi_mod_error ol,
699
- #sbi_mod_error ul{
700
- padding: 5px 0 5px 20px !important;
701
- margin: 0 !important;
702
- }
703
- #sbi_mod_error li{
704
- padding: 1px 0 !important;
705
- margin: 0 !important;
706
- }
707
- #sbi_mod_error span{
708
- font-size: 12px;
709
- }
710
-
711
- /* Medium */
712
- #sb_instagram.sbi_medium .sbi_playbtn,
713
- #sb_instagram.sbi_medium .sbi_photo_wrap .svg-inline--fa.fa-play{
714
- margin-top: -12px;
715
- margin-left: -9px;
716
- font-size: 23px;
717
- }
718
- #sb_instagram.sbi_medium .sbi_type_carousel .sbi_photo_wrap .fa-clone{
719
- right: 8px;
720
- top: 8px;
721
- font-size: 18px;
722
- }
723
- /* Small */
724
- #sb_instagram.sbi_small .sbi_playbtn,
725
- #sb_instagram.sbi_small .sbi_photo_wrap .svg-inline--fa.fa-play{
726
- margin-top: -9px;
727
- margin-left: -7px;
728
- font-size: 18px;
729
- }
730
- #sb_instagram.sbi_small .sbi_type_carousel .sbi_photo_wrap .fa-clone{
731
- right: 5px;
732
- top: 5px;
733
- font-size: 12px;
734
- }
735
-
736
- /* Media queries */
737
- @media all and (max-width: 640px){
738
- /* Make 3-6 cols into 2 col */
739
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
740
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
741
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
742
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item{
743
- width: 50%;
744
- }
745
- /* Make 7-10 cols into 4 col */
746
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
747
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
748
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
749
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
750
- width: 25%;
751
- }
752
- /* On mobile make the min-width 100% */
753
- #sb_instagram.sbi_width_resp{
754
- width: 100% !important;
755
- }
756
- }
757
- @media all and (max-width: 480px){
758
- /* Make all cols into 1 col */
759
- #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
760
- #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
761
- #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
762
- #sb_instagram.sbi_col_6 #sbi_images .sbi_item,
763
- #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
764
- #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
765
- #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
766
- #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
767
- width: 100%;
768
- }
769
- }
770
-
771
- /* NO JS */
772
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap{
773
- box-sizing: border-box;
774
- position: relative;
775
- overflow: hidden;
776
- }
777
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap:before {
778
- content: "";
779
- display: block;
780
- padding-top: 100%;
781
- z-index: -300;
782
- }
783
- #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo {
784
- position: absolute;
785
- top: 0;
786
- left: 0;
787
- bottom: 0;
788
- right: 0;
789
- }
790
- #sb_instagram.sbi_no_js #sbi_images .sbi_item.sbi_transition {
791
- opacity: 1;
792
- max-height: 640px;
793
- }
794
- #sb_instagram.sbi_no_js .sbi_photo img,
795
- #sb_instagram.sbi_no_js .sbi_load_btn{
796
- display: none;
797
- }
798
- #sb_instagram #sbi_images .sbi_js_load_disabled .sbi_imgLiquid_ready.sbi_photo {
799
- padding-bottom: 0 !important;
800
- }
801
- #sb_instagram #sbi_mod_error .sb_frontend_btn {
802
- display: inline-block;
803
- padding: 6px 10px;
804
- background: #ddd;
805
- background: rgba(0,0,0,.1);
806
- text-decoration: none;
807
- border-radius: 5px;
808
- margin-top: 10px;
809
- color: #444
810
- }
811
-
812
- #sb_instagram #sbi_mod_error .sb_frontend_btn:hover {
813
- background: #ccc;
814
- background: rgba(0,0,0,.15)
815
- }
816
-
817
- #sb_instagram #sbi_mod_error .sb_frontend_btn .fa {
818
- margin-right: 2px
819
  }
1
+ /**************/
2
+ /*** LAYOUT ***/
3
+ /**************/
4
+
5
+ /* Feed container */
6
+ #sb_instagram {
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
+ #sb_instagram:after{
15
+ content: "";
16
+ display: table;
17
+ clear: both;
18
+ }
19
+
20
+ /*********************/
21
+ /*** STYLE OPTIONS ***/
22
+ /*********************/
23
+ #sb_instagram.sbi_fixed_height{
24
+ overflow: hidden;
25
+ overflow-y: auto;
26
+ -webkit-box-sizing: border-box;
27
+ -moz-box-sizing: border-box;
28
+ box-sizing: border-box;
29
+ }
30
+ #sb_instagram #sbi_images{
31
+ width: 100%;
32
+ float: left;
33
+ line-height: 0;
34
+
35
+ -webkit-box-sizing: border-box;
36
+ -moz-box-sizing: border-box;
37
+ box-sizing: border-box;
38
+ }
39
+ /* Remove header shadow/border */
40
+ #sb_instagram .sbi_header_link {
41
+ -webkit-box-shadow: none;
42
+ box-shadow: none;
43
+ }
44
+ #sb_instagram .sbi_header_link:hover {
45
+ border: none;
46
+ }
47
+
48
+ /* Items */
49
+ #sb_instagram #sbi_images .sbi_item{
50
+ display: -moz-inline-stack;
51
+ display: inline-block;
52
+ float: left;
53
+ vertical-align: top;
54
+ zoom: 1;
55
+ *display: inline;
56
+
57
+ max-height: 1000px;
58
+ padding: inherit !important;
59
+ margin: 0 !important;
60
+ text-decoration: none;
61
+ opacity: 1;
62
+ overflow: hidden;
63
+
64
+ -webkit-box-sizing: border-box;
65
+ -moz-box-sizing: border-box;
66
+ box-sizing: border-box;
67
+
68
+ -webkit-transition: all 0.5s ease;
69
+ -moz-transition: all 0.5s ease;
70
+ -o-transition: all 0.5s ease;
71
+ -ms-transition: all 0.5s ease;
72
+ transition: all 0.5s ease;
73
+ }
74
+ /* Transition items in */
75
+ #sb_instagram #sbi_images .sbi_item.sbi_transition{
76
+ opacity: 0;
77
+ max-height: 0;
78
+ }
79
+
80
+ /* Cols */
81
+ #sb_instagram.sbi_col_1 #sbi_images .sbi_item{ width: 100%; }
82
+ #sb_instagram.sbi_col_2 #sbi_images .sbi_item{ width: 50%; }
83
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item{ width: 33.33%; }
84
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item{ width: 25%; }
85
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item{ width: 20%; }
86
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item{ width: 16.66%; }
87
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item{ width: 14.28%; }
88
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item{ width: 12.5%; }
89
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item{ width: 11.11%; }
90
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{ width: 10%; }
91
+
92
+ /* Disable mobile layout */
93
+ #sb_instagram.sbi_col_1.sbi_disable_mobile #sbi_images .sbi_item{ width: 100%; }
94
+ #sb_instagram.sbi_col_2.sbi_disable_mobile #sbi_images .sbi_item{ width: 50%; }
95
+ #sb_instagram.sbi_col_3.sbi_disable_mobile #sbi_images .sbi_item{ width: 33.33%; }
96
+ #sb_instagram.sbi_col_4.sbi_disable_mobile #sbi_images .sbi_item{ width: 25%; }
97
+ #sb_instagram.sbi_col_5.sbi_disable_mobile #sbi_images .sbi_item{ width: 20%; }
98
+ #sb_instagram.sbi_col_6.sbi_disable_mobile #sbi_images .sbi_item{ width: 16.66%; }
99
+ #sb_instagram.sbi_col_7.sbi_disable_mobile #sbi_images .sbi_item{ width: 14.28%; }
100
+ #sb_instagram.sbi_col_8.sbi_disable_mobile #sbi_images .sbi_item{ width: 12.5%; }
101
+ #sb_instagram.sbi_col_9.sbi_disable_mobile #sbi_images .sbi_item{ width: 11.11%; }
102
+ #sb_instagram.sbi_col_10.sbi_disable_mobile #sbi_images .sbi_item{ width: 10%; }
103
+
104
+ /* Photos */
105
+ #sb_instagram .sbi_photo_wrap{
106
+ position: relative;
107
+ }
108
+ #sb_instagram .sbi_photo{
109
+ display: block;
110
+ text-decoration: none;
111
+ }
112
+ #sb_instagram .sbi_photo img{
113
+ width: 100%;
114
+ height: auto;
115
+ }
116
+ #sb_instagram .sbi_no_js img{
117
+ display: none;
118
+ }
119
+ #sb_instagram a,
120
+ #sb_instagram a:hover,
121
+ #sb_instagram a:focus,
122
+ #sb_instagram a:active{
123
+ outline: none;
124
+ }
125
+ #sb_instagram img{
126
+ display: block;
127
+ padding: 0 !important;
128
+ margin: 0 !important;
129
+ max-width: 100% !important;
130
+ opacity: 1 !important;
131
+ }
132
+ #sb_instagram .sbi_link{
133
+ display: none;
134
+ position: absolute;
135
+ bottom: 0;
136
+ right: 0;
137
+
138
+ width: 100%;
139
+ padding: 10px 0;
140
+ background: rgba(0,0,0,0.5);
141
+ text-align: center;
142
+ color: #fff;
143
+ font-size: 12px;
144
+ line-height: 1.1;
145
+ }
146
+ #sb_instagram .sbi_link a{
147
+ padding: 0 6px;
148
+ text-decoration: none;
149
+ color: #fff;
150
+ font-size: 12px;
151
+ line-height: 1.1;
152
+
153
+ display: -moz-inline-stack;
154
+ display: inline-block;
155
+ vertical-align: top;
156
+ zoom: 1;
157
+ *display: inline;
158
+ }
159
+ #sb_instagram .sbi_link .sbi_lightbox_link{
160
+ padding-bottom: 5px;
161
+ }
162
+ #sb_instagram .sbi_link a:hover,
163
+ #sb_instagram .sbi_link a:focus{
164
+ text-decoration: underline;
165
+ }
166
+ #sb_instagram .sbi_photo_wrap:hover .sbi_link,
167
+ #sb_instagram .sbi_photo_wrap:focus .sbi_link{
168
+ display: block;
169
+ }
170
+
171
+ /* Videos */
172
+ #sb_instagram svg:not(:root).svg-inline--fa {
173
+ height: 1em;
174
+ display: inline-block;
175
+ }
176
+
177
+ #sb_instagram .sbi_type_video .sbi_playbtn,
178
+ #sb_instagram .sbi_type_carousel .sbi_playbtn,
179
+ .sbi_type_carousel .fa-clone,
180
+ #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play,
181
+ #sb_instagram .sbi_type_video .svg-inline--fa.fa-play{
182
+ display: block !important;
183
+ position: absolute;
184
+ z-index: 1;
185
+
186
+ color: #fff;
187
+ color: rgba(255,255,255,0.9);
188
+ font-style: normal !important;
189
+ text-shadow: 0 0 8px rgba(0,0,0,0.8);
190
+ }
191
+ #sb_instagram .sbi_type_video .sbi_playbtn,
192
+ #sb_instagram .sbi_type_carousel .sbi_playbtn {
193
+ z-index: 2;
194
+ top: 50%;
195
+ left: 50%;
196
+ margin-top: -24px;
197
+ margin-left: -19px;
198
+ padding: 0;
199
+ font-size: 48px;
200
+ }
201
+ #sb_instagram .sbi_type_carousel .fa-clone{
202
+ right: 12px;
203
+ top: 12px;
204
+ font-size: 24px;
205
+ text-shadow: 0 0 8px rgba(0,0,0,0.3);
206
+ }
207
+ .sbi_type_carousel svg.fa-clone,
208
+ #sb_instagram .sbi_type_video .svg-inline--fa.fa-play,
209
+ #sb_instagram .sbi_type_carousel .svg-inline--fa.fa-play{
210
+ -webkit-filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
211
+ filter: drop-shadow( 0px 0px 2px rgba(0,0,0,.4) );
212
+ }
213
+
214
+ /* Loader */
215
+ #sb_instagram .sbi_loader{
216
+ width: 20px;
217
+ height: 20px;
218
+
219
+ position: relative;
220
+ top: 50%;
221
+ left: 50%;
222
+ margin: -10px 0 0 -10px;
223
+ background-color: #000;
224
+ background-color: rgba(0,0,0,0.5);
225
+
226
+ border-radius: 100%;
227
+ -webkit-animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
228
+ animation: sbi-sk-scaleout 1.0s infinite ease-in-out;
229
+ }
230
+ #sb_instagram br {
231
+ display: none;
232
+ }
233
+ #sbi_load p {
234
+ display: inline;
235
+ padding: 0;
236
+ margin: 0;
237
+ }
238
+ /* Loader in button */
239
+ #sb_instagram #sbi_load .sbi_loader{
240
+ position: absolute;
241
+ margin-top: -11px;
242
+ background-color: #fff;
243
+ opacity: 1;
244
+ }
245
+ @-webkit-keyframes sbi-sk-scaleout {
246
+ 0% { -webkit-transform: scale(0) }
247
+ 100% {
248
+ -webkit-transform: scale(1.0);
249
+ opacity: 0;
250
+ }
251
+ }
252
+ @keyframes sbi-sk-scaleout {
253
+ 0% {
254
+ -webkit-transform: scale(0);
255
+ -ms-transform: scale(0);
256
+ transform: scale(0);
257
+ } 100% {
258
+ -webkit-transform: scale(1.0);
259
+ -ms-transform: scale(1.0);
260
+ transform: scale(1.0);
261
+ opacity: 0;
262
+ }
263
+ }
264
+
265
+ #sb_instagram .fa-spin,
266
+ #sbi_lightbox .fa-spin{
267
+ -webkit-animation: fa-spin 2s infinite linear;
268
+ animation: fa-spin 2s infinite linear
269
+ }
270
+
271
+ #sb_instagram .fa-pulse,
272
+ #sbi_lightbox .fa-pulse{
273
+ -webkit-animation: fa-spin 1s infinite steps(8);
274
+ animation: fa-spin 1s infinite steps(8)
275
+ }
276
+
277
+ @-webkit-keyframes fa-spin {
278
+ 0% {
279
+ -webkit-transform: rotate(0deg);
280
+ transform: rotate(0deg)
281
+ }
282
+ 100% {
283
+ -webkit-transform: rotate(359deg);
284
+ transform: rotate(359deg)
285
+ }
286
+ }
287
+
288
+ @keyframes fa-spin {
289
+ 0% {
290
+ -webkit-transform: rotate(0deg);
291
+ transform: rotate(0deg)
292
+ }
293
+ 100% {
294
+ -webkit-transform: rotate(359deg);
295
+ transform: rotate(359deg)
296
+ }
297
+ }
298
+ /* Screen reader */
299
+ .sbi-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;text-align: left !important; }
300
+
301
+ /* HEADER */
302
+ #sb_instagram .sb_instagram_header{
303
+ float: left;
304
+ clear: both;
305
+ margin: 0 0 15px 0;
306
+ padding: 0;
307
+ line-height: 1.2;
308
+ width: 100%;
309
+ }
310
+ #sb_instagram .sb_instagram_header a{
311
+ float: left;
312
+ display: block;
313
+ /*width: 100%;*/
314
+ min-width: 100%\9;
315
+ text-decoration: none;
316
+ transition: color 0.5s ease;
317
+ }
318
+ .sbi_no_avatar .sbi_header_img{
319
+ background: #333;
320
+ color: #fff;
321
+ width: 50px;
322
+ height: 50px;
323
+ position: relative;
324
+ }
325
+ .sbi_no_avatar .sbi_header_hashtag_icon {
326
+ display: block;
327
+ color: #fff;
328
+ opacity: .9;
329
+ -webkit-transition: background .6s linear,color .6s linear;
330
+ -moz-transition: background .6s linear,color .6s linear;
331
+ -ms-transition: background .6s linear,color .6s linear;
332
+ -o-transition: background .6s linear,color .6s linear;
333
+ transition: background .6s linear,color .6s linear
334
+ }
335
+
336
+ .sbi_no_avatar:hover .sbi_header_hashtag_icon {
337
+ display: block;
338
+ opacity: 1;
339
+ -webkit-transition: background .2s linear,color .2s linear;
340
+ -moz-transition: background .2s linear,color .2s linear;
341
+ -ms-transition: background .2s linear,color .2s linear;
342
+ -o-transition: background .2s linear,color .2s linear;
343
+ transition: background .2s linear,color .2s linear
344
+ }
345
+ /** Medium Header */
346
+ /* Only use medium & large headers on devices above 480px */
347
+ @media all and (min-width: 480px){
348
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img {
349
+ width: 80px;
350
+ height: 80px;
351
+ border-radius: 40px;
352
+ }
353
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_img img {
354
+ width: 80px;
355
+ height: 80px;
356
+ border-radius: 40px;
357
+ }
358
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3 {
359
+ font-size: 20px;
360
+ }
361
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
362
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
363
+ font-size: 14px;
364
+ }
365
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3,
366
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info,
367
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio{
368
+ margin-left: 95px !important;
369
+ line-height: 1.4
370
+ }
371
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text h3{
372
+ margin-right: -85px !important;
373
+ }
374
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text .sbi_bio_info{
375
+ margin-top: 4px !important;
376
+ }
377
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_text.sbi_no_bio h3{
378
+ padding-top: 20px !important;
379
+ }
380
+ /** Large Header */
381
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img {
382
+ width: 120px;
383
+ height: 120px;
384
+ border-radius: 60px;
385
+ }
386
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_img img {
387
+ width: 120px;
388
+ height: 120px;
389
+ border-radius: 60px;
390
+ }
391
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3 {
392
+ font-size: 28px;
393
+ }
394
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
395
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
396
+ font-size: 16px;
397
+ }
398
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3,
399
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info,
400
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio{
401
+ margin-left: 140px !important;
402
+ line-height: 1.5;
403
+ }
404
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text h3{
405
+ margin-right: -120px !important;
406
+ }
407
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text .sbi_bio_info{
408
+ margin-top: 12px !important;
409
+ }
410
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_text.sbi_no_bio h3{
411
+ padding-top: 32px !important;
412
+ }
413
+ }
414
+
415
+ /* Header profile pic */
416
+ #sb_instagram .sb_instagram_header .sbi_header_img{
417
+ float: left;
418
+ position: relative;
419
+ width: 50px;
420
+ margin: 0 0 0 -100% !important;
421
+ overflow: hidden;
422
+
423
+ -moz-border-radius: 40px;
424
+ -webkit-border-radius: 40px;
425
+ border-radius: 40px;
426
+ }
427
+ #sb_instagram .sb_instagram_header .sbi_header_img img{
428
+ float: left;
429
+ margin: 0 !important;
430
+ padding: 0 !important;
431
+ border: none !important;
432
+
433
+ -moz-border-radius: 40px;
434
+ -webkit-border-radius: 40px;
435
+ border-radius: 40px;
436
+ }
437
+ /* Profile pic hover */
438
+ /* Profile pic hover */
439
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
440
+ opacity: 0;
441
+ position: absolute;
442
+ width: 100%;
443
+ top: 0;
444
+ bottom: 0;
445
+ left: 0;
446
+ text-align: center;
447
+ color: #fff;
448
+ background: rgba(0,0,0,0.75);
449
+ }
450
+
451
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover .sbi_new_logo,
452
+ #sb_instagram .sb_instagram_header .sbi_header_hashtag_icon .sbi_new_logo{
453
+ position: absolute;
454
+ top: 50%;
455
+ left: 50%;
456
+ margin-top: -12px;
457
+ margin-left: -12px;
458
+ width: 24px;
459
+ height: 24px;
460
+ font-size: 24px;
461
+ }
462
+ #sb_instagram .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo,
463
+ .sb_instagram_header.sbi_medium .sbi_header_hashtag_icon .sbi_new_logo{
464
+ margin-top: -18px;
465
+ margin-left: -18px;
466
+ width: 36px;
467
+ height: 36px;
468
+ font-size: 36px
469
+ }
470
+
471
+ #sb_instagram .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo,
472
+ .sb_instagram_header.sbi_large .sbi_header_hashtag_icon .sbi_new_logo {
473
+ margin-top: -24px;
474
+ margin-left: -24px;
475
+ width: 48px;
476
+ height: 48px;
477
+ font-size: 48px
478
+ }
479
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover i {
480
+ overflow: hidden;
481
+ background: url('../img/small-logo.png') no-repeat 0 0;
482
+ }
483
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
484
+ z-index: 2;
485
+ transition: opacity 0.4s ease-in-out;
486
+ }
487
+ #sb_instagram .sb_instagram_header .sbi_fade_in{
488
+ opacity: 1;
489
+ transition: opacity 0.2s ease-in-out;
490
+ }
491
+ #sb_instagram .sb_instagram_header .sbi_header_img_hover{
492
+ position: absolute;
493
+ width: 100%;
494
+ top: 0;
495
+ bottom: 0;
496
+ left: 0;
497
+ text-align: center;
498
+ color: #fff;
499
+ background: rgba(0,0,0,0.75);
500
+
501
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
502
+ filter: alpha(opacity=0);
503
+ -moz-opacity: 0;
504
+ -khtml-opacity: 0;
505
+ opacity: 0;
506
+ border-radius: 40px;
507
+ transition: opacity 0.2s;
508
+ }
509
+ /* Fade the Instagram icon in when hovering on the header */
510
+ #sb_instagram .sb_instagram_header a:hover .sbi_header_img_hover,
511
+ #sb_instagram .sb_instagram_header a:focus .sbi_header_img_hover{
512
+ opacity: 1;
513
+ }
514
+ /* Header text */
515
+ #sb_instagram .sb_instagram_header .sbi_header_text{
516
+ float: left;
517
+ width: 100%;
518
+ padding-top: 5px;
519
+ }
520
+ #sb_instagram .sb_instagram_header a{
521
+ text-decoration: none;
522
+ }
523
+ #sb_instagram .sb_instagram_header .sbi_header_text .sbi_bio,
524
+ #sb_instagram .sb_instagram_header .sbi_header_text h3{
525
+ float: left;
526
+ clear: both;
527
+ width: auto;
528
+ margin: 0 0 0 60px !important;
529
+ padding: 0 !important;
530
+ }
531
+ #sb_instagram .sb_instagram_header h3{
532
+ font-size: 16px;
533
+ line-height: 1.3;
534
+ }
535
+ #sb_instagram .sb_instagram_header p{
536
+ font-size: 13px;
537
+ line-height: 1.3;
538
+ margin: 0;
539
+ padding: 0;
540
+ }
541
+ #sb_instagram p:empty { display: none; }
542
+ #sb_instagram .sb_instagram_header .sbi_header_text img.emoji{
543
+ margin-right: 3px !important;
544
+ }
545
+
546
+ /* No bio */
547
+ #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio h3{
548
+ padding-top: 9px !important;
549
+ }
550
+ #sb_instagram .sb_instagram_header .sbi_header_text.sbi_no_bio .sbi_bio_info{
551
+ clear: both;
552
+ }
553
+
554
+
555
+ /* Buttons */
556
+ #sb_instagram #sbi_load{
557
+ float: left;
558
+ clear: both;
559
+ width: 100%;
560
+ text-align: center;
561
+ }
562
+ #sb_instagram #sbi_load .fa-spinner{
563
+ display: none;
564
+ position: absolute;
565
+ top: 50%;
566
+ left: 50%;
567
+ margin: -8px 0 0 -7px;
568
+ font-size: 15px;
569
+ }
570
+ #sb_instagram #sbi_load{
571
+ opacity: 1;
572
+ transition: all 0.5s ease-in;
573
+ }
574
+ #sb_instagram .sbi_load_btn .sbi_btn_text, #sb_instagram .sbi_load_btn .sbi_loader{
575
+ opacity: 1;
576
+ transition: all 0.1s ease-in;
577
+ }
578
+ #sb_instagram .sbi_hidden{
579
+ opacity: 0 !important;
580
+ }
581
+ #sb_instagram #sbi_load .sbi_load_btn,
582
+ #sb_instagram .sbi_follow_btn a{
583
+ display: -moz-inline-stack;
584
+ display: inline-block;
585
+ vertical-align: top;
586
+ zoom: 1;
587
+ *display: inline;
588
+
589
+ padding: 7px 14px;
590
+ margin: 5px auto 0 auto;
591
+ background: #333;
592
+ color: #eee;
593
+ border: none;
594
+ color: #fff;
595
+ text-decoration: none;
596
+ font-size: 13px;
597
+ line-height: 1.5;
598
+
599
+ -moz-border-radius: 4px;
600
+ -webkit-border-radius: 4px;
601
+ border-radius: 4px;
602
+
603
+ -webkit-box-sizing: border-box;
604
+ -moz-box-sizing: border-box;
605
+ box-sizing: border-box;
606
+ }
607
+ #sb_instagram #sbi_load .sbi_load_btn {
608
+ position: relative;
609
+ }
610
+ /* Follow button */
611
+ #sb_instagram .sbi_follow_btn{
612
+ display: -moz-inline-stack;
613
+ display: inline-block;
614
+ vertical-align: top;
615
+ zoom: 1;
616
+ *display: inline;
617
+ text-align: center;
618
+ }
619
+ #sb_instagram .sbi_follow_btn.sbi_top{
620
+ display: block;
621
+ margin-bottom: 5px;
622
+ }
623
+ #sb_instagram .sbi_follow_btn a{
624
+ background: #408bd1;
625
+ color: #fff;
626
+ }
627
+ #sb_instagram .sbi_follow_btn a,
628
+ #sb_instagram .sbi_follow_btn a,
629
+ #sb_instagram #sbi_load .sbi_load_btn{
630
+ transition: all 0.1s ease-in;
631
+ }
632
+ /* Hover state for default colors */
633
+ #sb_instagram #sbi_load .sbi_load_btn:hover{
634
+ outline: none;
635
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
636
+ }
637
+ #sb_instagram .sbi_follow_btn a:hover,
638
+ #sb_instagram .sbi_follow_btn a:focus{
639
+ outline: none;
640
+ box-shadow: inset 0 0 10px 20px #359dff;
641
+ }
642
+ /* If a custom color is applied then just use opacity for the hover effect */
643
+ #sb_instagram .sbi_follow_btn.sbi_custom a:hover,
644
+ #sb_instagram .sbi_follow_btn.sbi_custom a:focus,
645
+ #sb_instagram #sbi_load .sbi_load_btn.sbi_custom:hover{
646
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
647
+ }
648
+ /* Active state */
649
+ #sb_instagram .sbi_follow_btn a:active,
650
+ #sb_instagram #sbi_load .sbi_load_btn:active{
651
+ box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
652
+ }
653
+
654
+ #sb_instagram .sbi_follow_btn .fa,
655
+ #sb_instagram .sbi_follow_btn svg{
656
+ margin-bottom: -1px;
657
+ margin-right: 7px;
658
+ font-size: 15px;
659
+ }
660
+ #sb_instagram .sbi_follow_btn svg{
661
+ vertical-align: -.125em;
662
+ }
663
+ #sb_instagram #sbi_load .sbi_follow_btn{
664
+ margin-left: 5px;
665
+ }
666
+
667
+ /* Error messages */
668
+ #sb_instagram .sb_instagram_error{
669
+ width: 100%;
670
+ text-align: center;
671
+ line-height: 1.4;
672
+ }
673
+
674
+ /* Mod only error msgs */
675
+ #sbi_mod_error{
676
+ display: none;
677
+ border: 1px solid #ddd;
678
+ background: #eee;
679
+ color: #333;
680
+ margin: 10px 0 0;
681
+ padding: 10px 15px;
682
+ font-size: 13px;
683
+ text-align: center;
684
+ clear: both;
685
+
686
+ -moz-border-radius: 4px;
687
+ -webkit-border-radius: 4px;
688
+ border-radius: 4px;
689
+ }
690
+ #sbi_mod_error br {
691
+ display: initial !important;
692
+ }
693
+ #sbi_mod_error p{
694
+ padding: 5px 0 !important;
695
+ margin: 0 !important;
696
+ line-height: 1.3 !important;
697
+ }
698
+ #sbi_mod_error ol,
699
+ #sbi_mod_error ul{
700
+ padding: 5px 0 5px 20px !important;
701
+ margin: 0 !important;
702
+ }
703
+ #sbi_mod_error li{
704
+ padding: 1px 0 !important;
705
+ margin: 0 !important;
706
+ }
707
+ #sbi_mod_error span{
708
+ font-size: 12px;
709
+ }
710
+
711
+ /* Medium */
712
+ #sb_instagram.sbi_medium .sbi_playbtn,
713
+ #sb_instagram.sbi_medium .sbi_photo_wrap .svg-inline--fa.fa-play{
714
+ margin-top: -12px;
715
+ margin-left: -9px;
716
+ font-size: 23px;
717
+ }
718
+ #sb_instagram.sbi_medium .sbi_type_carousel .sbi_photo_wrap .fa-clone{
719
+ right: 8px;
720
+ top: 8px;
721
+ font-size: 18px;
722
+ }
723
+ /* Small */
724
+ #sb_instagram.sbi_small .sbi_playbtn,
725
+ #sb_instagram.sbi_small .sbi_photo_wrap .svg-inline--fa.fa-play{
726
+ margin-top: -9px;
727
+ margin-left: -7px;
728
+ font-size: 18px;
729
+ }
730
+ #sb_instagram.sbi_small .sbi_type_carousel .sbi_photo_wrap .fa-clone{
731
+ right: 5px;
732
+ top: 5px;
733
+ font-size: 12px;
734
+ }
735
+
736
+ /* Media queries */
737
+ @media all and (max-width: 640px){
738
+ /* Make 3-6 cols into 2 col */
739
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
740
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
741
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
742
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item{
743
+ width: 50%;
744
+ }
745
+ /* Make 7-10 cols into 4 col */
746
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
747
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
748
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
749
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
750
+ width: 25%;
751
+ }
752
+ /* On mobile make the min-width 100% */
753
+ #sb_instagram.sbi_width_resp{
754
+ width: 100% !important;
755
+ }
756
+ }
757
+ @media all and (max-width: 480px){
758
+ /* Make all cols into 1 col */
759
+ #sb_instagram.sbi_col_3 #sbi_images .sbi_item,
760
+ #sb_instagram.sbi_col_4 #sbi_images .sbi_item,
761
+ #sb_instagram.sbi_col_5 #sbi_images .sbi_item,
762
+ #sb_instagram.sbi_col_6 #sbi_images .sbi_item,
763
+ #sb_instagram.sbi_col_7 #sbi_images .sbi_item,
764
+ #sb_instagram.sbi_col_8 #sbi_images .sbi_item,
765
+ #sb_instagram.sbi_col_9 #sbi_images .sbi_item,
766
+ #sb_instagram.sbi_col_10 #sbi_images .sbi_item{
767
+ width: 100%;
768
+ }
769
+ }
770
+
771
+ /* NO JS */
772
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap{
773
+ box-sizing: border-box;
774
+ position: relative;
775
+ overflow: hidden;
776
+ }
777
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo_wrap:before {
778
+ content: "";
779
+ display: block;
780
+ padding-top: 100%;
781
+ z-index: -300;
782
+ }
783
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item .sbi_photo {
784
+ position: absolute;
785
+ top: 0;
786
+ left: 0;
787
+ bottom: 0;
788
+ right: 0;
789
+ }
790
+ #sb_instagram.sbi_no_js #sbi_images .sbi_item.sbi_transition {
791
+ opacity: 1;
792
+ max-height: 640px;
793
+ }
794
+ #sb_instagram.sbi_no_js .sbi_photo img,
795
+ #sb_instagram.sbi_no_js .sbi_load_btn{
796
+ display: none;
797
+ }
798
+ #sb_instagram #sbi_images .sbi_js_load_disabled .sbi_imgLiquid_ready.sbi_photo {
799
+ padding-bottom: 0 !important;
800
+ }
801
+ #sb_instagram #sbi_mod_error .sb_frontend_btn {
802
+ display: inline-block;
803
+ padding: 6px 10px;
804
+ background: #ddd;
805
+ background: rgba(0,0,0,.1);
806
+ text-decoration: none;
807
+ border-radius: 5px;
808
+ margin-top: 10px;
809
+ color: #444
810
+ }
811
+
812
+ #sb_instagram #sbi_mod_error .sb_frontend_btn:hover {
813
+ background: #ccc;
814
+ background: rgba(0,0,0,.15)
815
+ }
816
+
817
+ #sb_instagram #sbi_mod_error .sb_frontend_btn .fa {
818
+ margin-right: 2px
819
  }
img/about/api-error.png ADDED
Binary file
img/about/icon-full.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg viewBox="0 0 37 28" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.29 26.462c.328.375.75.562 1.266.562s.937-.187 1.266-.562L35.563 5.79c.329-.328.493-.75.493-1.265 0-.516-.164-.938-.493-1.266L32.962.728a1.567 1.567 0 00-1.23-.563c-.493 0-.926.188-1.301.563L13.556 17.603 5.681 9.728c-.375-.375-.808-.563-1.301-.563-.492 0-.902.188-1.23.563L.548 12.259c-.328.328-.492.75-.492 1.265 0 .516.164.938.492 1.266L12.29 26.462z" fill="#6ab255" fill-rule="nonzero"/></svg>
img/about/icon-none.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg viewBox="0 0 33 33" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M27.592 32.359a1.928 1.928 0 01-1.417.583 1.928 1.928 0 01-1.416-.583l-8.084-8.084-8.083 8.084a1.928 1.928 0 01-1.417.583 1.93 1.93 0 01-1.417-.583l-4.5-4.5a1.932 1.932 0 01-.583-1.417c0-.555.195-1.028.583-1.417l8.084-8.083-8.084-8.084a1.931 1.931 0 01-.583-1.416c0-.556.195-1.028.583-1.417l4.5-4.5A1.93 1.93 0 017.175.942c.556 0 1.028.194 1.417.583l8.083 8.083 8.084-8.083a1.928 1.928 0 011.416-.583c.556 0 1.028.194 1.417.583l4.5 4.5c.389.389.583.861.583 1.417 0 .555-.194 1.027-.583 1.416l-8.083 8.084 8.083 8.083c.389.389.583.862.583 1.417 0 .556-.194 1.028-.583 1.417l-4.5 4.5z" fill="#d83638" fill-rule="nonzero"/></svg>
img/about/icon-partial.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg viewBox="0 0 53 53" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-miterlimit="10"><path d="M37.592 42.359a1.928 1.928 0 01-1.417.583 1.928 1.928 0 01-1.416-.583l-8.084-8.084-8.083 8.084a1.928 1.928 0 01-1.417.583 1.93 1.93 0 01-1.417-.583l-4.5-4.5a1.932 1.932 0 01-.583-1.417c0-.556.195-1.028.583-1.417l8.084-8.083-8.084-8.084a1.93 1.93 0 01-.583-1.416c0-.556.195-1.028.583-1.417l4.5-4.5a1.93 1.93 0 011.417-.584 1.93 1.93 0 011.417.584l8.083 8.083 8.084-8.083a1.928 1.928 0 011.416-.584 1.93 1.93 0 011.417.584l4.5 4.5c.389.389.583.861.583 1.417 0 .555-.194 1.028-.583 1.416l-8.083 8.084 8.083 8.083c.389.389.583.861.583 1.417s-.194 1.028-.583 1.417l-4.5 4.5z" fill="none" stroke="#d83638" stroke-width="2" stroke-dasharray="4,2"/></svg>
img/about/plugin-fb.png ADDED
Binary file
img/about/plugin-mi.png ADDED
Binary file
img/about/plugin-om.png ADDED
Binary file
img/about/plugin-rp.png ADDED
Binary file
img/about/plugin-seo.png ADDED
Binary file
img/about/plugin-smtp.png ADDED
Binary file
img/about/plugin-tw.jpg ADDED
Binary file
img/about/plugin-wpforms.png ADDED
Binary file
img/about/plugin-yt.png ADDED
Binary file
img/about/steps.png ADDED
Binary file
img/about/team.jpg ADDED
Binary file
img/balloon-120.png ADDED
Binary file
img/insta-logo.png ADDED
Binary file
img/sbi-icon-offer.png CHANGED
Binary file
inc/admin/PluginSilentUpgrader.php ADDED
@@ -0,0 +1,576 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Sbi\Helpers;
4
+
5
+ use WP_Error;
6
+ use WP_Upgrader;
7
+ use WP_Filesystem_Base;
8
+
9
+ /** \WP_Upgrader class */
10
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
11
+
12
+ /** \Plugin_Upgrader class */
13
+ require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
14
+
15
+ /**
16
+ * In WP 5.3 a PHP 5.6 splat operator (...$args) was added to \WP_Upgrader_Skin::feedback().
17
+ * We need to remove all calls to *Skin::feedback() method, as we can't override it in own Skins
18
+ * without breaking support for PHP 5.3-5.5.
19
+ *
20
+ * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
21
+ *
22
+ * @since 1.5.6.1
23
+ */
24
+ class PluginSilentUpgrader extends \Plugin_Upgrader {
25
+
26
+ /**
27
+ * Run an upgrade/installation.
28
+ *
29
+ * Attempts to download the package (if it is not a local file), unpack it, and
30
+ * install it in the destination folder.
31
+ *
32
+ * @since 1.5.6.1
33
+ *
34
+ * @param array $options {
35
+ * Array or string of arguments for upgrading/installing a package.
36
+ *
37
+ * @type string $package The full path or URI of the package to install.
38
+ * Default empty.
39
+ * @type string $destination The full path to the destination folder.
40
+ * Default empty.
41
+ * @type bool $clear_destination Whether to delete any files already in the
42
+ * destination folder. Default false.
43
+ * @type bool $clear_working Whether to delete the files form the working
44
+ * directory after copying to the destination.
45
+ * Default false.
46
+ * @type bool $abort_if_destination_exists Whether to abort the installation if the destination
47
+ * folder already exists. When true, `$clear_destination`
48
+ * should be false. Default true.
49
+ * @type bool $is_multi Whether this run is one of multiple upgrade/installation
50
+ * actions being performed in bulk. When true, the skin
51
+ * WP_Upgrader::header() and WP_Upgrader::footer()
52
+ * aren't called. Default false.
53
+ * @type array $hook_extra Extra arguments to pass to the filter hooks called by
54
+ * WP_Upgrader::run().
55
+ * }
56
+ * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error,
57
+ * or false if unable to connect to the filesystem.
58
+ */
59
+ public function run( $options ) {
60
+
61
+ $defaults = array(
62
+ 'package' => '', // Please always pass this.
63
+ 'destination' => '', // And this
64
+ 'clear_destination' => false,
65
+ 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
66
+ 'clear_working' => true,
67
+ 'is_multi' => false,
68
+ 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
69
+ );
70
+
71
+ $options = wp_parse_args( $options, $defaults );
72
+
73
+ /**
74
+ * Filters the package options before running an update.
75
+ *
76
+ * See also {@see 'upgrader_process_complete'}.
77
+ *
78
+ * @since 4.3.0
79
+ *
80
+ * @param array $options {
81
+ * Options used by the upgrader.
82
+ *
83
+ * @type string $package Package for update.
84
+ * @type string $destination Update location.
85
+ * @type bool $clear_destination Clear the destination resource.
86
+ * @type bool $clear_working Clear the working resource.
87
+ * @type bool $abort_if_destination_exists Abort if the Destination directory exists.
88
+ * @type bool $is_multi Whether the upgrader is running multiple times.
89
+ * @type array $hook_extra {
90
+ * Extra hook arguments.
91
+ *
92
+ * @type string $action Type of action. Default 'update'.
93
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
94
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
95
+ * @type string $plugin Path to the plugin file relative to the plugins directory.
96
+ * @type string $theme The stylesheet or template name of the theme.
97
+ * @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme',
98
+ * or 'core'.
99
+ * @type object $language_update The language pack update offer.
100
+ * }
101
+ * }
102
+ */
103
+ $options = apply_filters( 'upgrader_package_options', $options );
104
+
105
+ if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times
106
+ $this->skin->header();
107
+ }
108
+
109
+ // Connect to the Filesystem first.
110
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
111
+ // Mainly for non-connected filesystem.
112
+ if ( ! $res ) {
113
+ if ( ! $options['is_multi'] ) {
114
+ $this->skin->footer();
115
+ }
116
+ return false;
117
+ }
118
+
119
+ $this->skin->before();
120
+
121
+ if ( is_wp_error( $res ) ) {
122
+ $this->skin->error( $res );
123
+ $this->skin->after();
124
+ if ( ! $options['is_multi'] ) {
125
+ $this->skin->footer();
126
+ }
127
+ return $res;
128
+ }
129
+
130
+ /*
131
+ * Download the package (Note, This just returns the filename
132
+ * of the file if the package is a local file)
133
+ */
134
+ $download = $this->download_package( $options['package'], true );
135
+
136
+ // Allow for signature soft-fail.
137
+ // WARNING: This may be removed in the future.
138
+ if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {
139
+
140
+ // Don't output the 'no signature could be found' failure message for now.
141
+ if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) {
142
+ // Outout the failure error as a normal feedback, and not as an error:
143
+ //$this->skin->feedback( $download->get_error_message() );
144
+
145
+ // Report this failure back to WordPress.org for debugging purposes.
146
+ wp_version_check(
147
+ array(
148
+ 'signature_failure_code' => $download->get_error_code(),
149
+ 'signature_failure_data' => $download->get_error_data(),
150
+ )
151
+ );
152
+ }
153
+
154
+ // Pretend this error didn't happen.
155
+ $download = $download->get_error_data( 'softfail-filename' );
156
+ }
157
+
158
+ if ( is_wp_error( $download ) ) {
159
+ $this->skin->error( $download );
160
+ $this->skin->after();
161
+ if ( ! $options['is_multi'] ) {
162
+ $this->skin->footer();
163
+ }
164
+ return $download;
165
+ }
166
+
167
+ $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file
168
+
169
+ // Unzips the file into a temporary directory.
170
+ $working_dir = $this->unpack_package( $download, $delete_package );
171
+ if ( is_wp_error( $working_dir ) ) {
172
+ $this->skin->error( $working_dir );
173
+ $this->skin->after();
174
+ if ( ! $options['is_multi'] ) {
175
+ $this->skin->footer();
176
+ }
177
+ return $working_dir;
178
+ }
179
+
180
+ // With the given options, this installs it to the destination directory.
181
+ $result = $this->install_package(
182
+ array(
183
+ 'source' => $working_dir,
184
+ 'destination' => $options['destination'],
185
+ 'clear_destination' => $options['clear_destination'],
186
+ 'abort_if_destination_exists' => $options['abort_if_destination_exists'],
187
+ 'clear_working' => $options['clear_working'],
188
+ 'hook_extra' => $options['hook_extra'],
189
+ )
190
+ );
191
+
192
+ $this->skin->set_result( $result );
193
+ if ( is_wp_error( $result ) ) {
194
+ $this->skin->error( $result );
195
+ //$this->skin->feedback( 'process_failed' );
196
+ } else {
197
+ // Installation succeeded.
198
+ //$this->skin->feedback( 'process_success' );
199
+ }
200
+
201
+ $this->skin->after();
202
+
203
+ if ( ! $options['is_multi'] ) {
204
+
205
+ /**
206
+ * Fires when the upgrader process is complete.
207
+ *
208
+ * See also {@see 'upgrader_package_options'}.
209
+ *
210
+ * @since 3.6.0
211
+ * @since 3.7.0 Added to WP_Upgrader::run().
212
+ * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
213
+ *
214
+ * @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a
215
+ * Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
216
+ * @param array $hook_extra {
217
+ * Array of bulk item update data.
218
+ *
219
+ * @type string $action Type of action. Default 'update'.
220
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
221
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
222
+ * @type array $plugins Array of the basename paths of the plugins' main files.
223
+ * @type array $themes The theme slugs.
224
+ * @type array $translations {
225
+ * Array of translations update data.
226
+ *
227
+ * @type string $language The locale the translation is for.
228
+ * @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'.
229
+ * @type string $slug Text domain the translation is for. The slug of a theme/plugin or
230
+ * 'default' for core translations.
231
+ * @type string $version The version of a theme, plugin, or core.
232
+ * }
233
+ * }
234
+ */
235
+ do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );
236
+
237
+ $this->skin->footer();
238
+ }
239
+
240
+ return $result;
241
+ }
242
+
243
+ /**
244
+ * Toggle maintenance mode for the site.
245
+ *
246
+ * Create/delete the maintenance file to enable/disable maintenance mode.
247
+ *
248
+ * @since 2.8.0
249
+ *
250
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
251
+ *
252
+ * @param bool $enable True to enable maintenance mode, false to disable.
253
+ */
254
+ public function maintenance_mode( $enable = false ) {
255
+ global $wp_filesystem;
256
+ $file = $wp_filesystem->abspath() . '.maintenance';
257
+ if ( $enable ) {
258
+ //$this->skin->feedback( 'maintenance_start' );
259
+ // Create maintenance file to signal that we are upgrading
260
+ $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
261
+ $wp_filesystem->delete( $file );
262
+ $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
263
+ } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
264
+ //$this->skin->feedback( 'maintenance_end' );
265
+ $wp_filesystem->delete( $file );
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Download a package.
271
+ *
272
+ * @since 2.8.0
273
+ *
274
+ * @param string $package The URI of the package. If this is the full path to an
275
+ * existing local file, it will be returned untouched.
276
+ * @param bool $check_signatures Whether to validate file signatures. Default false.
277
+ * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object.
278
+ */
279
+ public function download_package( $package, $check_signatures = false ) {
280
+
281
+ /**
282
+ * Filters whether to return the package.
283
+ *
284
+ * @since 3.7.0
285
+ *
286
+ * @param bool $reply Whether to bail without returning the package.
287
+ * Default false.
288
+ * @param string $package The package file name.
289
+ * @param WP_Upgrader $this The WP_Upgrader instance.
290
+ */
291
+ $reply = apply_filters( 'upgrader_pre_download', false, $package, $this );
292
+ if ( false !== $reply ) {
293
+ return $reply;
294
+ }
295
+
296
+ if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote?
297
+ return $package; //must be a local file..
298
+ }
299
+
300
+ if ( empty( $package ) ) {
301
+ return new WP_Error( 'no_package', $this->strings['no_package'] );
302
+ }
303
+
304
+ //$this->skin->feedback( 'downloading_package', $package );
305
+
306
+ $download_file = download_url( $package, 300, $check_signatures );
307
+
308
+ if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) {
309
+ return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
310
+ }
311
+
312
+ return $download_file;
313
+ }
314
+
315
+ /**
316
+ * Unpack a compressed package file.
317
+ *
318
+ * @since 2.8.0
319
+ *
320
+ * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
321
+ *
322
+ * @param string $package Full path to the package file.
323
+ * @param bool $delete_package Optional. Whether to delete the package file after attempting
324
+ * to unpack it. Default true.
325
+ * @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure.
326
+ */
327
+ public function unpack_package( $package, $delete_package = true ) {
328
+ global $wp_filesystem;
329
+
330
+ //$this->skin->feedback( 'unpack_package' );
331
+
332
+ $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
333
+
334
+ //Clean up contents of upgrade directory beforehand.
335
+ $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
336
+ if ( ! empty( $upgrade_files ) ) {
337
+ foreach ( $upgrade_files as $file ) {
338
+ $wp_filesystem->delete( $upgrade_folder . $file['name'], true );
339
+ }
340
+ }
341
+
342
+ // We need a working directory - Strip off any .tmp or .zip suffixes
343
+ $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
344
+
345
+ // Clean up working directory
346
+ if ( $wp_filesystem->is_dir( $working_dir ) ) {
347
+ $wp_filesystem->delete( $working_dir, true );
348
+ }
349
+
350
+ // Unzip package to working directory
351
+ $result = unzip_file( $package, $working_dir );
352
+
353
+ // Once extracted, delete the package if required.
354
+ if ( $delete_package ) {
355
+ unlink( $package );
356
+ }
357
+
358
+ if ( is_wp_error( $result ) ) {
359
+ $wp_filesystem->delete( $working_dir, true );
360
+ if ( 'incompatible_archive' == $result->get_error_code() ) {
361
+ return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
362
+ }
363
+ return $result;
364
+ }
365
+
366
+ return $working_dir;
367
+ }
368
+
369
+ /**
370
+ * Install a package.
371
+ *
372
+ * Copies the contents of a package form a source directory, and installs them in
373
+ * a destination directory. Optionally removes the source. It can also optionally
374
+ * clear out the destination folder if it already exists.
375
+ *
376
+ * @since 2.8.0
377
+ *
378
+ * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
379
+ * @global array $wp_theme_directories
380
+ *
381
+ * @param array|string $args {
382
+ * Optional. Array or string of arguments for installing a package. Default empty array.
383
+ *
384
+ * @type string $source Required path to the package source. Default empty.
385
+ * @type string $destination Required path to a folder to install the package in.
386
+ * Default empty.
387
+ * @type bool $clear_destination Whether to delete any files already in the destination
388
+ * folder. Default false.
389
+ * @type bool $clear_working Whether to delete the files form the working directory
390
+ * after copying to the destination. Default false.
391
+ * @type bool $abort_if_destination_exists Whether to abort the installation if
392
+ * the destination folder already exists. Default true.
393
+ * @type array $hook_extra Extra arguments to pass to the filter hooks called by
394
+ * WP_Upgrader::install_package(). Default empty array.
395
+ * }
396
+ *
397
+ * @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure.
398
+ */
399
+ public function install_package( $args = array() ) {
400
+ global $wp_filesystem, $wp_theme_directories;
401
+
402
+ $defaults = array(
403
+ 'source' => '', // Please always pass this
404
+ 'destination' => '', // and this
405
+ 'clear_destination' => false,
406
+ 'clear_working' => false,
407
+ 'abort_if_destination_exists' => true,
408
+ 'hook_extra' => array(),
409
+ );
410
+
411
+ $args = wp_parse_args( $args, $defaults );
412
+
413
+ // These were previously extract()'d.
414
+ $source = $args['source'];
415
+ $destination = $args['destination'];
416
+ $clear_destination = $args['clear_destination'];
417
+
418
+ set_time_limit( 300 );
419
+
420
+ if ( empty( $source ) || empty( $destination ) ) {
421
+ return new WP_Error( 'bad_request', $this->strings['bad_request'] );
422
+ }
423
+ //$this->skin->feedback( 'installing_package' );
424
+
425
+ /**
426
+ * Filters the install response before the installation has started.
427
+ *
428
+ * Returning a truthy value, or one that could be evaluated as a WP_Error
429
+ * will effectively short-circuit the installation, returning that value
430
+ * instead.
431
+ *
432
+ * @since 2.8.0
433
+ *
434
+ * @param bool|WP_Error $response Response.
435
+ * @param array $hook_extra Extra arguments passed to hooked filters.
436
+ */
437
+ $res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );
438
+
439
+ if ( is_wp_error( $res ) ) {
440
+ return $res;
441
+ }
442
+
443
+ //Retain the Original source and destinations
444
+ $remote_source = $args['source'];
445
+ $local_destination = $destination;
446
+
447
+ $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) );
448
+ $remote_destination = $wp_filesystem->find_folder( $local_destination );
449
+
450
+ //Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
451
+ if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents.
452
+ $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] );
453
+ } elseif ( count( $source_files ) == 0 ) {
454
+ return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files?
455
+ } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
456
+ $source = trailingslashit( $args['source'] );
457
+ }
458
+
459
+ /**
460
+ * Filters the source file location for the upgrade package.
461
+ *
462
+ * @since 2.8.0
463
+ * @since 4.4.0 The $hook_extra parameter became available.
464
+ *
465
+ * @param string $source File source location.
466
+ * @param string $remote_source Remote file source location.
467
+ * @param WP_Upgrader $this WP_Upgrader instance.
468
+ * @param array $hook_extra Extra arguments passed to hooked filters.
469
+ */
470
+ $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );
471
+
472
+ if ( is_wp_error( $source ) ) {
473
+ return $source;
474
+ }
475
+
476
+ // Has the source location changed? If so, we need a new source_files list.
477
+ if ( $source !== $remote_source ) {
478
+ $source_files = array_keys( $wp_filesystem->dirlist( $source ) );
479
+ }
480
+
481
+ /*
482
+ * Protection against deleting files in any important base directories.
483
+ * Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
484
+ * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
485
+ * to copy the directory into the directory, whilst they pass the source
486
+ * as the actual files to copy.
487
+ */
488
+ $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
489
+
490
+ if ( is_array( $wp_theme_directories ) ) {
491
+ $protected_directories = array_merge( $protected_directories, $wp_theme_directories );
492
+ }
493
+
494
+ if ( in_array( $destination, $protected_directories ) ) {
495
+ $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
496
+ $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
497
+ }
498
+
499
+ if ( $clear_destination ) {
500
+ // We're going to clear the destination if there's something there.
501
+ //$this->skin->feedback( 'remove_old' );
502
+
503
+ $removed = $this->clear_destination( $remote_destination );
504
+
505
+ /**
506
+ * Filters whether the upgrader cleared the destination.
507
+ *
508
+ * @since 2.8.0
509
+ *
510
+ * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure
511
+ * @param string $local_destination The local package destination.
512
+ * @param string $remote_destination The remote package destination.
513
+ * @param array $hook_extra Extra arguments passed to hooked filters.
514
+ */
515
+ $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
516
+
517
+ if ( is_wp_error( $removed ) ) {
518
+ return $removed;
519
+ }
520
+ } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) {
521
+ //If we're not clearing the destination folder and something exists there already, Bail.
522
+ //But first check to see if there are actually any files in the folder.
523
+ $_files = $wp_filesystem->dirlist( $remote_destination );
524
+ if ( ! empty( $_files ) ) {
525
+ $wp_filesystem->delete( $remote_source, true ); //Clear out the source files.
526
+ return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination );
527
+ }
528
+ }
529
+
530
+ //Create destination if needed
531
+ if ( ! $wp_filesystem->exists( $remote_destination ) ) {
532
+ if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
533
+ return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );
534
+ }
535
+ }
536
+ // Copy new version of item into place.
537
+ $result = copy_dir( $source, $remote_destination );
538
+ if ( is_wp_error( $result ) ) {
539
+ if ( $args['clear_working'] ) {
540
+ $wp_filesystem->delete( $remote_source, true );
541
+ }
542
+ return $result;
543
+ }
544
+
545
+ //Clear the Working folder?
546
+ if ( $args['clear_working'] ) {
547
+ $wp_filesystem->delete( $remote_source, true );
548
+ }
549
+
550
+ $destination_name = basename( str_replace( $local_destination, '', $destination ) );
551
+ if ( '.' == $destination_name ) {
552
+ $destination_name = '';
553
+ }
554
+
555
+ $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );
556
+
557
+ /**
558
+ * Filters the installation response after the installation has finished.
559
+ *
560
+ * @since 2.8.0
561
+ *
562
+ * @param bool $response Installation response.
563
+ * @param array $hook_extra Extra arguments passed to hooked filters.
564
+ * @param array $result Installation result data.
565
+ */
566
+ $res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result );
567
+
568
+ if ( is_wp_error( $res ) ) {
569
+ $this->result = $res;
570
+ return $res;
571
+ }
572
+
573
+ //Bombard the calling function will all the info which we've just used.
574
+ return $this->result;
575
+ }
576
+ }
inc/admin/PluginSilentUpgraderSkin.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Sbi\Helpers;
4
+
5
+ /** \WP_Upgrader_Skin class */
6
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
7
+
8
+ /**
9
+ * Class PluginSilentUpgraderSkin.
10
+ *
11
+ * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
12
+ *
13
+ * @since 1.5.6.1
14
+ */
15
+ class PluginSilentUpgraderSkin extends \WP_Upgrader_Skin {
16
+
17
+ /**
18
+ * Empty out the header of its HTML content and only check to see if it has
19
+ * been performed or not.
20
+ *
21
+ * @since 1.5.6.1
22
+ */
23
+ public function header() {
24
+ }
25
+
26
+ /**
27
+ * Empty out the footer of its HTML contents.
28
+ *
29
+ * @since 1.5.6.1
30
+ */
31
+ public function footer() {
32
+ }
33
+
34
+ /**
35
+ * Instead of outputting HTML for errors, just return them.
36
+ * Ajax request will just ignore it.
37
+ *
38
+ * @since 1.5.6.1
39
+ *
40
+ * @param array $errors Array of errors with the install process.
41
+ *
42
+ * @return array
43
+ */
44
+ public function error( $errors ) {
45
+ return $errors;
46
+ }
47
+
48
+ /**
49
+ * Empty out JavaScript output that calls function to decrement the update counts.
50
+ *
51
+ * @since 1.5.6.1
52
+ *
53
+ * @param string $type Type of update count to decrement.
54
+ */
55
+ public function decrement_update_count( $type ) {
56
+ }
57
+ }
inc/admin/actions.php CHANGED
@@ -1,1182 +1,1283 @@
1
- <?php
2
- /**
3
- * Includes functions related to actions while in the admin area.
4
- *
5
- * - All AJAX related features
6
- * - Enqueueing of JS and CSS files
7
- * - Settings link on "Plugins" page
8
- * - Creation of local avatar image files
9
- * - Connecting accounts on the "Configure" tab
10
- * - Displaying admin notices
11
- * - Clearing caches
12
- */
13
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
-
15
- function sb_instagram_admin_style() {
16
- wp_register_style( 'sb_instagram_admin_css', SBI_PLUGIN_URL . 'css/sb-instagram-admin.css', array(), SBIVER );
17
- wp_enqueue_style( 'sb_instagram_font_awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css' );
18
- wp_enqueue_style( 'sb_instagram_admin_css' );
19
- wp_enqueue_style( 'wp-color-picker' );
20
- }
21
- add_action( 'admin_enqueue_scripts', 'sb_instagram_admin_style' );
22
-
23
- function sb_instagram_admin_scripts() {
24
- wp_enqueue_script( 'sb_instagram_admin_js', SBI_PLUGIN_URL . 'js/sb-instagram-admin-2-2.js', array(), SBIVER );
25
- wp_localize_script( 'sb_instagram_admin_js', 'sbiA', array(
26
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
27
- 'sbi_nonce' => wp_create_nonce( 'sbi_nonce' )
28
- )
29
- );
30
- if( !wp_script_is('jquery-ui-draggable') ) {
31
- wp_enqueue_script(
32
- array(
33
- 'jquery',
34
- 'jquery-ui-core',
35
- 'jquery-ui-draggable'
36
- )
37
- );
38
- }
39
- wp_enqueue_script(
40
- array(
41
- 'hoverIntent',
42
- 'wp-color-picker'
43
- )
44
- );
45
- }
46
- add_action( 'admin_enqueue_scripts', 'sb_instagram_admin_scripts' );
47
-
48
- // Add a Settings link to the plugin on the Plugins page
49
- $sbi_plugin_file = 'instagram-feed/instagram-feed.php';
50
- add_filter( "plugin_action_links_{$sbi_plugin_file}", 'sbi_add_settings_link', 10, 2 );
51
-
52
- //modify the link by unshifting the array
53
- function sbi_add_settings_link( $links, $file ) {
54
- $sbi_settings_link = '<a href="' . admin_url( 'admin.php?page=sb-instagram-feed' ) . '">' . __( 'Settings', 'instagram-feed' ) . '</a>';
55
- array_unshift( $links, $sbi_settings_link );
56
-
57
- return $links;
58
- }
59
-
60
-
61
- /**
62
- * Called via ajax to automatically save access token and access token secret
63
- * retrieved with the big blue button
64
- */
65
- function sbi_auto_save_tokens() {
66
- $nonce = $_POST['sbi_nonce'];
67
-
68
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
69
- die ( 'You did not do this the right way!' );
70
- }
71
-
72
- wp_cache_delete ( 'alloptions', 'options' );
73
-
74
- $options = sbi_get_database_settings();
75
- $new_access_token = isset( $_POST['access_token'] ) ? sanitize_text_field( $_POST['access_token'] ) : false;
76
- $split_token = $new_access_token ? explode( '.', $new_access_token ) : array();
77
- $new_user_id = isset( $split_token[0] ) ? $split_token[0] : '';
78
-
79
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
80
- $test_connection_data = sbi_account_data_for_token( $new_access_token );
81
-
82
- $connected_accounts[ $new_user_id ] = array(
83
- 'access_token' => sbi_get_parts( $new_access_token ),
84
- 'user_id' => $test_connection_data['id'],
85
- 'username' => $test_connection_data['username'],
86
- 'is_valid' => $test_connection_data['is_valid'],
87
- 'last_checked' => $test_connection_data['last_checked'],
88
- 'profile_picture' => $test_connection_data['profile_picture'],
89
- );
90
-
91
- if ( !$options['sb_instagram_disable_resize'] ) {
92
- if ( sbi_create_local_avatar( $test_connection_data['username'], $test_connection_data['profile_picture'] ) ) {
93
- $connected_accounts[ $new_user_id ]['local_avatar'] = true;
94
- }
95
- } else {
96
- $connected_accounts[ $new_user_id ]['local_avatar'] = false;
97
- }
98
-
99
- $options['connected_accounts'] = $connected_accounts;
100
-
101
- update_option( 'sb_instagram_settings', $options );
102
-
103
- echo wp_json_encode( $connected_accounts[ $new_user_id ] );
104
-
105
- die();
106
- }
107
- add_action( 'wp_ajax_sbi_auto_save_tokens', 'sbi_auto_save_tokens' );
108
-
109
- function sbi_delete_local_avatar( $username ) {
110
- $upload = wp_upload_dir();
111
-
112
- $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $username . '.jpg' ); // get all matching images
113
- foreach ( $image_files as $file ) { // iterate files
114
- if ( is_file( $file ) ) {
115
- unlink( $file );
116
- }
117
- }
118
- }
119
-
120
- function sbi_create_local_avatar( $username, $file_name ) {
121
- $image_editor = wp_get_image_editor( $file_name );
122
-
123
- if ( ! is_wp_error( $image_editor ) ) {
124
- $upload = wp_upload_dir();
125
-
126
- $full_file_name = trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $username . '.jpg';
127
-
128
- $saved_image = $image_editor->save( $full_file_name );
129
-
130
- if ( ! $saved_image ) {
131
- global $sb_instagram_posts_manager;
132
-
133
- $sb_instagram_posts_manager->add_error( 'image_editor_save', array(
134
- __( 'Error saving edited image.', 'instagram-feed' ),
135
- $full_file_name
136
- ) );
137
- } else {
138
- return true;
139
- }
140
- } else {
141
- global $sb_instagram_posts_manager;
142
-
143
- $message = __( 'Error editing image.', 'instagram-feed' );
144
- if ( isset( $image_editor ) && isset( $image_editor->errors ) ) {
145
- foreach ( $image_editor->errors as $key => $item ) {
146
- $message .= ' ' . $key . '- ' . $item[0] . ' |';
147
- }
148
- }
149
-
150
- $sb_instagram_posts_manager->add_error( 'image_editor', array( $file_name, $message ) );
151
- }
152
- return false;
153
- }
154
-
155
- function sbi_connect_business_accounts() {
156
- $nonce = $_POST['sbi_nonce'];
157
-
158
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
159
- die ( 'You did not do this the right way!' );
160
- }
161
-
162
- $accounts = isset( $_POST['accounts'] ) ? json_decode( stripslashes( $_POST['accounts'] ), true ) : false;
163
- $options = sbi_get_database_settings();
164
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
165
-
166
- foreach ( $accounts as $account ) {
167
- $access_token = isset( $account['access_token'] ) ? $account['access_token'] : '';
168
- $page_access_token = isset( $account['page_access_token'] ) ? $account['page_access_token'] : '';
169
- $username = isset( $account['username'] ) ? $account['username'] : '';
170
- $name = isset( $account['name'] ) ? $account['name'] : '';
171
- $profile_picture = isset( $account['profile_picture_url'] ) ? $account['profile_picture_url'] : '';
172
- $user_id = isset( $account['id'] ) ? $account['id'] : '';
173
- $type = 'business';
174
-
175
- $connected_accounts[ $user_id ] = array(
176
- 'access_token' => $access_token,
177
- 'page_access_token' => $page_access_token,
178
- 'user_id' => $user_id,
179
- 'username' => $username,
180
- 'is_valid' => true,
181
- 'last_checked' => time(),
182
- 'profile_picture' => $profile_picture,
183
- 'name' => sbi_sanitize_emoji( $name ),
184
- 'type' => $type,
185
- 'use_tagged' => '1'
186
- );
187
-
188
- if ( !$options['sb_instagram_disable_resize'] ) {
189
- if ( sbi_create_local_avatar( $username, $profile_picture ) ) {
190
- $connected_accounts[ $user_id ]['local_avatar'] = true;
191
- }
192
- } else {
193
- $connected_accounts[ $user_id ]['local_avatar'] = false;
194
- }
195
-
196
- delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $user_id );
197
- }
198
-
199
- $options['connected_accounts'] = $connected_accounts;
200
-
201
- update_option( 'sb_instagram_settings', $options );
202
-
203
- echo wp_json_encode( $connected_accounts );
204
-
205
- die();
206
- }
207
- add_action( 'wp_ajax_sbi_connect_business_accounts', 'sbi_connect_business_accounts' );
208
-
209
- function sbi_auto_save_id() {
210
- $nonce = $_POST['sbi_nonce'];
211
-
212
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
213
- die ( 'You did not do this the right way!' );
214
- }
215
- if ( current_user_can( 'edit_posts' ) && isset( $_POST['id'] ) ) {
216
- $options = get_option( 'sb_instagram_settings', array() );
217
-
218
- $options['sb_instagram_user_id'] = array( sanitize_text_field( $_POST['id'] ) );
219
-
220
- update_option( 'sb_instagram_settings', $options );
221
- }
222
- die();
223
- }
224
- add_action( 'wp_ajax_sbi_auto_save_id', 'sbi_auto_save_id' );
225
-
226
- function sbi_test_token() {
227
- $access_token = isset( $_POST['access_token'] ) ? sanitize_text_field( $_POST['access_token'] ) : false;
228
- $account_id = isset( $_POST['account_id'] ) ? sanitize_text_field( $_POST['account_id'] ) : false;
229
- $options = sbi_get_database_settings();
230
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
231
-
232
- if ( $access_token ) {
233
- wp_cache_delete ( 'alloptions', 'options' );
234
-
235
- $number_dots = substr_count ( $access_token , '.' );
236
- $test_connection_data = array( 'error_message' => 'A successful connection could not be made. Please make sure your Access Token is valid.');
237
-
238
- if ( $number_dots > 1 ) {
239
- $split_token = explode( '.', $access_token );
240
- $new_user_id = isset( $split_token[0] ) ? $split_token[0] : '';
241
-
242
- $test_connection_data = sbi_account_data_for_token( $access_token );
243
- } else if (! empty( $account_id ) ) {
244
-
245
- if ( sbi_code_check( $access_token ) ) {
246
- $data = array(
247
- 'access_token' => $access_token,
248
- 'user_id' => $account_id,
249
- 'type' => 'basic'
250
- );
251
- $basic_account_attempt = new SB_Instagram_API_Connect( $data, 'header', array() );
252
- $basic_account_attempt->connect();
253
-
254
- if ( !$basic_account_attempt->is_wp_error() && ! $basic_account_attempt->is_instagram_error() ) {
255
- $new_data = $basic_account_attempt->get_data();
256
-
257
- $basic_account_access_token_connect = new SB_Instagram_API_Connect( $data, 'access_token', array() );
258
- $basic_account_access_token_connect->connect();
259
- if ( !$basic_account_access_token_connect->is_wp_error() && ! $basic_account_access_token_connect->is_instagram_error() ) {
260
-
261
- $token_data = $basic_account_access_token_connect->get_data();
262
- $expires_in = $token_data['expires_in'];
263
- $expires_timestamp = time() + $expires_in;
264
-
265
- $new_connected_account = array(
266
- 'access_token' => $access_token,
267
- 'account_type' => $new_data['account_type'],
268
- 'user_id' => $new_data['id'],
269
- 'username' => $new_data['username'],
270
- 'expires_timestamp' => $expires_timestamp,
271
- 'type' => 'basic'
272
- );
273
-
274
- $updated_options = sbi_connect_basic_account( $new_connected_account );
275
-
276
- echo wp_json_encode( $updated_options['connected_accounts'][ $new_data['id'] ] );
277
- die();
278
-
279
- }
280
-
281
- }
282
- }
283
-
284
- $url = 'https://graph.facebook.com/'.$account_id.'?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token='.sbi_maybe_clean( $access_token );
285
- $json = json_decode( sbi_business_account_request( $url, array( 'access_token' => $access_token ) ), true );
286
-
287
- if ( isset( $json['error'] ) && $json['error']['type'] === 'OAuthException' ) {
288
- $data = array(
289
- 'access_token' => $access_token,
290
- 'user_id' => $account_id,
291
- 'type' => 'basic'
292
- );
293
- $basic_account_attempt = new SB_Instagram_API_Connect( $data, 'header', array() );
294
- $basic_account_attempt->connect();
295
-
296
- if ( !$basic_account_attempt->is_wp_error() && ! $basic_account_attempt->is_instagram_error() ) {
297
- $new_data = $basic_account_attempt->get_data();
298
-
299
- $basic_account_access_token_connect = new SB_Instagram_API_Connect( $data, 'access_token', array() );
300
- $basic_account_access_token_connect->connect();
301
- if ( !$basic_account_access_token_connect->is_wp_error() && ! $basic_account_access_token_connect->is_instagram_error() ) {
302
-
303
- $token_data = $basic_account_access_token_connect->get_data();
304
- $expires_in = $token_data['expires_in'];
305
- $expires_timestamp = time() + $expires_in;
306
-
307
- $new_connected_account = array(
308
- 'access_token' => $access_token,
309
- 'account_type' => $new_data['account_type'],
310
- 'user_id' => $new_data['id'],
311
- 'username' => $new_data['username'],
312
- 'expires_timestamp' => $expires_timestamp,
313
- 'type' => 'basic'
314
- );
315
-
316
- $updated_options = sbi_connect_basic_account( $new_connected_account );
317
-
318
- echo wp_json_encode( $updated_options['connected_accounts'][ $new_data['id'] ] );
319
- die();
320
-
321
- }
322
-
323
- }
324
-
325
- die();
326
-
327
- } else {
328
- if ( isset( $json['id'] ) ) {
329
- $new_user_id = $json['id'];
330
- $test_connection_data = array(
331
- 'access_token' => $access_token,
332
- 'id' => $json['id'],
333
- 'username' => $json['username'],
334
- 'type' => 'business',
335
- 'is_valid' => true,
336
- 'last_checked' => time(),
337
- 'profile_picture' => $json['profile_picture_url']
338
- );
339
- }
340
- }
341
-
342
-
343
-
344
- delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $json['id'] );
345
-
346
- }
347
-
348
- if ( isset( $test_connection_data['error_message'] ) ) {
349
- echo $test_connection_data['error_message'];
350
- } elseif ( $test_connection_data !== false && ! empty( $new_user_id ) ) {
351
- $username = $test_connection_data['username'] ? $test_connection_data['username'] : $connected_accounts[ $new_user_id ]['username'];
352
- $user_id = $test_connection_data['id'] ? $test_connection_data['id'] : $connected_accounts[ $new_user_id ]['user_id'];
353
- $profile_picture = $test_connection_data['profile_picture'] ? $test_connection_data['profile_picture'] : $connected_accounts[ $new_user_id ]['profile_picture'];
354
- $type = isset( $test_connection_data['type'] ) ? $test_connection_data['type'] : 'personal';
355
- $connected_accounts[ $new_user_id ] = array(
356
- 'access_token' => sbi_get_parts( $access_token ),
357
- 'user_id' => $user_id,
358
- 'username' => $username,
359
- 'type' => $type,
360
- 'is_valid' => true,
361
- 'last_checked' => $test_connection_data['last_checked'],
362
- 'profile_picture' => $profile_picture
363
- );
364
-
365
- if ( !$options['sb_instagram_disable_resize'] ) {
366
- if ( sbi_create_local_avatar( $username, $profile_picture ) ) {
367
- $connected_accounts[ $new_user_id ]['local_avatar'] = true;
368
- }
369
- } else {
370
- $connected_accounts[ $new_user_id ]['local_avatar'] = false;
371
- }
372
-
373
- if ( $type === 'business' ) {
374
- $url = 'https://graph.facebook.com/'.$user_id.'/tags?user_id='.$user_id.'&fields=id&limit=1&access_token='.sbi_maybe_clean( $access_token );
375
- $args = array(
376
- 'timeout' => 60,
377
- 'sslverify' => false
378
- );
379
- $response = wp_remote_get( $url, $args );
380
-
381
- if ( ! is_wp_error( $response ) ) {
382
- // certain ways of representing the html for double quotes causes errors so replaced here.
383
- $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
384
- if ( isset( $response['data'] ) ) {
385
- $connected_accounts[ $new_user_id ]['use_tagged'] = '1';
386
- }
387
- }
388
- }
389
-
390
- delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $user_id );
391
-
392
- $options['connected_accounts'] = $connected_accounts;
393
-
394
- update_option( 'sb_instagram_settings', $options );
395
-
396
- echo wp_json_encode( $connected_accounts[ $new_user_id ] );
397
- } else {
398
- echo 'A successful connection could not be made. Please make sure your Access Token is valid.';
399
- }
400
-
401
- }
402
-
403
- die();
404
- }
405
- add_action( 'wp_ajax_sbi_test_token', 'sbi_test_token' );
406
-
407
- function sbi_delete_account() {
408
- $nonce = $_POST['sbi_nonce'];
409
-
410
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
411
- die ( 'You did not do this the right way!' );
412
- }
413
- $account_id = isset( $_POST['account_id'] ) ? sanitize_text_field( $_POST['account_id'] ) : false;
414
- $options = get_option( 'sb_instagram_settings', array() );
415
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
416
-
417
- wp_cache_delete ( 'alloptions', 'options' );
418
- $username = $connected_accounts[ $account_id ]['username'];
419
-
420
- $num_times_used = 0;
421
-
422
- $new_con_accounts = array();
423
- foreach ( $connected_accounts as $connected_account ) {
424
-
425
- if ( $connected_account['username'] === $username ) {
426
- $num_times_used++;
427
- }
428
-
429
- if ( $connected_account['username'] !== '' && $account_id !== $connected_account['user_id'] && ! empty( $connected_account['user_id'] ) ) {
430
- $new_con_accounts[ $connected_account['user_id'] ] = $connected_account;
431
- }
432
- }
433
-
434
- if ( $num_times_used < 2 ) {
435
- sbi_delete_local_avatar( $username );
436
- }
437
-
438
- $options['connected_accounts'] = $new_con_accounts;
439
-
440
- update_option( 'sb_instagram_settings', $options );
441
-
442
-
443
- die();
444
- }
445
- add_action( 'wp_ajax_sbi_delete_account', 'sbi_delete_account' );
446
-
447
- function sbi_account_data_for_token( $access_token ) {
448
- $return = array(
449
- 'id' => false,
450
- 'username' => false,
451
- 'is_valid' => false,
452
- 'last_checked' => time()
453
- );
454
- $url = 'https://api.instagram.com/v1/users/self/?access_token=' . sbi_maybe_clean( $access_token );
455
- $args = array(
456
- 'timeout' => 60,
457
- 'sslverify' => false
458
- );
459
- $result = wp_remote_get( $url, $args );
460
-
461
- if ( ! is_wp_error( $result ) ) {
462
- $data = json_decode( $result['body'] );
463
- } else {
464
- $data = array();
465
- }
466
-
467
- if ( isset( $data->data->id ) ) {
468
- $return['id'] = $data->data->id;
469
- $return['username'] = $data->data->username;
470
- $return['is_valid'] = true;
471
- $return['profile_picture'] = $data->data->profile_picture;
472
-
473
- } elseif ( isset( $data->error_type ) && $data->error_type === 'OAuthRateLimitException' ) {
474
- $return['error_message'] = 'This account\'s access token is currently over the rate limit. Try removing this access token from all feeds and wait an hour before reconnecting.';
475
- } else {
476
- $return = false;
477
- }
478
-
479
- $sbi_options = get_option( 'sb_instagram_settings', array() );
480
- $sbi_options['sb_instagram_at'] = '';
481
- update_option( 'sb_instagram_settings', $sbi_options );
482
-
483
- return $return;
484
- }
485
-
486
- function sbi_get_connected_accounts_data( $sb_instagram_at ) {
487
- $sbi_options = get_option( 'sb_instagram_settings' );
488
- $return = array();
489
- $return['connected_accounts'] = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
490
-
491
- if ( ! empty( $return['connected_accounts'] ) ) {
492
- $return['access_token'] = '';
493
- } else {
494
- $return['access_token'] = $sb_instagram_at;
495
- }
496
-
497
- if ( ! sbi_is_after_deprecation_deadline() && empty( $connected_accounts ) && ! empty( $sb_instagram_at ) ) {
498
- $tokens = explode(',', $sb_instagram_at );
499
- $user_ids = array();
500
-
501
- foreach ( $tokens as $token ) {
502
- $account = sbi_account_data_for_token( $token );
503
- if ( isset( $account['is_valid'] ) ) {
504
- $split = explode( '.', $token );
505
- $return['connected_accounts'][ $split[0] ] = array(
506
- 'access_token' => sbi_get_parts( $token ),
507
- 'user_id' => $split[0],
508
- 'username' => '',
509
- 'is_valid' => true,
510
- 'last_checked' => time(),
511
- 'profile_picture' => ''
512
- );
513
- $user_ids[] = $split[0];
514
- }
515
-
516
- }
517
-
518
- $sbi_options['connected_accounts'] = $return['connected_accounts'];
519
- $sbi_options['sb_instagram_at'] = '';
520
- $sbi_options['sb_instagram_user_id'] = $user_ids;
521
-
522
- $return['user_ids'] = $user_ids;
523
-
524
- update_option( 'sb_instagram_settings', $sbi_options );
525
- }
526
-
527
- return $return;
528
- }
529
-
530
- function sbi_connect_basic_account( $new_account_details ) {
531
-
532
- $options = sbi_get_database_settings();
533
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
534
-
535
- $accounts_to_save = array();
536
- $old_account_user_id = '';
537
- $ids_to_save = array();
538
- $user_ids = is_array( $options[ 'sb_instagram_user_id' ] ) ? $options[ 'sb_instagram_user_id' ] : explode( ',', str_replace( ' ', '', $options[ 'sb_instagram_user_id' ] ) );
539
-
540
- $profile_picture = '';
541
-
542
- // do not connect as a basic display account if already connected as a business account
543
- if ( isset( $connected_accounts[ $new_account_details['user_id'] ] )
544
- && isset( $connected_accounts[ $new_account_details['user_id'] ]['type'] )
545
- && $connected_accounts[ $new_account_details['user_id'] ]['type'] === 'business' ) {
546
- return $options;
547
- }
548
-
549
- foreach ( $connected_accounts as $account ) {
550
- $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
551
- if ( ($account['username'] !== $new_account_details['username'])
552
- || $account_type === 'business' ) {
553
- $accounts_to_save[ $account['user_id'] ] = $account;
554
- } else {
555
- $old_account_user_id = $account['user_id'];
556
- $profile_picture = isset( $account['profile_picture'] ) ? $account['profile_picture'] : '';
557
- }
558
- }
559
-
560
- foreach ( $user_ids as $id ) {
561
- if ( $id === $old_account_user_id ) {
562
- $ids_to_save[] = $new_account_details['user_id'];
563
- } else {
564
- $ids_to_save[] = $id;
565
- }
566
- }
567
-
568
- $accounts_to_save[ $new_account_details['user_id'] ] = array(
569
- 'access_token' => sbi_fixer( $new_account_details['access_token'] ),
570
- 'user_id' => $new_account_details['user_id'],
571
- 'username' => $new_account_details['username'],
572
- 'is_valid' => true,
573
- 'last_checked' => time(),
574
- 'expires_timestamp' => $new_account_details['expires_timestamp'],
575
- 'profile_picture' => $profile_picture,
576
- 'account_type' => strtolower( $new_account_details['account_type'] ),
577
- 'type' => 'basic',
578
- );
579
-
580
- if ( ! empty( $old_account_user_id ) && $old_account_user_id !== $new_account_details['user_id'] ) {
581
- $accounts_to_save[ $new_account_details['user_id'] ]['old_user_id'] = $old_account_user_id;
582
-
583
- // get last saved header data
584
- $fuzzy_matches = sbi_fuzzy_matching_header_data( $old_account_user_id );
585
- if ( ! empty( $fuzzy_matches[0] ) ) {
586
- $header_data = sbi_find_matching_data_from_results( $fuzzy_matches, $old_account_user_id );
587
- $bio = SB_Instagram_Parse::get_bio( $header_data );
588
- $accounts_to_save[ $new_account_details['user_id'] ]['bio'] = sbi_sanitize_emoji( $bio );
589
- }
590
-
591
- }
592
-
593
- if ( ! empty( $profile_picture ) && !$options['sb_instagram_disable_resize'] ) {
594
- if ( sbi_create_local_avatar( $new_account_details['username'], $profile_picture ) ) {
595
- $accounts_to_save[ $new_account_details['user_id'] ]['local_avatar'] = true;
596
- }
597
- } else {
598
- $accounts_to_save[ $new_account_details['user_id'] ]['local_avatar'] = false;
599
- }
600
-
601
- delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $new_account_details['user_id'] );
602
-
603
- $options['connected_accounts'] = $accounts_to_save;
604
- $options['sb_instagram_user_id'] = $ids_to_save;
605
-
606
- update_option( 'sb_instagram_settings', $options );
607
- return $options;
608
- }
609
-
610
- function sbi_fuzzy_matching_header_data( $user_id ) {
611
-
612
- if ( empty( $user_id ) || strlen( $user_id ) < 4 ) {
613
- return array();
614
- }
615
- global $wpdb;
616
- $escaped_id = esc_sql( $user_id );
617
-
618
- $values = $wpdb->get_results( "
619
- SELECT option_value
620
- FROM $wpdb->options
621
- WHERE option_name LIKE ('%!sbi\_header\_".$escaped_id."%')
622
- LIMIT 10", ARRAY_A );
623
-
624
- $regular_values = $wpdb->get_results( "
625
- SELECT option_value
626
- FROM $wpdb->options
627
- WHERE option_name LIKE ('%sbi\_header\_".$escaped_id."%')
628
- LIMIT 10", ARRAY_A );
629
-
630
- $values = array_merge( $values, $regular_values );
631
-
632
- return $values;
633
- }
634
-
635
- function sbi_find_matching_data_from_results( $results, $user_id ) {
636
-
637
- $match = array();
638
-
639
- $i = 0;
640
-
641
- while( empty( $match ) && isset( $results[ $i ] ) ) {
642
- if ( ! empty( $results[ $i ] ) ) {
643
- $header_data = json_decode( $results[ $i ]['option_value'], true );
644
- if ( isset( $header_data['id'] ) && (string)$header_data['id'] === (string)$user_id ) {
645
- $match = $header_data;
646
- }
647
- }
648
- $i++;
649
- }
650
-
651
- return $match;
652
- }
653
-
654
- function sbi_matches_existing_personal( $new_account_details ) {
655
-
656
- $options = sbi_get_database_settings();
657
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
658
-
659
- $matches_one_account = false;
660
- $accounts_to_save = array();
661
- foreach ( $connected_accounts as $account ) {
662
- $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
663
- if ( ($account_type === 'personal' || $account_type === 'basic')
664
- && $account['username'] == $new_account_details['username'] ) {
665
- $matches_one_account = true;
666
-
667
-
668
- }
669
- }
670
-
671
- return $matches_one_account;
672
-
673
- }
674
-
675
- function sbi_business_account_request( $url, $account, $remove_access_token = true ) {
676
- $args = array(
677
- 'timeout' => 60,
678
- 'sslverify' => false
679
- );
680
- $result = wp_remote_get( $url, $args );
681
-
682
- if ( ! is_wp_error( $result ) ) {
683
- $response_no_at = $remove_access_token ? str_replace( sbi_maybe_clean( $account['access_token'] ), '{accesstoken}', $result['body'] ) : $result['body'];
684
- return $response_no_at;
685
- } else {
686
- return wp_json_encode( $result );
687
- }
688
- }
689
-
690
- function sbi_after_connection() {
691
-
692
- if ( isset( $_POST['access_token'] ) ) {
693
- $access_token = sanitize_text_field( $_POST['access_token'] );
694
- $account_info = sbi_account_data_for_token( $access_token );
695
- echo wp_json_encode( $account_info );
696
- }
697
-
698
- die();
699
- }
700
- add_action( 'wp_ajax_sbi_after_connection', 'sbi_after_connection' );
701
-
702
- function sbi_account_type_display( $type ) {
703
- if ( $type === 'basic' ) {
704
- return 'personal (new API)';
705
- }
706
- return $type;
707
- }
708
-
709
- function sbi_clear_backups() {
710
- $nonce = isset( $_POST['sbi_nonce'] ) ? sanitize_text_field( $_POST['sbi_nonce'] ) : '';
711
-
712
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
713
- die ( 'You did not do this the right way!' );
714
- }
715
-
716
- //Delete all transients
717
- global $wpdb;
718
- $table_name = $wpdb->prefix . "options";
719
- $wpdb->query( "
720
- DELETE
721
- FROM $table_name
722
- WHERE `option_name` LIKE ('%!sbi\_%')
723
- " );
724
- $wpdb->query( "
725
- DELETE
726
- FROM $table_name
727
- WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
728
- " );
729
- $wpdb->query( "
730
- DELETE
731
- FROM $table_name
732
- WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
733
- " );
734
-
735
- die();
736
- }
737
- add_action( 'wp_ajax_sbi_clear_backups', 'sbi_clear_backups' );
738
-
739
- function sbi_reset_resized() {
740
-
741
- global $sb_instagram_posts_manager;
742
- $sb_instagram_posts_manager->delete_all_sbi_instagram_posts();
743
-
744
- echo "1";
745
-
746
- die();
747
- }
748
- add_action( 'wp_ajax_sbi_reset_resized', 'sbi_reset_resized' );
749
-
750
- function sbi_lite_dismiss() {
751
- $nonce = isset( $_POST['sbi_nonce'] ) ? sanitize_text_field( $_POST['sbi_nonce'] ) : '';
752
-
753
- if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
754
- die ( 'You did not do this the right way!' );
755
- }
756
-
757
- set_transient( 'instagram_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS );
758
-
759
- die();
760
- }
761
- add_action( 'wp_ajax_sbi_lite_dismiss', 'sbi_lite_dismiss' );
762
-
763
- function sbi_reset_log() {
764
-
765
- delete_option( 'sb_instagram_errors' );
766
-
767
- echo "1";
768
-
769
- die();
770
- }
771
- add_action( 'wp_ajax_sbi_reset_log', 'sbi_reset_log' );
772
-
773
- add_action('admin_notices', 'sbi_admin_error_notices');
774
- function sbi_admin_error_notices() {
775
- //Only display notice to admins
776
- if( !current_user_can( 'manage_options' ) ) return;
777
-
778
- global $sb_instagram_posts_manager;
779
-
780
- if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'sb-instagram-feed' )) ) {
781
- $errors = $sb_instagram_posts_manager->get_errors();
782
- if ( ! empty( $errors ) && ( isset( $errors['database_create_posts'] ) || isset( $errors['database_create_posts_feeds'] ) || isset( $errors['upload_dir'] ) || isset( $errors['ajax'] ) ) ) : ?>
783
- <div class="notice notice-warning is-dismissible sbi-admin-notice">
784
-
785
- <?php foreach ( $sb_instagram_posts_manager->get_errors() as $type => $error ) : ?>
786
- <?php if ( (in_array( $type, array( 'database_create_posts', 'database_create_posts_feeds', 'upload_dir' ) ) && !$sb_instagram_posts_manager->image_resizing_disabled() ) ) : ?>
787
- <p><strong><?php echo $error[0]; ?></strong></p>
788
- <p><?php _e( 'Note for support', 'instagram-feed' ); ?>: <?php echo $error[1]; ?></p>
789
- <?php endif; ?>
790
- <?php endforeach; ?>
791
- <?php if ( ( isset( $errors['database_create_posts'] ) || isset( $errors['database_create_posts_feeds'] ) || isset( $errors['upload_dir'] ) ) && !$sb_instagram_posts_manager->image_resizing_disabled() ) : ?>
792
- <p><?php _e( sprintf( 'Visit our %s page for help', '<a href="https://smashballoon.com/instagram-feed/support/faq/" target="_blank">FAQ</a>' ), 'instagram-feed' ); ?></p>
793
- <?php endif; ?>
794
-
795
- <?php foreach ( $sb_instagram_posts_manager->get_errors() as $type => $error ) : ?>
796
- <?php if (in_array( $type, array( 'ajax' ) )) : ?>
797
- <p class="sbi-admin-error" data-sbi-type="ajax"><strong><?php echo $error[0]; ?></strong></p>
798
- <p><?php echo $error[1]; ?></p>
799
- <?php endif; ?>
800
- <?php endforeach; ?>
801
-
802
- </div>
803
-
804
- <?php endif;
805
- }
806
-
807
- }
808
-
809
- function sbi_maybe_add_ajax_test_error() {
810
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'sb-instagram-feed' ) {
811
- global $sb_instagram_posts_manager;
812
-
813
- if ( $sb_instagram_posts_manager->should_add_ajax_test_notice() ) {
814
- $sb_instagram_posts_manager->add_error( 'ajax', array( __( 'Unable to use admin-ajax.php when displaying feeds. Some features of the plugin will be unavailable.', 'instagram-feed' ), __( sprintf( 'Please visit %s to troubleshoot.', '<a href="https://smashballoon.com/admin-ajax-requests-are-not-working/">'.__( 'this page', 'instagram-feed' ).'</a>' ), 'instagram-feed' ) ) );
815
- } else {
816
- $sb_instagram_posts_manager->remove_error( 'ajax' );
817
- }
818
- }
819
- }
820
- add_action( 'admin_init', 'sbi_maybe_add_ajax_test_error' );
821
-
822
- function sbi_get_user_names_of_personal_accounts_not_also_already_updated() {
823
- $sbi_options = get_option( 'sb_instagram_settings', array() );
824
- $users_in_personal_accounts = array();
825
- $non_personal_account_users = array();
826
-
827
- $connected_accounts = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
828
-
829
- if ( ! empty( $connected_accounts ) ) {
830
-
831
- foreach ( $connected_accounts as $account ) {
832
- $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
833
-
834
- if ( $account_type === 'personal' ) {
835
- $users_in_personal_accounts[] = $account['username'];
836
- } else {
837
- $non_personal_account_users[] = $account['username'];
838
- }
839
-
840
- }
841
-
842
- if ( ! empty( $users_in_personal_accounts ) ) {
843
- $user_accounts_that_need_updating = array();
844
- foreach ( $users_in_personal_accounts as $personal_user ) {
845
- if ( ! in_array( $personal_user, $non_personal_account_users, true ) && $personal_user !== '' ) {
846
- $user_accounts_that_need_updating[] = $personal_user;
847
- }
848
- }
849
-
850
- return $user_accounts_that_need_updating;
851
- }
852
- } elseif ( empty( $connected_accounts ) && ! empty( $sbi_options['sb_instagram_at'] ) ) {
853
- return array( 'your Instagram feed');
854
- }
855
-
856
- return array();
857
- }
858
-
859
- function sbi_reconnect_accounts_notice() {
860
- if( ! current_user_can( 'manage_options' ) ) return;
861
-
862
- $should_show_link = ! isset( $_GET['page'] ) || $_GET['page'] !== 'sb-instagram-feed';
863
- $personal_accounts_that_need_updating = sbi_get_user_names_of_personal_accounts_not_also_already_updated();
864
- if ( empty( $personal_accounts_that_need_updating ) ) {
865
- return;
866
- } else {
867
- $total = count( $personal_accounts_that_need_updating );
868
- if ( $total > 1 ) {
869
- $user_string = '';
870
- $i = 0;
871
-
872
- foreach ( $personal_accounts_that_need_updating as $username ) {
873
- if ( ($i + 1) === $total ) {
874
- $user_string .= ' and ' . $username;
875
- } else {
876
- if ( $i !== 0 ) {
877
- $user_string .= ', ' . $username;
878
- } else {
879
- $user_string .= $username;
880
- }
881
- }
882
- $i++;
883
- }
884
- } else {
885
- $user_string = $personal_accounts_that_need_updating[0];
886
- }
887
-
888
- if ( sbi_is_after_deprecation_deadline() ) {
889
- $notice_class = 'notice-error';
890
- $error = '<p><b>' . sprintf( __( 'Error: Instagram Feed plugin - account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to recent Instagram platform changes some Instagram accounts will need to be reconnected in the plugin in order for them to continue updating.', 'instagram-feed' );
891
- } else {
892
- $notice_class = 'notice-warning';
893
- $error = '<p><b>' . sprintf( __( 'Warning: Instagram Feed plugin - account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to Instagram platform changes on March 31, 2020, some Instagram accounts will need to be reconnected in the plugin to avoid disruption to your feeds.', 'instagram-feed' );
894
- }
895
- if( !$should_show_link ) $error .= __( ' Use the big blue button below to reconnect your account.', 'instagram-feed' );
896
- }
897
- $url = admin_url( '?page=sb-instagram-feed' );
898
-
899
- ?>
900
- <div class="notice <?php echo $notice_class; ?> is-dismissible">
901
- <?php echo $error; ?>
902
- <p>
903
- <?php if ( $should_show_link ) : ?>
904
- <a href="<?php echo $url; ?>" class="button-primary" style="margin-right:10px;"><i class="fa fa-instagram" aria-hidden="true"></i> &nbsp;Reconnect on Settings Page</a>
905
- <?php endif; ?>
906
- <a href="https://smashballoon.com/instagram-api-changes-march-2-2020/" target="_blank" rel="noopener">See more details</a>
907
- </p>
908
- </div>
909
-
910
- <?php
911
-
912
- }
913
- add_action( 'admin_notices', 'sbi_reconnect_accounts_notice' );
914
-
915
- function sbi_get_current_time() {
916
- $current_time = time();
917
-
918
- // where to do tests
919
- // $current_time = strtotime( 'November 25, 2022' ) + 1;
920
-
921
- return $current_time;
922
- }
923
-
924
- // generates the html for the admin notices
925
- function sbi_notices_html() {
926
-
927
- //Only show to admins
928
- $current_screen = get_current_screen();
929
- $is_plugins_page = isset( $current_screen->id ) && $current_screen->id === 'plugins';
930
- $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : '';
931
- //Only show to admins
932
- if ( ! current_user_can( 'manage_options' ) ) {
933
- return;
934
- }
935
-
936
- $sbi_statuses_option = get_option( 'sbi_statuses', array() );
937
- $current_time = sbi_get_current_time();
938
- $sbi_bfcm_discount_code = 'happysmashgiving' . date('Y', $current_time );
939
-
940
- // reset everything for testing
941
- if ( false ) {
942
- global $current_user;
943
- $user_id = $current_user->ID;
944
- delete_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
945
- //delete_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
946
- //$sbi_statuses_option = array( 'first_install' => strtotime( 'December 8, 2019' ) );
947
- //$sbi_statuses_option = array( 'first_install' => time() );
948
-
949
- //update_option( 'sbi_statuses', $sbi_statuses_option, false );
950
- //delete_option( 'sbi_rating_notice');
951
- //delete_transient( 'instagram_feed_rating_notice_waiting' );
952
-
953
- //set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
954
- //update_option( 'sbi_rating_notice', 'pending', false );
955
- }
956
-
957
- //$sbi_statuses_option['rating_notice_dismissed'] = time();
958
- //update_option( 'sbi_statuses', $sbi_statuses_option, false );
959
- // rating notice logic
960
- $sbi_rating_notice_option = get_option( 'sbi_rating_notice', false );
961
- $sbi_rating_notice_waiting = get_transient( 'instagram_feed_rating_notice_waiting' );
962
- $should_show_rating_notice = ($sbi_rating_notice_waiting !== 'waiting' && $sbi_rating_notice_option !== 'dismissed');
963
-
964
- // black friday cyber monday logic
965
- $thanksgiving_this_year = sbi_get_future_date( 11, date('Y', $current_time ), 4, 4, 1 );
966
- $one_week_before_black_friday_this_year = $thanksgiving_this_year - 7*24*60*60;
967
- $one_day_after_cyber_monday_this_year = $thanksgiving_this_year + 5*24*60*60;
968
- $has_been_two_days_since_rating_dismissal = isset( $sbi_statuses_option['rating_notice_dismissed'] ) ? ((int)$sbi_statuses_option['rating_notice_dismissed'] + 2*24*60*60) < $current_time : true;
969
-
970
- $could_show_bfcm_discount = ($current_time > $one_week_before_black_friday_this_year && $current_time < $one_day_after_cyber_monday_this_year);
971
- $should_show_bfcm_discount = false;
972
- if ( $could_show_bfcm_discount && $has_been_two_days_since_rating_dismissal ) {
973
- global $current_user;
974
- $user_id = $current_user->ID;
975
-
976
- $ignore_bfcm_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
977
- $ignore_bfcm_sale_notice_meta = isset( $ignore_bfcm_sale_notice_meta[0] ) ? $ignore_bfcm_sale_notice_meta[0] : '';
978
-
979
- /* Check that the user hasn't already clicked to ignore the message */
980
- $should_show_bfcm_discount = ($ignore_bfcm_sale_notice_meta !== 'always' && $ignore_bfcm_sale_notice_meta !== date( 'Y', $current_time ));
981
- }
982
-
983
- // new user discount logic
984
- $in_new_user_month_range = true;
985
- $should_show_new_user_discount = false;
986
- $has_been_one_month_since_rating_dismissal = isset( $sbi_statuses_option['rating_notice_dismissed'] ) ? ((int)$sbi_statuses_option['rating_notice_dismissed'] + 30*24*60*60) < $current_time + 1: true;
987
-
988
- if ( isset( $sbi_statuses_option['first_install'] ) && $sbi_statuses_option['first_install'] === 'from_update' ) {
989
- global $current_user;
990
- $user_id = $current_user->ID;
991
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
992
- $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
993
- if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
994
- $should_show_new_user_discount = true;
995
- }
996
- } elseif ( $in_new_user_month_range && $has_been_one_month_since_rating_dismissal ) {
997
- global $current_user;
998
- $user_id = $current_user->ID;
999
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1000
- $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
1001
-
1002
- if ( $ignore_new_user_sale_notice_meta !== 'always'
1003
- && isset( $sbi_statuses_option['first_install'] )
1004
- && $current_time > (int)$sbi_statuses_option['first_install'] + 60*60*24*30 ) {
1005
- $should_show_new_user_discount = true;
1006
- }
1007
- }
1008
-
1009
- // for debugging
1010
- if ( false ) {
1011
- global $current_user;
1012
- $user_id = $current_user->ID;
1013
- $ignore_bfcm_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
1014
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1015
-
1016
- var_dump( 'new user rating option', $sbi_rating_notice_option );
1017
- var_dump( 'new user rating transient', $sbi_rating_notice_waiting );
1018
-
1019
- var_dump( 'should show new user rating notice?', $should_show_rating_notice );
1020
-
1021
- var_dump( 'new user discount month range?', $in_new_user_month_range );
1022
- var_dump( 'should show new user discount?', $should_show_new_user_discount );
1023
-
1024
- var_dump( 'Thanksgiving this year?', date('m/d/Y', $thanksgiving_this_year ) );
1025
-
1026
- var_dump( 'could show bfcm discount?', $could_show_bfcm_discount );
1027
- var_dump( 'should show bfcm discount?', $should_show_bfcm_discount );
1028
-
1029
- var_dump( 'ignore_bfcm_sale_notice_meta', $ignore_bfcm_sale_notice_meta );
1030
- var_dump( 'ignore_new_user_sale_notice_meta', $ignore_new_user_sale_notice_meta );
1031
-
1032
- var_dump( $sbi_statuses_option );
1033
- }
1034
-
1035
-
1036
- if ( $should_show_rating_notice ) {
1037
- $other_notice_html = '';
1038
- $dismiss_url = add_query_arg( 'sbi_ignore_rating_notice_nag', '1' );
1039
- $later_url = add_query_arg( 'sbi_ignore_rating_notice_nag', 'later' );
1040
- if ( $should_show_bfcm_discount ) {
1041
- $other_notice_html = '<p class="sbi_other_notice">' . __( 'PS. We currently have a <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount='.$sbi_bfcm_discount_code.'" target="_blank"><b style="font-weight: 700;">Black Friday deal</b></a> for 20% off the Pro version!', 'instagram-feed' ) . '</a></p>';
1042
-
1043
- $dismiss_url = add_query_arg( array(
1044
- 'sbi_ignore_rating_notice_nag' => '1',
1045
- 'sbi_ignore_bfcm_sale_notice' => date( 'Y', $current_time )
1046
- )
1047
- );
1048
- $later_url = add_query_arg( array(
1049
- 'sbi_ignore_rating_notice_nag' => 'later',
1050
- 'sbi_ignore_bfcm_sale_notice' => date( 'Y', $current_time )
1051
- )
1052
- );
1053
- }
1054
-
1055
- echo "
1056
- <div class='sbi_notice sbi_review_notice'>
1057
- <img src='". SBI_PLUGIN_URL . 'img/sbi-icon.png' ."' alt='" . __( 'Instagram Feed', 'instagram-feed' ) . "'>
1058
- <div class='sbi-notice-text'>
1059
- <p style='padding-top: 4px;'>" . __( "It's great to see that you've been using the <strong style='font-weight: 700;'>Instagram Feed</strong> plugin for a while now. Hopefully you're happy with it!&nbsp; If so, would you consider leaving a positive review? It really helps to support the plugin and helps others to discover it too!", 'instagram-feed' ) . "</p>
1060
- <p class='links'";
1061
- if( $should_show_bfcm_discount ) echo " style='margin-top: 0 !important;'";
1062
- echo ">
1063
- <a class='sbi_notice_dismiss' href='https://wordpress.org/support/plugin/instagram-feed/reviews/' target='_blank'>" . __( 'Sure, I\'d love to!', 'instagram-feed' ) . "</a>
1064
- &middot;
1065
- <a class='sbi_notice_dismiss' href='" .esc_url( $dismiss_url ). "'>" . __( 'No thanks', 'instagram-feed' ) . "</a>
1066
- &middot;
1067
- <a class='sbi_notice_dismiss' href='" .esc_url( $dismiss_url ). "'>" . __( 'I\'ve already given a review', 'instagram-feed' ) . "</a>
1068
- &middot;
1069
- <a class='sbi_notice_dismiss' href='" .esc_url( $later_url ). "'>" . __( 'Ask Me Later', 'instagram-feed' ) . "</a>
1070
- </p>"
1071
- . $other_notice_html .
1072
- "</div>
1073
- <a class='sbi_notice_close' href='" .esc_url( $dismiss_url ). "'><i class='fa fa-close'></i></a>
1074
- </div>";
1075
-
1076
- } elseif ( $should_show_new_user_discount ) {
1077
- global $current_user;
1078
- $user_id = $current_user->ID;
1079
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1080
- if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
1081
-
1082
- echo "
1083
- <div class='sbi_notice sbi_review_notice sbi_new_user_sale_notice'>
1084
- <img src='" . SBI_PLUGIN_URL . 'img/sbi-icon-offer.png' . "' alt='Instagram Feed'>
1085
- <div class='sbi-notice-text'>
1086
- <p>" . __( '<b style="font-weight: 700;">Exclusive offer!</b> We don\'t run promotions very often, but for a limited time we\'re offering <b style="font-weight: 700;">20% off</b> our Pro version to all users of our free Instagram Feed plugin.', 'instagram-feed' ) . "</p>
1087
- <p class='sbi-links'>
1088
- <a class='sbi_notice_dismiss sbi_offer_btn' href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount=instagramthankyou' target='_blank'><b>" . __( 'Get this offer', 'instagram-feed' ) . "</b></a>
1089
- <a class='sbi_notice_dismiss' style='margin-left: 5px;' href='" . esc_url( add_query_arg( 'sbi_ignore_new_user_sale_notice', 'always' ) ) . "'>" . __( 'I\'m not interested', 'instagram-feed' ) . "</a>
1090
-
1091
- </p>
1092
- </div>
1093
- <a class='sbi_new_user_sale_notice_close' href='" . esc_url( add_query_arg( 'sbi_ignore_new_user_sale_notice', 'always' ) ) . "'><i class='fa fa-close'></i></a>
1094
- </div>
1095
- ";
1096
- }
1097
-
1098
- } elseif ( $should_show_bfcm_discount ) {
1099
-
1100
- echo "
1101
- <div class='sbi_notice sbi_review_notice sbi_bfcm_sale_notice'>
1102
- <img src='". SBI_PLUGIN_URL . 'img/sbi-icon-offer.png' ."' alt='Instagram Feed'>
1103
- <div class='sbi-notice-text'>
1104
- <p>" . __( '<b style="font-weight: 700;">Black Friday/Cyber Monday Deal!</b> Thank you for using our free Instagram Feed plugin. For a limited time, we\'re offering <b style="font-weight: 700;">20% off</b> the Pro version for all of our users.', 'instagram-feed' ) . "</p>
1105
- <p class='sbi-links'>
1106
- <a class='sbi_notice_dismiss sbi_offer_btn' href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount=".$sbi_bfcm_discount_code."' target='_blank'>" . __( 'Get this offer!', 'instagram-feed' ) . "</a>
1107
- <a class='sbi_notice_dismiss' style='margin-left: 5px;' href='" .esc_url( add_query_arg( 'sbi_ignore_bfcm_sale_notice', date( 'Y', $current_time ) ) ). "'>" . __( 'I\'m not interested', 'instagram-feed' ) . "</a>
1108
- </p>
1109
- </div>
1110
- <a class='sbi_bfcm_sale_notice_close' href='" .esc_url( add_query_arg( 'sbi_ignore_bfcm_sale_notice', date( 'Y', $current_time ) ) ). "'><i class='fa fa-close'></i></a>
1111
- </div>
1112
- ";
1113
-
1114
- }
1115
-
1116
- }
1117
- add_action( 'admin_notices', 'sbi_notices_html', 8 ); // priority 12 for Twitter, priority 10 for Facebook
1118
-
1119
- function sbi_process_nags() {
1120
-
1121
- global $current_user;
1122
- $user_id = $current_user->ID;
1123
- $sbi_statuses_option = get_option( 'sbi_statuses', array() );
1124
-
1125
- if ( isset( $_GET['sbi_ignore_rating_notice_nag'] ) ) {
1126
- if ( (int)$_GET['sbi_ignore_rating_notice_nag'] === 1 ) {
1127
- update_option( 'sbi_rating_notice', 'dismissed', false );
1128
- $sbi_statuses_option['rating_notice_dismissed'] = sbi_get_current_time();
1129
- update_option( 'sbi_statuses', $sbi_statuses_option, false );
1130
-
1131
- } elseif ( $_GET['sbi_ignore_rating_notice_nag'] === 'later' ) {
1132
- set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
1133
- update_option( 'sbi_rating_notice', 'pending', false );
1134
- }
1135
- }
1136
-
1137
- if ( isset( $_GET['sbi_ignore_new_user_sale_notice'] ) ) {
1138
- $response = sanitize_text_field( $_GET['sbi_ignore_new_user_sale_notice'] );
1139
- if ( $response === 'always' ) {
1140
- update_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice', 'always' );
1141
-
1142
- $current_month_number = (int)date('n', sbi_get_current_time() );
1143
- $not_early_in_the_year = ($current_month_number > 5);
1144
-
1145
- if ( $not_early_in_the_year ) {
1146
- update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', date( 'Y', sbi_get_current_time() ) );
1147
- }
1148
-
1149
- }
1150
- }
1151
-
1152
- if ( isset( $_GET['sbi_ignore_bfcm_sale_notice'] ) ) {
1153
- $response = sanitize_text_field( $_GET['sbi_ignore_bfcm_sale_notice'] );
1154
- if ( $response === 'always' ) {
1155
- update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', 'always' );
1156
- } elseif ( $response === date( 'Y', sbi_get_current_time() ) ) {
1157
- update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', date( 'Y', sbi_get_current_time() ) );
1158
- }
1159
- update_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice', 'always' );
1160
- }
1161
-
1162
- }
1163
- add_action( 'admin_init', 'sbi_process_nags' );
1164
-
1165
- function sbi_get_future_date( $month, $year, $week, $day, $direction ) {
1166
- if ( $direction > 0 ) {
1167
- $startday = 1;
1168
- } else {
1169
- $startday = date( 't', mktime(0, 0, 0, $month, 1, $year ) );
1170
- }
1171
-
1172
- $start = mktime( 0, 0, 0, $month, $startday, $year );
1173
- $weekday = date( 'N', $start );
1174
-
1175
- $offset = 0;
1176
- if ( $direction * $day >= $direction * $weekday ) {
1177
- $offset = -$direction * 7;
1178
- }
1179
-
1180
- $offset += $direction * ($week * 7) + ($day - $weekday);
1181
- return mktime( 0, 0, 0, $month, $startday + $offset, $year );
1182
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Includes functions related to actions while in the admin area.
4
+ *
5
+ * - All AJAX related features
6
+ * - Enqueueing of JS and CSS files
7
+ * - Settings link on "Plugins" page
8
+ * - Creation of local avatar image files
9
+ * - Connecting accounts on the "Configure" tab
10
+ * - Displaying admin notices
11
+ * - Clearing caches
12
+ */
13
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
+
15
+ function sb_instagram_admin_style() {
16
+ wp_register_style( 'sb_instagram_admin_css', SBI_PLUGIN_URL . 'css/sb-instagram-admin.css', array(), SBIVER );
17
+ wp_enqueue_style( 'sb_instagram_font_awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css' );
18
+ wp_enqueue_style( 'sb_instagram_admin_css' );
19
+ wp_enqueue_style( 'wp-color-picker' );
20
+ }
21
+ add_action( 'admin_enqueue_scripts', 'sb_instagram_admin_style' );
22
+
23
+ function sb_instagram_admin_scripts() {
24
+ wp_enqueue_script( 'sb_instagram_admin_js', SBI_PLUGIN_URL . 'js/sb-instagram-admin-2-2.js', array(), SBIVER );
25
+ wp_localize_script( 'sb_instagram_admin_js', 'sbiA', array(
26
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
27
+ 'sbi_nonce' => wp_create_nonce( 'sbi_nonce' )
28
+ )
29
+ );
30
+ $strings = array(
31
+ 'addon_activate' => esc_html__( 'Activate', 'instagram-feed' ),
32
+ 'addon_activated' => esc_html__( 'Activated', 'instagram-feed' ),
33
+ 'addon_active' => esc_html__( 'Active', 'instagram-feed' ),
34
+ 'addon_deactivate' => esc_html__( 'Deactivate', 'instagram-feed' ),
35
+ 'addon_inactive' => esc_html__( 'Inactive', 'instagram-feed' ),
36
+ 'addon_install' => esc_html__( 'Install Addon', 'instagram-feed' ),
37
+ 'addon_error' => esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'instagram-feed' ),
38
+ 'plugin_error' => esc_html__( 'Could not install a plugin. Please download from WordPress.org and install manually.', 'instagram-feed' ),
39
+ 'addon_search' => esc_html__( 'Searching Addons', 'instagram-feed' ),
40
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
41
+ 'cancel' => esc_html__( 'Cancel', 'instagram-feed' ),
42
+ 'close' => esc_html__( 'Close', 'instagram-feed' ),
43
+ 'nonce' => wp_create_nonce( 'sbi-admin' ),
44
+ 'almost_done' => esc_html__( 'Almost Done', 'instagram-feed' ),
45
+ 'oops' => esc_html__( 'Oops!', 'instagram-feed' ),
46
+ 'ok' => esc_html__( 'OK', 'instagram-feed' ),
47
+ 'plugin_install_activate_btn' => esc_html__( 'Install and Activate', 'instagram-feed' ),
48
+ 'plugin_install_activate_confirm' => esc_html__( 'needs to be installed and activated to import its forms. Would you like us to install and activate it for you?', 'instagram-feed' ),
49
+ 'plugin_activate_btn' => esc_html__( 'Activate', 'instagram-feed' ),
50
+ );
51
+ $strings = apply_filters( 'sbi_admin_strings', $strings );
52
+
53
+ wp_localize_script(
54
+ 'sb_instagram_admin_js',
55
+ 'sbi_admin',
56
+ $strings
57
+ );
58
+ if( !wp_script_is('jquery-ui-draggable') ) {
59
+ wp_enqueue_script(
60
+ array(
61
+ 'jquery',
62
+ 'jquery-ui-core',
63
+ 'jquery-ui-draggable'
64
+ )
65
+ );
66
+ }
67
+ wp_enqueue_script(
68
+ array(
69
+ 'hoverIntent',
70
+ 'wp-color-picker'
71
+ )
72
+ );
73
+ }
74
+ add_action( 'admin_enqueue_scripts', 'sb_instagram_admin_scripts' );
75
+
76
+ // Add a Settings link to the plugin on the Plugins page
77
+ $sbi_plugin_file = 'instagram-feed/instagram-feed.php';
78
+ add_filter( "plugin_action_links_{$sbi_plugin_file}", 'sbi_add_settings_link', 10, 2 );
79
+
80
+ //modify the link by unshifting the array
81
+ function sbi_add_settings_link( $links, $file ) {
82
+ $sbi_settings_link = '<a href="' . admin_url( 'admin.php?page=sb-instagram-feed' ) . '">' . __( 'Settings', 'instagram-feed' ) . '</a>';
83
+ array_unshift( $links, $sbi_settings_link );
84
+
85
+ return $links;
86
+ }
87
+
88
+
89
+ /**
90
+ * Called via ajax to automatically save access token and access token secret
91
+ * retrieved with the big blue button
92
+ */
93
+ function sbi_auto_save_tokens() {
94
+ $nonce = $_POST['sbi_nonce'];
95
+
96
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
97
+ die ( 'You did not do this the right way!' );
98
+ }
99
+
100
+ wp_cache_delete ( 'alloptions', 'options' );
101
+
102
+ $options = sbi_get_database_settings();
103
+ $new_access_token = isset( $_POST['access_token'] ) ? sanitize_text_field( $_POST['access_token'] ) : false;
104
+ $split_token = $new_access_token ? explode( '.', $new_access_token ) : array();
105
+ $new_user_id = isset( $split_token[0] ) ? $split_token[0] : '';
106
+
107
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
108
+ $test_connection_data = sbi_account_data_for_token( $new_access_token );
109
+
110
+ $connected_accounts[ $new_user_id ] = array(
111
+ 'access_token' => sbi_get_parts( $new_access_token ),
112
+ 'user_id' => $test_connection_data['id'],
113
+ 'username' => $test_connection_data['username'],
114
+ 'is_valid' => $test_connection_data['is_valid'],
115
+ 'last_checked' => $test_connection_data['last_checked'],
116
+ 'profile_picture' => $test_connection_data['profile_picture'],
117
+ );
118
+
119
+ if ( !$options['sb_instagram_disable_resize'] ) {
120
+ if ( sbi_create_local_avatar( $test_connection_data['username'], $test_connection_data['profile_picture'] ) ) {
121
+ $connected_accounts[ $new_user_id ]['local_avatar'] = true;
122
+ }
123
+ } else {
124
+ $connected_accounts[ $new_user_id ]['local_avatar'] = false;
125
+ }
126
+
127
+ $options['connected_accounts'] = $connected_accounts;
128
+
129
+ update_option( 'sb_instagram_settings', $options );
130
+
131
+ echo wp_json_encode( $connected_accounts[ $new_user_id ] );
132
+
133
+ die();
134
+ }
135
+ add_action( 'wp_ajax_sbi_auto_save_tokens', 'sbi_auto_save_tokens' );
136
+
137
+ function sbi_delete_local_avatar( $username ) {
138
+ $upload = wp_upload_dir();
139
+
140
+ $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $username . '.jpg' ); // get all matching images
141
+ foreach ( $image_files as $file ) { // iterate files
142
+ if ( is_file( $file ) ) {
143
+ unlink( $file );
144
+ }
145
+ }
146
+ }
147
+
148
+ function sbi_create_local_avatar( $username, $file_name ) {
149
+ $image_editor = wp_get_image_editor( $file_name );
150
+
151
+ if ( ! is_wp_error( $image_editor ) ) {
152
+ $upload = wp_upload_dir();
153
+
154
+ $full_file_name = trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $username . '.jpg';
155
+
156
+ $saved_image = $image_editor->save( $full_file_name );
157
+
158
+ if ( ! $saved_image ) {
159
+ global $sb_instagram_posts_manager;
160
+
161
+ $sb_instagram_posts_manager->add_error( 'image_editor_save', array(
162
+ __( 'Error saving edited image.', 'instagram-feed' ),
163
+ $full_file_name
164
+ ) );
165
+ } else {
166
+ return true;
167
+ }
168
+ } else {
169
+ global $sb_instagram_posts_manager;
170
+
171
+ $message = __( 'Error editing image.', 'instagram-feed' );
172
+ if ( isset( $image_editor ) && isset( $image_editor->errors ) ) {
173
+ foreach ( $image_editor->errors as $key => $item ) {
174
+ $message .= ' ' . $key . '- ' . $item[0] . ' |';
175
+ }
176
+ }
177
+
178
+ $sb_instagram_posts_manager->add_error( 'image_editor', array( $file_name, $message ) );
179
+ }
180
+ return false;
181
+ }
182
+
183
+ function sbi_connect_business_accounts() {
184
+ $nonce = $_POST['sbi_nonce'];
185
+
186
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
187
+ die ( 'You did not do this the right way!' );
188
+ }
189
+
190
+ $accounts = isset( $_POST['accounts'] ) ? json_decode( stripslashes( $_POST['accounts'] ), true ) : false;
191
+ $options = sbi_get_database_settings();
192
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
193
+
194
+ foreach ( $accounts as $account ) {
195
+ $access_token = isset( $account['access_token'] ) ? $account['access_token'] : '';
196
+ $page_access_token = isset( $account['page_access_token'] ) ? $account['page_access_token'] : '';
197
+ $username = isset( $account['username'] ) ? $account['username'] : '';
198
+ $name = isset( $account['name'] ) ? $account['name'] : '';
199
+ $profile_picture = isset( $account['profile_picture_url'] ) ? $account['profile_picture_url'] : '';
200
+ $user_id = isset( $account['id'] ) ? $account['id'] : '';
201
+ $type = 'business';
202
+
203
+ $connected_accounts[ $user_id ] = array(
204
+ 'access_token' => $access_token,
205
+ 'page_access_token' => $page_access_token,
206
+ 'user_id' => $user_id,
207
+ 'username' => $username,
208
+ 'is_valid' => true,
209
+ 'last_checked' => time(),
210
+ 'profile_picture' => $profile_picture,
211
+ 'name' => sbi_sanitize_emoji( $name ),
212
+ 'type' => $type,
213
+ 'use_tagged' => '1'
214
+ );
215
+
216
+ if ( !$options['sb_instagram_disable_resize'] ) {
217
+ if ( sbi_create_local_avatar( $username, $profile_picture ) ) {
218
+ $connected_accounts[ $user_id ]['local_avatar'] = true;
219
+ }
220
+ } else {
221
+ $connected_accounts[ $user_id ]['local_avatar'] = false;
222
+ }
223
+ global $sb_instagram_posts_manager;
224
+
225
+ $sb_instagram_posts_manager->remove_error( 'at_' . $username );
226
+ delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $user_id );
227
+ }
228
+
229
+ $options['connected_accounts'] = $connected_accounts;
230
+
231
+ update_option( 'sb_instagram_settings', $options );
232
+
233
+ echo wp_json_encode( $connected_accounts );
234
+
235
+ die();
236
+ }
237
+ add_action( 'wp_ajax_sbi_connect_business_accounts', 'sbi_connect_business_accounts' );
238
+
239
+ function sbi_auto_save_id() {
240
+ $nonce = $_POST['sbi_nonce'];
241
+
242
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
243
+ die ( 'You did not do this the right way!' );
244
+ }
245
+ if ( current_user_can( 'edit_posts' ) && isset( $_POST['id'] ) ) {
246
+ $options = get_option( 'sb_instagram_settings', array() );
247
+
248
+ $options['sb_instagram_user_id'] = array( sanitize_text_field( $_POST['id'] ) );
249
+
250
+ update_option( 'sb_instagram_settings', $options );
251
+ }
252
+ die();
253
+ }
254
+ add_action( 'wp_ajax_sbi_auto_save_id', 'sbi_auto_save_id' );
255
+
256
+ function sbi_test_token() {
257
+ $access_token = isset( $_POST['access_token'] ) ? sanitize_text_field( $_POST['access_token'] ) : false;
258
+ $account_id = isset( $_POST['account_id'] ) ? sanitize_text_field( $_POST['account_id'] ) : false;
259
+ $options = sbi_get_database_settings();
260
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
261
+
262
+ if ( $access_token ) {
263
+ wp_cache_delete ( 'alloptions', 'options' );
264
+
265
+ $number_dots = substr_count ( $access_token , '.' );
266
+ $test_connection_data = array( 'error_message' => 'A successful connection could not be made. Please make sure your Access Token is valid.');
267
+
268
+ if ( $number_dots > 1 ) {
269
+ $split_token = explode( '.', $access_token );
270
+ $new_user_id = isset( $split_token[0] ) ? $split_token[0] : '';
271
+
272
+ $test_connection_data = sbi_account_data_for_token( $access_token );
273
+ } else if (! empty( $account_id ) ) {
274
+
275
+ if ( sbi_code_check( $access_token ) ) {
276
+ $data = array(
277
+ 'access_token' => $access_token,
278
+ 'user_id' => $account_id,
279
+ 'type' => 'basic'
280
+ );
281
+ $basic_account_attempt = new SB_Instagram_API_Connect( $data, 'header', array() );
282
+ $basic_account_attempt->connect();
283
+
284
+ if ( !$basic_account_attempt->is_wp_error() && ! $basic_account_attempt->is_instagram_error() ) {
285
+ $new_data = $basic_account_attempt->get_data();
286
+
287
+ $basic_account_access_token_connect = new SB_Instagram_API_Connect( $data, 'access_token', array() );
288
+ $basic_account_access_token_connect->connect();
289
+ if ( !$basic_account_access_token_connect->is_wp_error() && ! $basic_account_access_token_connect->is_instagram_error() ) {
290
+
291
+ $token_data = $basic_account_access_token_connect->get_data();
292
+ $expires_in = $token_data['expires_in'];
293
+ $expires_timestamp = time() + $expires_in;
294
+
295
+ $new_connected_account = array(
296
+ 'access_token' => $access_token,
297
+ 'account_type' => $new_data['account_type'],
298
+ 'user_id' => $new_data['id'],
299
+ 'username' => $new_data['username'],
300
+ 'expires_timestamp' => $expires_timestamp,
301
+ 'type' => 'basic'
302
+ );
303
+
304
+ $updated_options = sbi_connect_basic_account( $new_connected_account );
305
+
306
+ echo wp_json_encode( $updated_options['connected_accounts'][ $new_data['id'] ] );
307
+ die();
308
+
309
+ }
310
+
311
+ }
312
+ }
313
+
314
+ $url = 'https://graph.facebook.com/'.$account_id.'?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token='.sbi_maybe_clean( $access_token );
315
+ $json = json_decode( sbi_business_account_request( $url, array( 'access_token' => $access_token ) ), true );
316
+
317
+ if ( isset( $json['error'] ) && $json['error']['type'] === 'OAuthException' ) {
318
+ $data = array(
319
+ 'access_token' => $access_token,
320
+ 'user_id' => $account_id,
321
+ 'type' => 'basic'
322
+ );
323
+ $basic_account_attempt = new SB_Instagram_API_Connect( $data, 'header', array() );
324
+ $basic_account_attempt->connect();
325
+
326
+ if ( !$basic_account_attempt->is_wp_error() && ! $basic_account_attempt->is_instagram_error() ) {
327
+ $new_data = $basic_account_attempt->get_data();
328
+
329
+ $basic_account_access_token_connect = new SB_Instagram_API_Connect( $data, 'access_token', array() );
330
+ $basic_account_access_token_connect->connect();
331
+ if ( !$basic_account_access_token_connect->is_wp_error() && ! $basic_account_access_token_connect->is_instagram_error() ) {
332
+
333
+ $token_data = $basic_account_access_token_connect->get_data();
334
+ $expires_in = $token_data['expires_in'];
335
+ $expires_timestamp = time() + $expires_in;
336
+
337
+ $new_connected_account = array(
338
+ 'access_token' => $access_token,
339
+ 'account_type' => $new_data['account_type'],
340
+ 'user_id' => $new_data['id'],
341
+ 'username' => $new_data['username'],
342
+ 'expires_timestamp' => $expires_timestamp,
343
+ 'type' => 'basic'
344
+ );
345
+
346
+ $updated_options = sbi_connect_basic_account( $new_connected_account );
347
+
348
+ echo wp_json_encode( $updated_options['connected_accounts'][ $new_data['id'] ] );
349
+ die();
350
+
351
+ }
352
+
353
+ }
354
+
355
+ die();
356
+
357
+ } else {
358
+ if ( isset( $json['id'] ) ) {
359
+ $new_user_id = $json['id'];
360
+ $test_connection_data = array(
361
+ 'access_token' => $access_token,
362
+ 'id' => $json['id'],
363
+ 'username' => $json['username'],
364
+ 'type' => 'business',
365
+ 'is_valid' => true,
366
+ 'last_checked' => time(),
367
+ 'profile_picture' => $json['profile_picture_url']
368
+ );
369
+ }
370
+ }
371
+
372
+
373
+ global $sb_instagram_posts_manager;
374
+
375
+ $sb_instagram_posts_manager->remove_error( 'at_' . $json['username'] );
376
+ delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $json['id'] );
377
+
378
+ }
379
+
380
+ if ( isset( $test_connection_data['error_message'] ) ) {
381
+ echo $test_connection_data['error_message'];
382
+ } elseif ( $test_connection_data !== false && ! empty( $new_user_id ) ) {
383
+ $username = $test_connection_data['username'] ? $test_connection_data['username'] : $connected_accounts[ $new_user_id ]['username'];
384
+ $user_id = $test_connection_data['id'] ? $test_connection_data['id'] : $connected_accounts[ $new_user_id ]['user_id'];
385
+ $profile_picture = $test_connection_data['profile_picture'] ? $test_connection_data['profile_picture'] : $connected_accounts[ $new_user_id ]['profile_picture'];
386
+ $type = isset( $test_connection_data['type'] ) ? $test_connection_data['type'] : 'personal';
387
+ $connected_accounts[ $new_user_id ] = array(
388
+ 'access_token' => sbi_get_parts( $access_token ),
389
+ 'user_id' => $user_id,
390
+ 'username' => $username,
391
+ 'type' => $type,
392
+ 'is_valid' => true,
393
+ 'last_checked' => $test_connection_data['last_checked'],
394
+ 'profile_picture' => $profile_picture
395
+ );
396
+
397
+ if ( !$options['sb_instagram_disable_resize'] ) {
398
+ if ( sbi_create_local_avatar( $username, $profile_picture ) ) {
399
+ $connected_accounts[ $new_user_id ]['local_avatar'] = true;
400
+ }
401
+ } else {
402
+ $connected_accounts[ $new_user_id ]['local_avatar'] = false;
403
+ }
404
+
405
+ if ( $type === 'business' ) {
406
+ $url = 'https://graph.facebook.com/'.$user_id.'/tags?user_id='.$user_id.'&fields=id&limit=1&access_token='.sbi_maybe_clean( $access_token );
407
+ $args = array(
408
+ 'timeout' => 60,
409
+ 'sslverify' => false
410
+ );
411
+ $response = wp_remote_get( $url, $args );
412
+
413
+ if ( ! is_wp_error( $response ) ) {
414
+ // certain ways of representing the html for double quotes causes errors so replaced here.
415
+ $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
416
+ if ( isset( $response['data'] ) ) {
417
+ $connected_accounts[ $new_user_id ]['use_tagged'] = '1';
418
+ }
419
+ }
420
+ }
421
+
422
+ delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $user_id );
423
+ global $sb_instagram_posts_manager;
424
+
425
+ $sb_instagram_posts_manager->remove_error( 'at_' . $username );
426
+ $options['connected_accounts'] = $connected_accounts;
427
+
428
+ update_option( 'sb_instagram_settings', $options );
429
+
430
+ echo wp_json_encode( $connected_accounts[ $new_user_id ] );
431
+ } else {
432
+ echo 'A successful connection could not be made. Please make sure your Access Token is valid.';
433
+ }
434
+
435
+ }
436
+
437
+ die();
438
+ }
439
+ add_action( 'wp_ajax_sbi_test_token', 'sbi_test_token' );
440
+
441
+ function sbi_delete_account() {
442
+ $nonce = $_POST['sbi_nonce'];
443
+
444
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
445
+ die ( 'You did not do this the right way!' );
446
+ }
447
+ $account_id = isset( $_POST['account_id'] ) ? sanitize_text_field( $_POST['account_id'] ) : false;
448
+ $options = get_option( 'sb_instagram_settings', array() );
449
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
450
+
451
+ wp_cache_delete ( 'alloptions', 'options' );
452
+ $username = $connected_accounts[ $account_id ]['username'];
453
+
454
+ $num_times_used = 0;
455
+
456
+ $new_con_accounts = array();
457
+ foreach ( $connected_accounts as $connected_account ) {
458
+
459
+ if ( $connected_account['username'] === $username ) {
460
+ $num_times_used++;
461
+ }
462
+
463
+ if ( $connected_account['username'] !== '' && $account_id !== $connected_account['user_id'] && ! empty( $connected_account['user_id'] ) ) {
464
+ $new_con_accounts[ $connected_account['user_id'] ] = $connected_account;
465
+ }
466
+ }
467
+
468
+ if ( $num_times_used < 2 ) {
469
+ sbi_delete_local_avatar( $username );
470
+ }
471
+
472
+ $options['connected_accounts'] = $new_con_accounts;
473
+
474
+ update_option( 'sb_instagram_settings', $options );
475
+
476
+
477
+ die();
478
+ }
479
+ add_action( 'wp_ajax_sbi_delete_account', 'sbi_delete_account' );
480
+
481
+ function sbi_account_data_for_token( $access_token ) {
482
+ $return = array(
483
+ 'id' => false,
484
+ 'username' => false,
485
+ 'is_valid' => false,
486
+ 'last_checked' => time()
487
+ );
488
+ $url = 'https://api.instagram.com/v1/users/self/?access_token=' . sbi_maybe_clean( $access_token );
489
+ $args = array(
490
+ 'timeout' => 60,
491
+ 'sslverify' => false
492
+ );
493
+ $result = wp_remote_get( $url, $args );
494
+
495
+ if ( ! is_wp_error( $result ) ) {
496
+ $data = json_decode( $result['body'] );
497
+ } else {
498
+ $data = array();
499
+ }
500
+
501
+ if ( isset( $data->data->id ) ) {
502
+ $return['id'] = $data->data->id;
503
+ $return['username'] = $data->data->username;
504
+ $return['is_valid'] = true;
505
+ $return['profile_picture'] = $data->data->profile_picture;
506
+
507
+ } elseif ( isset( $data->error_type ) && $data->error_type === 'OAuthRateLimitException' ) {
508
+ $return['error_message'] = 'This account\'s access token is currently over the rate limit. Try removing this access token from all feeds and wait an hour before reconnecting.';
509
+ } else {
510
+ $return = false;
511
+ }
512
+
513
+ $sbi_options = get_option( 'sb_instagram_settings', array() );
514
+ $sbi_options['sb_instagram_at'] = '';
515
+ update_option( 'sb_instagram_settings', $sbi_options );
516
+
517
+ return $return;
518
+ }
519
+
520
+ function sbi_get_connected_accounts_data( $sb_instagram_at ) {
521
+ $sbi_options = get_option( 'sb_instagram_settings' );
522
+ $return = array();
523
+ $return['connected_accounts'] = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
524
+
525
+ if ( ! empty( $return['connected_accounts'] ) ) {
526
+ $return['access_token'] = '';
527
+ } else {
528
+ $return['access_token'] = $sb_instagram_at;
529
+ }
530
+
531
+ if ( ! sbi_is_after_deprecation_deadline() && empty( $connected_accounts ) && ! empty( $sb_instagram_at ) ) {
532
+ $tokens = explode(',', $sb_instagram_at );
533
+ $user_ids = array();
534
+
535
+ foreach ( $tokens as $token ) {
536
+ $account = sbi_account_data_for_token( $token );
537
+ if ( isset( $account['is_valid'] ) ) {
538
+ $split = explode( '.', $token );
539
+ $return['connected_accounts'][ $split[0] ] = array(
540
+ 'access_token' => sbi_get_parts( $token ),
541
+ 'user_id' => $split[0],
542
+ 'username' => '',
543
+ 'is_valid' => true,
544
+ 'last_checked' => time(),
545
+ 'profile_picture' => ''
546
+ );
547
+ $user_ids[] = $split[0];
548
+ }
549
+
550
+ }
551
+
552
+ $sbi_options['connected_accounts'] = $return['connected_accounts'];
553
+ $sbi_options['sb_instagram_at'] = '';
554
+ $sbi_options['sb_instagram_user_id'] = $user_ids;
555
+
556
+ $return['user_ids'] = $user_ids;
557
+
558
+ update_option( 'sb_instagram_settings', $sbi_options );
559
+ }
560
+
561
+ return $return;
562
+ }
563
+
564
+ function sbi_connect_basic_account( $new_account_details ) {
565
+
566
+ $options = sbi_get_database_settings();
567
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
568
+
569
+ $accounts_to_save = array();
570
+ $old_account_user_id = '';
571
+ $ids_to_save = array();
572
+ $user_ids = is_array( $options[ 'sb_instagram_user_id' ] ) ? $options[ 'sb_instagram_user_id' ] : explode( ',', str_replace( ' ', '', $options[ 'sb_instagram_user_id' ] ) );
573
+
574
+ $profile_picture = '';
575
+
576
+ // do not connect as a basic display account if already connected as a business account
577
+ if ( isset( $connected_accounts[ $new_account_details['user_id'] ] )
578
+ && isset( $connected_accounts[ $new_account_details['user_id'] ]['type'] )
579
+ && $connected_accounts[ $new_account_details['user_id'] ]['type'] === 'business' ) {
580
+ return $options;
581
+ }
582
+
583
+ foreach ( $connected_accounts as $account ) {
584
+ $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
585
+ if ( ($account['username'] !== $new_account_details['username'])
586
+ || $account_type === 'business' ) {
587
+ $accounts_to_save[ $account['user_id'] ] = $account;
588
+ } else {
589
+ $old_account_user_id = $account['user_id'];
590
+ $profile_picture = isset( $account['profile_picture'] ) ? $account['profile_picture'] : '';
591
+ }
592
+ }
593
+
594
+ foreach ( $user_ids as $id ) {
595
+ if ( $id === $old_account_user_id ) {
596
+ $ids_to_save[] = $new_account_details['user_id'];
597
+ } else {
598
+ $ids_to_save[] = $id;
599
+ }
600
+ }
601
+
602
+ $accounts_to_save[ $new_account_details['user_id'] ] = array(
603
+ 'access_token' => sbi_fixer( $new_account_details['access_token'] ),
604
+ 'user_id' => $new_account_details['user_id'],
605
+ 'username' => $new_account_details['username'],
606
+ 'is_valid' => true,
607
+ 'last_checked' => time(),
608
+ 'expires_timestamp' => $new_account_details['expires_timestamp'],
609
+ 'profile_picture' => $profile_picture,
610
+ 'account_type' => strtolower( $new_account_details['account_type'] ),
611
+ 'type' => 'basic',
612
+ );
613
+
614
+ if ( ! empty( $old_account_user_id ) && $old_account_user_id !== $new_account_details['user_id'] ) {
615
+ $accounts_to_save[ $new_account_details['user_id'] ]['old_user_id'] = $old_account_user_id;
616
+
617
+ // get last saved header data
618
+ $fuzzy_matches = sbi_fuzzy_matching_header_data( $old_account_user_id );
619
+ if ( ! empty( $fuzzy_matches[0] ) ) {
620
+ $header_data = sbi_find_matching_data_from_results( $fuzzy_matches, $old_account_user_id );
621
+ $bio = SB_Instagram_Parse::get_bio( $header_data );
622
+ $accounts_to_save[ $new_account_details['user_id'] ]['bio'] = sbi_sanitize_emoji( $bio );
623
+ }
624
+
625
+ }
626
+
627
+ if ( ! empty( $profile_picture ) && !$options['sb_instagram_disable_resize'] ) {
628
+ if ( sbi_create_local_avatar( $new_account_details['username'], $profile_picture ) ) {
629
+ $accounts_to_save[ $new_account_details['user_id'] ]['local_avatar'] = true;
630
+ }
631
+ } else {
632
+ $accounts_to_save[ $new_account_details['user_id'] ]['local_avatar'] = false;
633
+ }
634
+
635
+ delete_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $new_account_details['user_id'] );
636
+ global $sb_instagram_posts_manager;
637
+
638
+ $sb_instagram_posts_manager->remove_error( 'at_' . $new_account_details['username'] );
639
+ $options['connected_accounts'] = $accounts_to_save;
640
+ $options['sb_instagram_user_id'] = $ids_to_save;
641
+
642
+ update_option( 'sb_instagram_settings', $options );
643
+ return $options;
644
+ }
645
+
646
+ function sbi_fuzzy_matching_header_data( $user_id ) {
647
+
648
+ if ( empty( $user_id ) || strlen( $user_id ) < 4 ) {
649
+ return array();
650
+ }
651
+ global $wpdb;
652
+ $escaped_id = esc_sql( $user_id );
653
+
654
+ $values = $wpdb->get_results( "
655
+ SELECT option_value
656
+ FROM $wpdb->options
657
+ WHERE option_name LIKE ('%!sbi\_header\_".$escaped_id."%')
658
+ LIMIT 10", ARRAY_A );
659
+
660
+ $regular_values = $wpdb->get_results( "
661
+ SELECT option_value
662
+ FROM $wpdb->options
663
+ WHERE option_name LIKE ('%sbi\_header\_".$escaped_id."%')
664
+ LIMIT 10", ARRAY_A );
665
+
666
+ $values = array_merge( $values, $regular_values );
667
+
668
+ return $values;
669
+ }
670
+
671
+ function sbi_find_matching_data_from_results( $results, $user_id ) {
672
+
673
+ $match = array();
674
+
675
+ $i = 0;
676
+
677
+ while( empty( $match ) && isset( $results[ $i ] ) ) {
678
+ if ( ! empty( $results[ $i ] ) ) {
679
+ $header_data = json_decode( $results[ $i ]['option_value'], true );
680
+ if ( isset( $header_data['id'] ) && (string)$header_data['id'] === (string)$user_id ) {
681
+ $match = $header_data;
682
+ }
683
+ }
684
+ $i++;
685
+ }
686
+
687
+ return $match;
688
+ }
689
+
690
+ function sbi_matches_existing_personal( $new_account_details ) {
691
+
692
+ $options = sbi_get_database_settings();
693
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
694
+
695
+ $matches_one_account = false;
696
+ $accounts_to_save = array();
697
+ foreach ( $connected_accounts as $account ) {
698
+ $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
699
+ if ( ($account_type === 'personal' || $account_type === 'basic')
700
+ && $account['username'] == $new_account_details['username'] ) {
701
+ $matches_one_account = true;
702
+
703
+
704
+ }
705
+ }
706
+
707
+ return $matches_one_account;
708
+
709
+ }
710
+
711
+ function sbi_business_account_request( $url, $account, $remove_access_token = true ) {
712
+ $args = array(
713
+ 'timeout' => 60,
714
+ 'sslverify' => false
715
+ );
716
+ $result = wp_remote_get( $url, $args );
717
+
718
+ if ( ! is_wp_error( $result ) ) {
719
+ $response_no_at = $remove_access_token ? str_replace( sbi_maybe_clean( $account['access_token'] ), '{accesstoken}', $result['body'] ) : $result['body'];
720
+ return $response_no_at;
721
+ } else {
722
+ return wp_json_encode( $result );
723
+ }
724
+ }
725
+
726
+ function sbi_after_connection() {
727
+
728
+ if ( isset( $_POST['access_token'] ) ) {
729
+ $access_token = sanitize_text_field( $_POST['access_token'] );
730
+ $account_info = sbi_account_data_for_token( $access_token );
731
+ echo wp_json_encode( $account_info );
732
+ }
733
+
734
+ die();
735
+ }
736
+ add_action( 'wp_ajax_sbi_after_connection', 'sbi_after_connection' );
737
+
738
+ function sbi_account_type_display( $type ) {
739
+ if ( $type === 'basic' ) {
740
+ return 'personal (new API)';
741
+ }
742
+ return $type;
743
+ }
744
+
745
+ function sbi_clear_backups() {
746
+ $nonce = isset( $_POST['sbi_nonce'] ) ? sanitize_text_field( $_POST['sbi_nonce'] ) : '';
747
+
748
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
749
+ die ( 'You did not do this the right way!' );
750
+ }
751
+
752
+ //Delete all transients
753
+ global $wpdb;
754
+ $table_name = $wpdb->prefix . "options";
755
+ $wpdb->query( "
756
+ DELETE
757
+ FROM $table_name
758
+ WHERE `option_name` LIKE ('%!sbi\_%')
759
+ " );
760
+ $wpdb->query( "
761
+ DELETE
762
+ FROM $table_name
763
+ WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
764
+ " );
765
+ $wpdb->query( "
766
+ DELETE
767
+ FROM $table_name
768
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
769
+ " );
770
+
771
+ die();
772
+ }
773
+ add_action( 'wp_ajax_sbi_clear_backups', 'sbi_clear_backups' );
774
+
775
+ function sbi_reset_resized() {
776
+
777
+ global $sb_instagram_posts_manager;
778
+ $sb_instagram_posts_manager->delete_all_sbi_instagram_posts();
779
+
780
+ echo "1";
781
+
782
+ die();
783
+ }
784
+ add_action( 'wp_ajax_sbi_reset_resized', 'sbi_reset_resized' );
785
+
786
+ function sbi_lite_dismiss() {
787
+ $nonce = isset( $_POST['sbi_nonce'] ) ? sanitize_text_field( $_POST['sbi_nonce'] ) : '';
788
+
789
+ if ( ! wp_verify_nonce( $nonce, 'sbi_nonce' ) ) {
790
+ die ( 'You did not do this the right way!' );
791
+ }
792
+
793
+ set_transient( 'instagram_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS );
794
+
795
+ die();
796
+ }
797
+ add_action( 'wp_ajax_sbi_lite_dismiss', 'sbi_lite_dismiss' );
798
+
799
+ function sbi_reset_log() {
800
+ global $sb_instagram_posts_manager;
801
+
802
+ $sb_instagram_posts_manager->remove_all_errors();
803
+
804
+ echo "1";
805
+
806
+ die();
807
+ }
808
+ add_action( 'wp_ajax_sbi_reset_log', 'sbi_reset_log' );
809
+
810
+ add_action('admin_notices', 'sbi_admin_error_notices');
811
+ function sbi_admin_error_notices() {
812
+
813
+
814
+ if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'sb-instagram-feed' )) ) {
815
+ global $sb_instagram_posts_manager;
816
+
817
+ $errors = $sb_instagram_posts_manager->get_errors();
818
+ if ( ! empty( $errors ) && ( isset( $errors['database_create_posts'] ) || isset( $errors['database_create_posts_feeds'] ) || isset( $errors['upload_dir'] ) || isset( $errors['ajax'] ) ) ) : ?>
819
+ <div class="notice notice-warning is-dismissible sbi-admin-notice">
820
+
821
+ <?php foreach ( $sb_instagram_posts_manager->get_errors() as $type => $error ) : ?>
822
+ <?php if ( (in_array( $type, array( 'database_create_posts', 'database_create_posts_feeds', 'upload_dir' ) ) && !$sb_instagram_posts_manager->image_resizing_disabled() ) ) : ?>
823
+ <p><strong><?php echo $error[0]; ?></strong></p>
824
+ <p><?php _e( 'Note for support', 'instagram-feed' ); ?>: <?php echo $error[1]; ?></p>
825
+ <?php endif; ?>
826
+ <?php endforeach; ?>
827
+ <?php if ( ( isset( $errors['database_create_posts'] ) || isset( $errors['database_create_posts_feeds'] ) || isset( $errors['upload_dir'] ) ) && !$sb_instagram_posts_manager->image_resizing_disabled() ) : ?>
828
+ <p><?php _e( sprintf( 'Visit our %s page for help', '<a href="https://smashballoon.com/instagram-feed/support/faq/" target="_blank">FAQ</a>' ), 'instagram-feed' ); ?></p>
829
+ <?php endif; ?>
830
+
831
+ <?php foreach ( $sb_instagram_posts_manager->get_errors() as $type => $error ) : ?>
832
+ <?php if (in_array( $type, array( 'ajax' ) )) : ?>
833
+ <p class="sbi-admin-error" data-sbi-type="ajax"><strong><?php echo $error[0]; ?></strong></p>
834
+ <p><?php echo $error[1]; ?></p>
835
+ <?php endif; ?>
836
+ <?php endforeach; ?>
837
+
838
+ </div>
839
+
840
+ <?php endif;
841
+ $errors = $sb_instagram_posts_manager->get_critical_errors();
842
+ if ( $sb_instagram_posts_manager->are_critical_errors() && ! empty( $errors ) ) : ?>
843
+ <div class="notice notice-warning is-dismissible sbi-admin-notice">
844
+ <p><strong><?php echo esc_html__( 'Instagram Feed is encountering an error and your feeds may not be updating due to the following reasons:', 'instagram-feed') ; ?></strong></p>
845
+
846
+ <?php echo $errors; ?>
847
+
848
+ <?php
849
+ $error_page = $sb_instagram_posts_manager->get_error_page();
850
+ if ( $error_page ) {
851
+ echo '<a href="' . get_the_permalink( $error_page ) . '" class="sbi-clear-errors-visit-page sbi-space-left button button-secondary">' . __( 'View Feed and Retry', 'instagram-feed' ) . '</a>';
852
+ }
853
+ ?>
854
+ </div>
855
+ <?php endif;
856
+ }
857
+
858
+ }
859
+
860
+ function sbi_maybe_add_ajax_test_error() {
861
+ if ( isset( $_GET['page'] ) && $_GET['page'] === 'sb-instagram-feed' ) {
862
+ global $sb_instagram_posts_manager;
863
+
864
+ if ( $sb_instagram_posts_manager->should_add_ajax_test_notice() ) {
865
+ $sb_instagram_posts_manager->add_error( 'ajax', array( __( 'Unable to use admin-ajax.php when displaying feeds. Some features of the plugin will be unavailable.', 'instagram-feed' ), __( sprintf( 'Please visit %s to troubleshoot.', '<a href="https://smashballoon.com/admin-ajax-requests-are-not-working/">'.__( 'this page', 'instagram-feed' ).'</a>' ), 'instagram-feed' ) ) );
866
+ } else {
867
+ $sb_instagram_posts_manager->remove_error( 'ajax' );
868
+ }
869
+ }
870
+ }
871
+ add_action( 'admin_init', 'sbi_maybe_add_ajax_test_error' );
872
+
873
+ function sbi_get_user_names_of_personal_accounts_not_also_already_updated() {
874
+ $sbi_options = get_option( 'sb_instagram_settings', array() );
875
+ $users_in_personal_accounts = array();
876
+ $non_personal_account_users = array();
877
+
878
+ $connected_accounts = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
879
+
880
+ if ( ! empty( $connected_accounts ) ) {
881
+
882
+ foreach ( $connected_accounts as $account ) {
883
+ $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
884
+
885
+ if ( $account_type === 'personal' ) {
886
+ $users_in_personal_accounts[] = $account['username'];
887
+ } else {
888
+ $non_personal_account_users[] = $account['username'];
889
+ }
890
+
891
+ }
892
+
893
+ if ( ! empty( $users_in_personal_accounts ) ) {
894
+ $user_accounts_that_need_updating = array();
895
+ foreach ( $users_in_personal_accounts as $personal_user ) {
896
+ if ( ! in_array( $personal_user, $non_personal_account_users, true ) && $personal_user !== '' ) {
897
+ $user_accounts_that_need_updating[] = $personal_user;
898
+ }
899
+ }
900
+
901
+ return $user_accounts_that_need_updating;
902
+ }
903
+ } elseif ( empty( $connected_accounts ) && ! empty( $sbi_options['sb_instagram_at'] ) ) {
904
+ return array( 'your Instagram feed');
905
+ }
906
+
907
+ return array();
908
+ }
909
+
910
+ function sbi_reconnect_accounts_notice() {
911
+ if( ! current_user_can( 'manage_options' ) ) return;
912
+
913
+ $should_show_link = ! isset( $_GET['page'] ) || $_GET['page'] !== 'sb-instagram-feed';
914
+ $personal_accounts_that_need_updating = sbi_get_user_names_of_personal_accounts_not_also_already_updated();
915
+ if ( empty( $personal_accounts_that_need_updating ) ) {
916
+ return;
917
+ } else {
918
+ $total = count( $personal_accounts_that_need_updating );
919
+ if ( $total > 1 ) {
920
+ $user_string = '';
921
+ $i = 0;
922
+
923
+ foreach ( $personal_accounts_that_need_updating as $username ) {
924
+ if ( ($i + 1) === $total ) {
925
+ $user_string .= ' and ' . $username;
926
+ } else {
927
+ if ( $i !== 0 ) {
928
+ $user_string .= ', ' . $username;
929
+ } else {
930
+ $user_string .= $username;
931
+ }
932
+ }
933
+ $i++;
934
+ }
935
+ } else {
936
+ $user_string = $personal_accounts_that_need_updating[0];
937
+ }
938
+
939
+ if ( sbi_is_after_deprecation_deadline() ) {
940
+ $notice_class = 'notice-error';
941
+ $error = '<p><b>' . sprintf( __( 'Error: Instagram Feed plugin - account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to recent Instagram platform changes some Instagram accounts will need to be reconnected in the plugin in order for them to continue updating.', 'instagram-feed' );
942
+ } else {
943
+ $notice_class = 'notice-warning';
944
+ $error = '<p><b>' . sprintf( __( 'Warning: Instagram Feed plugin - account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to Instagram platform changes on March 31, 2020, some Instagram accounts will need to be reconnected in the plugin to avoid disruption to your feeds.', 'instagram-feed' );
945
+ }
946
+ if( !$should_show_link ) $error .= __( ' Use the big blue button below to reconnect your account.', 'instagram-feed' );
947
+ }
948
+ $url = admin_url( '?page=sb-instagram-feed' );
949
+
950
+ ?>
951
+ <div class="notice <?php echo $notice_class; ?> is-dismissible">
952
+ <?php echo $error; ?>
953
+ <p>
954
+ <?php if ( $should_show_link ) : ?>
955
+ <a href="<?php echo $url; ?>" class="button-primary" style="margin-right:10px;"><i class="fa fa-instagram" aria-hidden="true"></i> &nbsp;Reconnect on Settings Page</a>
956
+ <?php endif; ?>
957
+ <a href="https://smashballoon.com/instagram-api-changes-march-2-2020/" target="_blank" rel="noopener">See more details</a>
958
+ </p>
959
+ </div>
960
+
961
+ <?php
962
+
963
+ }
964
+ add_action( 'admin_notices', 'sbi_reconnect_accounts_notice' );
965
+
966
+ function sbi_get_current_time() {
967
+ $current_time = time();
968
+
969
+ // where to do tests
970
+ // $current_time = strtotime( 'November 25, 2022' ) + 1;
971
+
972
+ return $current_time;
973
+ }
974
+
975
+ // generates the html for the admin notices
976
+ function sbi_notices_html() {
977
+
978
+ //Only show to admins
979
+ $current_screen = get_current_screen();
980
+ $is_plugins_page = isset( $current_screen->id ) && $current_screen->id === 'plugins';
981
+ $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : '';
982
+ //Only show to admins
983
+ if ( ! current_user_can( 'manage_options' ) ) {
984
+ return;
985
+ }
986
+
987
+ $sbi_statuses_option = get_option( 'sbi_statuses', array() );
988
+ $current_time = sbi_get_current_time();
989
+ $sbi_bfcm_discount_code = 'happysmashgiving' . date('Y', $current_time );
990
+
991
+ // reset everything for testing
992
+ if ( false ) {
993
+ global $current_user;
994
+ $user_id = $current_user->ID;
995
+ delete_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
996
+ //delete_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
997
+ //$sbi_statuses_option = array( 'first_install' => strtotime( 'December 8, 2019' ) );
998
+ //$sbi_statuses_option = array( 'first_install' => time() );
999
+
1000
+ //update_option( 'sbi_statuses', $sbi_statuses_option, false );
1001
+ //delete_option( 'sbi_rating_notice');
1002
+ //delete_transient( 'instagram_feed_rating_notice_waiting' );
1003
+
1004
+ //set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
1005
+ //update_option( 'sbi_rating_notice', 'pending', false );
1006
+ }
1007
+
1008
+ //$sbi_statuses_option['rating_notice_dismissed'] = time();
1009
+ //update_option( 'sbi_statuses', $sbi_statuses_option, false );
1010
+ // rating notice logic
1011
+ $sbi_rating_notice_option = get_option( 'sbi_rating_notice', false );
1012
+ $sbi_rating_notice_waiting = get_transient( 'instagram_feed_rating_notice_waiting' );
1013
+ $should_show_rating_notice = ($sbi_rating_notice_waiting !== 'waiting' && $sbi_rating_notice_option !== 'dismissed');
1014
+
1015
+ // black friday cyber monday logic
1016
+ $thanksgiving_this_year = sbi_get_future_date( 11, date('Y', $current_time ), 4, 4, 1 );
1017
+ $one_week_before_black_friday_this_year = $thanksgiving_this_year - 7*24*60*60;
1018
+ $one_day_after_cyber_monday_this_year = $thanksgiving_this_year + 5*24*60*60;
1019
+ $has_been_two_days_since_rating_dismissal = isset( $sbi_statuses_option['rating_notice_dismissed'] ) ? ((int)$sbi_statuses_option['rating_notice_dismissed'] + 2*24*60*60) < $current_time : true;
1020
+
1021
+ $could_show_bfcm_discount = ($current_time > $one_week_before_black_friday_this_year && $current_time < $one_day_after_cyber_monday_this_year);
1022
+ $should_show_bfcm_discount = false;
1023
+ if ( $could_show_bfcm_discount && $has_been_two_days_since_rating_dismissal ) {
1024
+ global $current_user;
1025
+ $user_id = $current_user->ID;
1026
+
1027
+ $ignore_bfcm_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
1028
+ $ignore_bfcm_sale_notice_meta = isset( $ignore_bfcm_sale_notice_meta[0] ) ? $ignore_bfcm_sale_notice_meta[0] : '';
1029
+
1030
+ /* Check that the user hasn't already clicked to ignore the message */
1031
+ $should_show_bfcm_discount = ($ignore_bfcm_sale_notice_meta !== 'always' && $ignore_bfcm_sale_notice_meta !== date( 'Y', $current_time ));
1032
+ }
1033
+
1034
+ // new user discount logic
1035
+ $in_new_user_month_range = true;
1036
+ $should_show_new_user_discount = false;
1037
+ $has_been_one_month_since_rating_dismissal = isset( $sbi_statuses_option['rating_notice_dismissed'] ) ? ((int)$sbi_statuses_option['rating_notice_dismissed'] + 30*24*60*60) < $current_time + 1: true;
1038
+
1039
+ if ( isset( $sbi_statuses_option['first_install'] ) && $sbi_statuses_option['first_install'] === 'from_update' ) {
1040
+ global $current_user;
1041
+ $user_id = $current_user->ID;
1042
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1043
+ $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
1044
+ if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
1045
+ $should_show_new_user_discount = true;
1046
+ }
1047
+ } elseif ( $in_new_user_month_range && $has_been_one_month_since_rating_dismissal ) {
1048
+ global $current_user;
1049
+ $user_id = $current_user->ID;
1050
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1051
+ $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
1052
+
1053
+ if ( $ignore_new_user_sale_notice_meta !== 'always'
1054
+ && isset( $sbi_statuses_option['first_install'] )
1055
+ && $current_time > (int)$sbi_statuses_option['first_install'] + 60*60*24*30 ) {
1056
+ $should_show_new_user_discount = true;
1057
+ }
1058
+ }
1059
+
1060
+ // for debugging
1061
+ if ( false ) {
1062
+ global $current_user;
1063
+ $user_id = $current_user->ID;
1064
+ $ignore_bfcm_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice' );
1065
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1066
+
1067
+ var_dump( 'new user rating option', $sbi_rating_notice_option );
1068
+ var_dump( 'new user rating transient', $sbi_rating_notice_waiting );
1069
+
1070
+ var_dump( 'should show new user rating notice?', $should_show_rating_notice );
1071
+
1072
+ var_dump( 'new user discount month range?', $in_new_user_month_range );
1073
+ var_dump( 'should show new user discount?', $should_show_new_user_discount );
1074
+
1075
+ var_dump( 'Thanksgiving this year?', date('m/d/Y', $thanksgiving_this_year ) );
1076
+
1077
+ var_dump( 'could show bfcm discount?', $could_show_bfcm_discount );
1078
+ var_dump( 'should show bfcm discount?', $should_show_bfcm_discount );
1079
+
1080
+ var_dump( 'ignore_bfcm_sale_notice_meta', $ignore_bfcm_sale_notice_meta );
1081
+ var_dump( 'ignore_new_user_sale_notice_meta', $ignore_new_user_sale_notice_meta );
1082
+
1083
+ var_dump( $sbi_statuses_option );
1084
+ }
1085
+
1086
+
1087
+ if ( $should_show_rating_notice ) {
1088
+ $other_notice_html = '';
1089
+ $dismiss_url = add_query_arg( 'sbi_ignore_rating_notice_nag', '1' );
1090
+ $later_url = add_query_arg( 'sbi_ignore_rating_notice_nag', 'later' );
1091
+ if ( $should_show_bfcm_discount ) {
1092
+ $other_notice_html = '<p class="sbi_other_notice">' . __( 'PS. We currently have a <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount='.$sbi_bfcm_discount_code.'" target="_blank"><b style="font-weight: 700;">Black Friday deal</b></a> for 60% off the Pro version!', 'instagram-feed' ) . '</a></p>';
1093
+
1094
+ $dismiss_url = add_query_arg( array(
1095
+ 'sbi_ignore_rating_notice_nag' => '1',
1096
+ 'sbi_ignore_bfcm_sale_notice' => date( 'Y', $current_time )
1097
+ )
1098
+ );
1099
+ $later_url = add_query_arg( array(
1100
+ 'sbi_ignore_rating_notice_nag' => 'later',
1101
+ 'sbi_ignore_bfcm_sale_notice' => date( 'Y', $current_time )
1102
+ )
1103
+ );
1104
+ }
1105
+
1106
+ echo "
1107
+ <div class='sbi_notice sbi_review_notice'>
1108
+ <img src='". SBI_PLUGIN_URL . 'img/sbi-icon.png' ."' alt='" . __( 'Instagram Feed', 'instagram-feed' ) . "'>
1109
+ <div class='sbi-notice-text'>
1110
+ <p style='padding-top: 4px;'>" . __( "It's great to see that you've been using the <strong style='font-weight: 700;'>Instagram Feed</strong> plugin for a while now. Hopefully you're happy with it!&nbsp; If so, would you consider leaving a positive review? It really helps to support the plugin and helps others to discover it too!", 'instagram-feed' ) . "</p>
1111
+ <p class='links'";
1112
+ if( $should_show_bfcm_discount ) echo " style='margin-top: 0 !important;'";
1113
+ echo ">
1114
+ <a class='sbi_notice_dismiss' href='https://wordpress.org/support/plugin/instagram-feed/reviews/' target='_blank'>" . __( 'Sure, I\'d love to!', 'instagram-feed' ) . "</a>
1115
+ &middot;
1116
+ <a class='sbi_notice_dismiss' href='" .esc_url( $dismiss_url ). "'>" . __( 'No thanks', 'instagram-feed' ) . "</a>
1117
+ &middot;
1118
+ <a class='sbi_notice_dismiss' href='" .esc_url( $dismiss_url ). "'>" . __( 'I\'ve already given a review', 'instagram-feed' ) . "</a>
1119
+ &middot;
1120
+ <a class='sbi_notice_dismiss' href='" .esc_url( $later_url ). "'>" . __( 'Ask Me Later', 'instagram-feed' ) . "</a>
1121
+ </p>"
1122
+ . $other_notice_html .
1123
+ "</div>
1124
+ <a class='sbi_notice_close' href='" .esc_url( $dismiss_url ). "'><i class='fa fa-close'></i></a>
1125
+ </div>";
1126
+
1127
+ } elseif ( $should_show_new_user_discount ) {
1128
+ global $current_user;
1129
+ $user_id = $current_user->ID;
1130
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice' );
1131
+ if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
1132
+
1133
+ echo "
1134
+ <div class='sbi_notice sbi_review_notice sbi_new_user_sale_notice'>
1135
+ <img src='" . SBI_PLUGIN_URL . 'img/sbi-icon-offer.png' . "' alt='Instagram Feed'>
1136
+ <div class='sbi-notice-text'>
1137
+ <p>" . __( '<b style="font-weight: 700;">Exclusive offer!</b> We don\'t run promotions very often, but for a limited time we\'re offering <b style="font-weight: 700;">60% off</b> our Pro version to all users of our free Instagram Feed plugin.', 'instagram-feed' ) . "</p>
1138
+ <p class='sbi-links'>
1139
+ <a class='sbi_notice_dismiss sbi_offer_btn' href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount=instagramthankyou' target='_blank'><b>" . __( 'Get this offer', 'instagram-feed' ) . "</b></a>
1140
+ <a class='sbi_notice_dismiss' style='margin-left: 5px;' href='" . esc_url( add_query_arg( 'sbi_ignore_new_user_sale_notice', 'always' ) ) . "'>" . __( 'I\'m not interested', 'instagram-feed' ) . "</a>
1141
+
1142
+ </p>
1143
+ </div>
1144
+ <a class='sbi_new_user_sale_notice_close' href='" . esc_url( add_query_arg( 'sbi_ignore_new_user_sale_notice', 'always' ) ) . "'><i class='fa fa-close'></i></a>
1145
+ </div>
1146
+ ";
1147
+ }
1148
+
1149
+ } elseif ( $should_show_bfcm_discount ) {
1150
+
1151
+ echo "
1152
+ <div class='sbi_notice sbi_review_notice sbi_bfcm_sale_notice'>
1153
+ <img src='". SBI_PLUGIN_URL . 'img/sbi-icon-offer.png' ."' alt='Instagram Feed'>
1154
+ <div class='sbi-notice-text'>
1155
+ <p>" . __( '<b style="font-weight: 700;">Black Friday/Cyber Monday Deal!</b> Thank you for using our free Instagram Feed plugin. For a limited time, we\'re offering <b style="font-weight: 700;">60% off</b> the Pro version for all of our users.', 'instagram-feed' ) . "</p>
1156
+ <p class='sbi-links'>
1157
+ <a class='sbi_notice_dismiss sbi_offer_btn' href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi&discount=".$sbi_bfcm_discount_code."' target='_blank'>" . __( 'Get this offer!', 'instagram-feed' ) . "</a>
1158
+ <a class='sbi_notice_dismiss' style='margin-left: 5px;' href='" .esc_url( add_query_arg( 'sbi_ignore_bfcm_sale_notice', date( 'Y', $current_time ) ) ). "'>" . __( 'I\'m not interested', 'instagram-feed' ) . "</a>
1159
+ </p>
1160
+ </div>
1161
+ <a class='sbi_bfcm_sale_notice_close' href='" .esc_url( add_query_arg( 'sbi_ignore_bfcm_sale_notice', date( 'Y', $current_time ) ) ). "'><i class='fa fa-close'></i></a>
1162
+ </div>
1163
+ ";
1164
+
1165
+ }
1166
+
1167
+ }
1168
+ add_action( 'admin_notices', 'sbi_notices_html', 8 ); // priority 12 for Twitter, priority 10 for Facebook
1169
+
1170
+ function sbi_process_nags() {
1171
+
1172
+ global $current_user;
1173
+ $user_id = $current_user->ID;
1174
+ $sbi_statuses_option = get_option( 'sbi_statuses', array() );
1175
+
1176
+ if ( isset( $_GET['sbi_ignore_rating_notice_nag'] ) ) {
1177
+ if ( (int)$_GET['sbi_ignore_rating_notice_nag'] === 1 ) {
1178
+ update_option( 'sbi_rating_notice', 'dismissed', false );
1179
+ $sbi_statuses_option['rating_notice_dismissed'] = sbi_get_current_time();
1180
+ update_option( 'sbi_statuses', $sbi_statuses_option, false );
1181
+
1182
+ } elseif ( $_GET['sbi_ignore_rating_notice_nag'] === 'later' ) {
1183
+ set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
1184
+ update_option( 'sbi_rating_notice', 'pending', false );
1185
+ }
1186
+ }
1187
+
1188
+ if ( isset( $_GET['sbi_ignore_new_user_sale_notice'] ) ) {
1189
+ $response = sanitize_text_field( $_GET['sbi_ignore_new_user_sale_notice'] );
1190
+ if ( $response === 'always' ) {
1191
+ update_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice', 'always' );
1192
+
1193
+ $current_month_number = (int)date('n', sbi_get_current_time() );
1194
+ $not_early_in_the_year = ($current_month_number > 5);
1195
+
1196
+ if ( $not_early_in_the_year ) {
1197
+ update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', date( 'Y', sbi_get_current_time() ) );
1198
+ }
1199
+
1200
+ }
1201
+ }
1202
+
1203
+ if ( isset( $_GET['sbi_ignore_bfcm_sale_notice'] ) ) {
1204
+ $response = sanitize_text_field( $_GET['sbi_ignore_bfcm_sale_notice'] );
1205
+ if ( $response === 'always' ) {
1206
+ update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', 'always' );
1207
+ } elseif ( $response === date( 'Y', sbi_get_current_time() ) ) {
1208
+ update_user_meta( $user_id, 'sbi_ignore_bfcm_sale_notice', date( 'Y', sbi_get_current_time() ) );
1209
+ }
1210
+ update_user_meta( $user_id, 'sbi_ignore_new_user_sale_notice', 'always' );
1211
+ }
1212
+
1213
+ }
1214
+ add_action( 'admin_init', 'sbi_process_nags' );
1215
+
1216
+ function sbi_get_future_date( $month, $year, $week, $day, $direction ) {
1217
+ if ( $direction > 0 ) {
1218
+ $startday = 1;
1219
+ } else {
1220
+ $startday = date( 't', mktime(0, 0, 0, $month, 1, $year ) );
1221
+ }
1222
+
1223
+ $start = mktime( 0, 0, 0, $month, $startday, $year );
1224
+ $weekday = date( 'N', $start );
1225
+
1226
+ $offset = 0;
1227
+ if ( $direction * $day >= $direction * $weekday ) {
1228
+ $offset = -$direction * 7;
1229
+ }
1230
+
1231
+ $offset += $direction * ($week * 7) + ($day - $weekday);
1232
+ return mktime( 0, 0, 0, $month, $startday + $offset, $year );
1233
+ }
1234
+
1235
+ function sbi_admin_hide_unrelated_notices() {
1236
+
1237
+ // Bail if we're not on a sbi screen or page.
1238
+ if ( ! isset( $_GET['page'] ) || strpos( $_GET['page'], 'sb-instagram-feed') === false ) {
1239
+ return;
1240
+ }
1241
+
1242
+ // Extra banned classes and callbacks from third-party plugins.
1243
+ $blacklist = array(
1244
+ 'classes' => array(),
1245
+ 'callbacks' => array(
1246
+ 'sbidb_admin_notice', // 'Database for sbi' plugin.
1247
+ ),
1248
+ );
1249
+
1250
+ global $wp_filter;
1251
+
1252
+ foreach ( array( 'user_admin_notices', 'admin_notices', 'all_admin_notices' ) as $notices_type ) {
1253
+ if ( empty( $wp_filter[ $notices_type ]->callbacks ) || ! is_array( $wp_filter[ $notices_type ]->callbacks ) ) {
1254
+ continue;
1255
+ }
1256
+ foreach ( $wp_filter[ $notices_type ]->callbacks as $priority => $hooks ) {
1257
+ foreach ( $hooks as $name => $arr ) {
1258
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
1259
+ unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
1260
+ continue;
1261
+ }
1262
+ $class = ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) ? strtolower( get_class( $arr['function'][0] ) ) : '';
1263
+ if (
1264
+ ! empty( $class ) &&
1265
+ strpos( $class, 'sbi' ) !== false &&
1266
+ ! in_array( $class, $blacklist['classes'], true )
1267
+ ) {
1268
+ continue;
1269
+ }
1270
+ if (
1271
+ ! empty( $name ) && (
1272
+ strpos( $name, 'sbi' ) === false ||
1273
+ in_array( $class, $blacklist['classes'], true ) ||
1274
+ in_array( $name, $blacklist['callbacks'], true )
1275
+ )
1276
+ ) {
1277
+ unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
1278
+ }
1279
+ }
1280
+ }
1281
+ }
1282
+ }
1283
+ add_action( 'admin_print_scripts', 'sbi_admin_hide_unrelated_notices' );
inc/admin/addon-functions.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+
4
+ /**
5
+ * Deactivate addon.
6
+ *
7
+ * @since 1.0.0
8
+ */
9
+ function sbi_deactivate_addon() {
10
+
11
+ // Run a security check.
12
+ check_ajax_referer( 'sbi-admin', 'nonce' );
13
+
14
+ // Check for permissions.
15
+ if ( ! current_user_can( 'manage_instagram_feed_options' ) ) {
16
+ wp_send_json_error();
17
+ }
18
+
19
+ $type = 'addon';
20
+ if ( ! empty( $_POST['type'] ) ) {
21
+ $type = sanitize_key( $_POST['type'] );
22
+ }
23
+
24
+ if ( isset( $_POST['plugin'] ) ) {
25
+ deactivate_plugins( $_POST['plugin'] );
26
+
27
+ if ( 'plugin' === $type ) {
28
+ wp_send_json_success( esc_html__( 'Plugin deactivated.', 'instagram-feed' ) );
29
+ } else {
30
+ wp_send_json_success( esc_html__( 'Addon deactivated.', 'instagram-feed' ) );
31
+ }
32
+ }
33
+
34
+ wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'instagram-feed' ) );
35
+ }
36
+ add_action( 'wp_ajax_sbi_deactivate_addon', 'sbi_deactivate_addon' );
37
+
38
+ /**
39
+ * Activate addon.
40
+ *
41
+ * @since 1.0.0
42
+ */
43
+ function sbi_activate_addon() {
44
+
45
+ // Run a security check.
46
+ check_ajax_referer( 'sbi-admin', 'nonce' );
47
+
48
+ // Check for permissions.
49
+ if ( ! current_user_can( 'manage_instagram_feed_options' ) ) {
50
+ wp_send_json_error();
51
+ }
52
+
53
+ if ( isset( $_POST['plugin'] ) ) {
54
+
55
+ $type = 'addon';
56
+ if ( ! empty( $_POST['type'] ) ) {
57
+ $type = sanitize_key( $_POST['type'] );
58
+ }
59
+
60
+ $activate = activate_plugins( $_POST['plugin'] );
61
+
62
+ if ( ! is_wp_error( $activate ) ) {
63
+ if ( 'plugin' === $type ) {
64
+ wp_send_json_success( esc_html__( 'Plugin activated.', 'instagram-feed' ) );
65
+ } else {
66
+ wp_send_json_success( esc_html__( 'Addon activated.', 'instagram-feed' ) );
67
+ }
68
+ }
69
+ }
70
+
71
+ wp_send_json_error( esc_html__( 'Could not activate addon. Please activate from the Plugins page.', 'instagram-feed' ) );
72
+ }
73
+ add_action( 'wp_ajax_sbi_activate_addon', 'sbi_activate_addon' );
74
+
75
+ /**
76
+ * Install addon.
77
+ *
78
+ * @since 1.0.0
79
+ */
80
+ function sbi_install_addon() {
81
+
82
+ // Run a security check.
83
+ check_ajax_referer( 'sbi-admin', 'nonce' );
84
+
85
+ // Check for permissions.
86
+ if ( ! current_user_can( 'manage_instagram_feed_options' ) ) {
87
+ wp_send_json_error();
88
+ }
89
+
90
+ $error = esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'instagram-feed' );
91
+
92
+ if ( empty( $_POST['plugin'] ) ) {
93
+ wp_send_json_error( $error );
94
+ }
95
+
96
+ // Set the current screen to avoid undefined notices.
97
+ set_current_screen( 'sb-instagram-feed-about' );
98
+
99
+ // Prepare variables.
100
+ $url = esc_url_raw(
101
+ add_query_arg(
102
+ array(
103
+ 'page' => 'sb-instagram-feed-about',
104
+ ),
105
+ admin_url( 'admin.php' )
106
+ )
107
+ );
108
+
109
+ $creds = request_filesystem_credentials( $url, '', false, false, null );
110
+
111
+ // Check for file system permissions.
112
+ if ( false === $creds ) {
113
+ wp_send_json_error( $error );
114
+ }
115
+
116
+ if ( ! WP_Filesystem( $creds ) ) {
117
+ wp_send_json_error( $error );
118
+ }
119
+
120
+ /*
121
+ * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
122
+ */
123
+
124
+ require_once SBI_PLUGIN_DIR . 'inc/admin/class-install-skin.php';
125
+
126
+ // Do not allow WordPress to search/download translations, as this will break JS output.
127
+ remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
128
+
129
+ // Create the plugin upgrader with our custom skin.
130
+ $installer = new Sbi\Helpers\PluginSilentUpgrader( new Sbi_Install_Skin() );
131
+
132
+ // Error check.
133
+ if ( ! method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) {
134
+ wp_send_json_error( $error );
135
+ }
136
+
137
+ $installer->install( $_POST['plugin'] ); // phpcs:ignore
138
+
139
+ // Flush the cache and return the newly installed plugin basename.
140
+ wp_cache_flush();
141
+
142
+ $plugin_basename = $installer->plugin_info();
143
+
144
+ if ( $plugin_basename ) {
145
+
146
+ $type = 'addon';
147
+ if ( ! empty( $_POST['type'] ) ) {
148
+ $type = sanitize_key( $_POST['type'] );
149
+ }
150
+
151
+ // Activate the plugin silently.
152
+ $activated = activate_plugin( $plugin_basename );
153
+
154
+ if ( ! is_wp_error( $activated ) ) {
155
+ wp_send_json_success(
156
+ array(
157
+ 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed & activated.', 'instagram-feed' ) : esc_html__( 'Addon installed & activated.', 'instagram-feed' ),
158
+ 'is_activated' => true,
159
+ 'basename' => $plugin_basename,
160
+ )
161
+ );
162
+ } else {
163
+ wp_send_json_success(
164
+ array(
165
+ 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed.', 'instagram-feed' ) : esc_html__( 'Addon installed.', 'instagram-feed' ),
166
+ 'is_activated' => false,
167
+ 'basename' => $plugin_basename,
168
+ )
169
+ );
170
+ }
171
+ }
172
+
173
+ wp_send_json_error( $error );
174
+ }
175
+ add_action( 'wp_ajax_sbi_install_addon', 'sbi_install_addon' );
inc/admin/blocks/class-sbi-blocks.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Instagram Feed block with live preview.
4
+ *
5
+ * @since 2.3
6
+ */
7
+ class SB_Instagram_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 2.3
24
+ */
25
+ public function load() {
26
+ $this->hooks();
27
+ }
28
+
29
+ /**
30
+ * Integration hooks.
31
+ *
32
+ * @since 2.3
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 2.3
43
+ */
44
+ public function register_block() {
45
+
46
+ wp_register_style(
47
+ 'sbi-blocks-styles',
48
+ trailingslashit( SBI_PLUGIN_URL ) . 'css/sb-blocks.css',
49
+ array( 'wp-edit-blocks' ),
50
+ SBIVER
51
+ );
52
+
53
+ $attributes = array(
54
+ 'shortcodeSettings' => array(
55
+ 'type' => 'string',
56
+ ),
57
+ 'noNewChanges' => array(
58
+ 'type' => 'boolean',
59
+ )
60
+ );
61
+
62
+ register_block_type(
63
+ 'sbi/sbi-feed-block',
64
+ array(
65
+ 'attributes' => $attributes,
66
+ 'render_callback' => array( $this, 'get_feed_html' ),
67
+ )
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Load Instagram Feed Gutenberg block scripts.
73
+ *
74
+ * @since 2.3
75
+ */
76
+ public function enqueue_block_editor_assets() {
77
+ $db = sbi_get_database_settings();
78
+
79
+ sb_instagram_scripts_enqueue();
80
+
81
+ wp_enqueue_style( 'sbi-blocks-styles' );
82
+ wp_enqueue_script(
83
+ 'sbi-feed-block',
84
+ trailingslashit( SBI_PLUGIN_URL ) . 'js/sb-blocks.js',
85
+ array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
86
+ SBIVER,
87
+ true
88
+ );
89
+
90
+ $shortcodeSettings = '';
91
+
92
+ $i18n = array(
93
+ 'addSettings' => esc_html__( 'Add Settings', 'instagram-feed' ),
94
+ 'shortcodeSettings' => esc_html__( 'Shortcode Settings', 'instagram-feed' ),
95
+ 'example' => esc_html__( 'Example', 'instagram-feed' ),
96
+ 'preview' => esc_html__( 'Apply Changes', 'instagram-feed' ),
97
+
98
+ );
99
+
100
+ wp_localize_script(
101
+ 'sbi-feed-block',
102
+ 'sbi_block_editor',
103
+ array(
104
+ 'wpnonce' => wp_create_nonce( 'sb-instagram-blocks' ),
105
+ 'canShowFeed' => ! empty( $db['connected_accounts'] ),
106
+ 'configureLink' => get_admin_url() . '?page=sb-instagram-feed',
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 2.3
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( '[instagram-feed', ']' ), '', $shortcode_settings );
129
+
130
+ $return .= do_shortcode( '[instagram-feed '.$shortcode_settings.']' );
131
+
132
+ return $return;
133
+
134
+ }
135
+
136
+ /**
137
+ * Checking if is Gutenberg REST API call.
138
+ *
139
+ * @since 2.3
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/admin/class-install-skin.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Sbi\Helpers\PluginSilentUpgraderSkin;
4
+
5
+ /**
6
+ * Skin for on-the-fly addon installations.
7
+ *
8
+ * @since 1.0.0
9
+ * @since 1.5.6.1 Extend PluginSilentUpgraderSkin and clean up the class.
10
+ */
11
+ class Sbi_Install_Skin extends PluginSilentUpgraderSkin {
12
+
13
+ /**
14
+ * Instead of outputting HTML for errors, json_encode the errors and send them
15
+ * back to the Ajax script for processing.
16
+ *
17
+ * @since 1.0.0
18
+ *
19
+ * @param array $errors Array of errors with the install process.
20
+ */
21
+ public function error( $errors ) {
22
+
23
+ if ( ! empty( $errors ) ) {
24
+ wp_send_json_error( $errors );
25
+ }
26
+ }
27
+ }
inc/admin/class-sbi-about.php ADDED
@@ -0,0 +1,1317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * About Sbi admin page class.
5
+ *
6
+ * @since 2.4/5.5
7
+ */
8
+ class SB_Instagram_About {
9
+
10
+ /**
11
+ * Admin menu page slug.
12
+ *
13
+ * @since 2.4/5.5
14
+ *
15
+ * @var string
16
+ */
17
+ const SLUG = 'sb-instagram-feed-about';
18
+
19
+ /**
20
+ * Default view for a page.
21
+ *
22
+ * @since 2.4/5.5
23
+ *
24
+ * @var string
25
+ */
26
+ const DEFAULT_TAB = 'about';
27
+
28
+ /**
29
+ * Array of license types, that are considered being top level and has no features difference.
30
+ *
31
+ * @since 2.4/5.5
32
+ *
33
+ * @var array
34
+ */
35
+ public static $licenses_top = array( 'pro', 'agency', 'ultimate', 'elite' );
36
+
37
+ /**
38
+ * List of features that licenses are different with.
39
+ *
40
+ * @since 2.4/5.5
41
+ *
42
+ * @var array
43
+ */
44
+ public static $licenses_features = array();
45
+
46
+ /**
47
+ * The current active tab.
48
+ *
49
+ * @since 2.4/5.5
50
+ *
51
+ * @var string
52
+ */
53
+ public $view;
54
+
55
+ /**
56
+ * The core views.
57
+ *
58
+ * @since 2.4/5.5
59
+ *
60
+ * @var array
61
+ */
62
+ public $views = array();
63
+
64
+ /**
65
+ * Primary class constructor.
66
+ *
67
+ * @since 2.4/5.5
68
+ */
69
+ public function __construct() {
70
+
71
+ // In old PHP we can't define this elsewhere.
72
+ self::$licenses_features = array(
73
+ 'entries' => esc_html__( 'Feed Types', 'instagram-feed' ),
74
+ 'fields' => esc_html__( 'Layouts', 'instagram-feed' ),
75
+ 'templates' => esc_html__( 'Post Information', 'instagram-feed' ),
76
+ 'conditionals' => esc_html__( 'Image and Video Display', 'instagram-feed' ),
77
+ 'addons' => esc_html__( 'Filtering', 'instagram-feed' ),
78
+ //'marketing' => esc_html__( 'Filtering', 'instagram-feed' ),
79
+ 'marketing' => esc_html__( 'Instagram Stories', 'instagram-feed' ),
80
+ 'payments' => esc_html__( 'Feed Moderation', 'instagram-feed' ),
81
+ 'surveys' => esc_html__( 'Header Display', 'instagram-feed' ),
82
+ 'advanced' => esc_html__( 'Post Linking', 'instagram-feed' ),
83
+ 'support' => esc_html__( 'Customer Support', 'instagram-feed' ),
84
+ );
85
+
86
+ // Maybe load tools page.
87
+ add_action( 'admin_init', array( $this, 'init' ) );
88
+ }
89
+
90
+ /**
91
+ * Determining if the user is viewing the our page, if so, party on.
92
+ *
93
+ * @since 2.4/5.5
94
+ */
95
+ public function init() {
96
+
97
+ // Check what page we are on.
98
+ $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
99
+
100
+ // Only load if we are actually on the settings page.
101
+ if ( self::SLUG !== $page ) {
102
+ return;
103
+ }
104
+
105
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
106
+
107
+ /*
108
+ * Define the core views for the our tab.
109
+ */
110
+ $this->views = apply_filters(
111
+ 'sbi_admin_about_views',
112
+ array(
113
+ esc_html__( 'About Us', 'instagram-feed' ) => array( 'about' ),
114
+ esc_html__( 'Getting Started', 'instagram-feed' ) => array( 'getting-started' ),
115
+ )
116
+ );
117
+
118
+ $license = $this->get_license_type();
119
+
120
+ if (
121
+ (
122
+ $license === 'pro' ||
123
+ ! in_array( $license, self::$licenses_top, true )
124
+ )
125
+ //sbi_debug()
126
+ ) {
127
+ $vs_tab_name = sprintf( /* translators: %1$s - current license type, %2$s - suggested license type. */
128
+ esc_html__( '%1$s vs %2$s', 'instagram-feed' ),
129
+ ucfirst( $license ),
130
+ $this->get_next_license( $license )
131
+ );
132
+
133
+ $this->views[ $vs_tab_name ] = array( 'versus' );
134
+ }
135
+
136
+ // Determine the current active settings tab.
137
+ $this->view = ! empty( $_GET['view'] ) ? esc_html( $_GET['view'] ) : self::DEFAULT_TAB;
138
+
139
+ // If the user tries to load an invalid view - fallback to About Us.
140
+ if (
141
+ ! in_array( $this->view, call_user_func_array( 'array_merge', $this->views ), true ) &&
142
+ ! has_action( 'sbi_admin_about_display_tab_' . sanitize_key( $this->view ) )
143
+ ) {
144
+ $this->view = self::DEFAULT_TAB;
145
+ }
146
+
147
+ add_action( 'sbi_admin_page', array( $this, 'output' ) );
148
+
149
+ // Hook for addons.
150
+ do_action( 'sbi_admin_about_init' );
151
+ }
152
+
153
+ /**
154
+ * Enqueue assets for the the page.
155
+ *
156
+ * @since 2.4/5.5
157
+ */
158
+ public function enqueues() {
159
+
160
+ wp_enqueue_script(
161
+ 'jquery-matchheight',
162
+ SBI_PLUGIN_URL . 'js/jquery.matchHeight-min.js',
163
+ array( 'jquery' ),
164
+ '0.7.0',
165
+ false
166
+ );
167
+ }
168
+
169
+ /**
170
+ * Output the basic page structure.
171
+ *
172
+ * @since 2.4/5.5
173
+ */
174
+ public function output() {
175
+
176
+ $show_nav = false;
177
+ foreach ( $this->views as $view ) {
178
+ if ( in_array( $this->view, (array) $view, true ) ) {
179
+ $show_nav = true;
180
+ break;
181
+ }
182
+ }
183
+ ?>
184
+
185
+ <div id="sbi-admin-about" class="wrap sbi-admin-wrap">
186
+
187
+ <?php
188
+ if ( $show_nav ) {
189
+ $license = $this->get_license_type();
190
+ $next_license = $this->get_next_license( $license );
191
+ echo '<ul class="sbi-admin-tabs">';
192
+ foreach ( $this->views as $label => $view ) {
193
+ $class = in_array( $this->view, $view, true ) ? 'active' : '';
194
+ echo '<li>';
195
+ printf(
196
+ '<a href="%s" class="%s">%s</a>',
197
+ esc_url( admin_url( 'admin.php?page=' . self::SLUG . '&view=' . sanitize_key( $view[0] ) ) ),
198
+ esc_attr( $class ),
199
+ esc_html( $label )
200
+ );
201
+ echo '</li>';
202
+ }
203
+ echo '</ul>';
204
+ }
205
+ ?>
206
+
207
+ <h1 class="sbi-h1-placeholder"></h1>
208
+
209
+ <?php
210
+ switch ( $this->view ) {
211
+ case 'about':
212
+ $this->output_about();
213
+ break;
214
+ case 'getting-started':
215
+ $this->output_getting_started();
216
+ break;
217
+ case 'versus':
218
+ $this->output_versus();
219
+ break;
220
+ default:
221
+ do_action( 'sbi_admin_about_display_tab_' . sanitize_key( $this->view ) );
222
+ break;
223
+ }
224
+ ?>
225
+
226
+ </div>
227
+
228
+ <?php
229
+ }
230
+
231
+ /**
232
+ * Display the About tab content.
233
+ *
234
+ * @since 2.4/5.5
235
+ */
236
+ protected function output_about() {
237
+
238
+ $this->output_about_info();
239
+ $this->output_about_addons();
240
+ }
241
+
242
+ /**
243
+ * Display the General Info section of About tab.
244
+ *
245
+ * @since 1.5.8
246
+ */
247
+ protected function output_about_info() {
248
+
249
+ ?>
250
+
251
+ <div class="sbi-admin-about-section sbi-admin-columns">
252
+
253
+ <div class="sbi-admin-about-text" style="min-height: 340px;">
254
+ <h3>
255
+ <?php esc_html_e( 'Hello and welcome to the Instagram Feed plugin, the most beautiful, clean, and reliable Instagram feed plugin in the world. At Smash Balloon, we build software that helps you create beautiful responsive social media feeds for your website in minutes.', 'instagram-feed' ); ?>
256
+ </h3>
257
+
258
+ <p>
259
+ <?php esc_html_e( 'Smash Balloon is a fun-loving WordPress plugin development company birthed into existence in early 2013. We specialize in creating plugins that are not only intuitive and simple to use, but also designed to integrate seamlessly into your website and allow you to display your social media content in powerful and unique ways. Over 1 million awesome people have decided to actively use our plugins, which is an incredible honor that we don’t take lightly. This compels us to try to provide the quickest and most effective customer support that we can, blowing users away with the best customer service they’ve ever experienced.', 'instagram-feed' ); ?>
260
+ </p>
261
+ <p>
262
+ <?php esc_html_e( 'We’re a small, but dedicated, team based in Minnesota in the USA.', 'instagram-feed' ); ?>
263
+ </p>
264
+ <!-- <p>
265
+ <?php
266
+ printf(
267
+ wp_kses(
268
+ /* translators: %1$s - WPBeginner URL, %2$s - OptinMonster URL, %3$s - MonsterInsights URL, %4$s - RafflePress URL. */
269
+ __( 'Instagram Feed is brought to you by the same team that’s behind the largest WordPress resource site, <a href="%1$s" target="_blank" rel="noopener noreferrer">WPBeginner</a>, the most popular lead-generation software, <a href="%2$s" target="_blank" rel="noopener noreferrer">OptinMonster</a>, the best WordPress analytics plugin, <a href="%3$s" target="_blank" rel="noopener noreferrer">MonsterInsights</a>, and the most powerful WordPress contest plugin, <a href="%4$s" target="_blank" rel="noopener noreferrer">RafflePress</a>.', 'instagram-feed' ),
270
+ array(
271
+ 'a' => array(
272
+ 'href' => array(),
273
+ 'rel' => array(),
274
+ 'target' => array(),
275
+ ),
276
+ )
277
+ ),
278
+ 'https://www.wpbeginner.com/?utm_source=sbiplugin&utm_medium=pluginaboutpage&utm_campaign=aboutsbi',
279
+ 'https://optinmonster.com/?utm_source=sbiplugin&utm_medium=pluginaboutpage&utm_campaign=aboutsbi',
280
+ 'https://www.monsterinsights.com/?utm_source=sbiplugin&utm_medium=pluginaboutpage&utm_campaign=aboutsbi',
281
+ 'https://rafflepress.com/?utm_source=sbiplugin&utm_medium=pluginaboutpage&utm_campaign=aboutsbi'
282
+ );
283
+ ?>
284
+ </p>
285
+ <p>
286
+ <?php esc_html_e( 'Yup, we know a thing or two about building awesome products that customers love.', 'instagram-feed' ); ?>
287
+ </p> -->
288
+ </div>
289
+
290
+ <div class="sbi-admin-about-image sbi-admin-column-last">
291
+ <figure>
292
+ <img src="<?php echo SBI_PLUGIN_URL; ?>img/about/team.jpg" alt="<?php esc_attr_e( 'The Sbi Team photo', 'instagram-feed' ); ?>">
293
+ <figcaption>
294
+ <?php esc_html_e( 'The Smash Balloon Team', 'instagram-feed' ); ?><br>
295
+ </figcaption>
296
+ </figure>
297
+ </div>
298
+
299
+ </div>
300
+ <?php
301
+ }
302
+
303
+ /**
304
+ * Display the Addons section of About tab.
305
+ *
306
+ * @since 1.5.8
307
+ */
308
+ protected function output_about_addons() {
309
+
310
+ if ( ! current_user_can( 'manage_instagram_feed_options' ) || version_compare( PHP_VERSION, '5.3.0' ) <= 0 ) {
311
+ return;
312
+ }
313
+
314
+ $all_plugins = get_plugins();
315
+ $am_plugins = $this->get_am_plugins();
316
+
317
+ ?>
318
+ <div id="sbi-admin-addons">
319
+ <div class="addons-container">
320
+ <h3><?php echo __( 'Our Other Plugins', 'instagram-feed' ); ?></h3>
321
+ <?php
322
+ foreach ( $am_plugins as $plugin => $details ) :
323
+
324
+ $plugin_data = $this->get_plugin_data( $plugin, $details, $all_plugins );
325
+
326
+ if ( $plugin === 'wpforms-lite/wpforms.php' ) {
327
+ echo '<h3>' .__( 'Plugins We Recommend', 'instagram-feed' ). '</h3>';
328
+ }
329
+
330
+ ?>
331
+ <div class="addon-container">
332
+ <div class="addon-item">
333
+ <div class="details sbi-clear">
334
+ <img src="<?php echo esc_url( $plugin_data['details']['icon'] ); ?>">
335
+ <h5 class="addon-name">
336
+ <?php echo esc_html( $plugin_data['details']['name'] ); ?>
337
+ </h5>
338
+ <p class="addon-desc">
339
+ <?php echo wp_kses_post( $plugin_data['details']['desc'] ); ?>
340
+ </p>
341
+ </div>
342
+ <div class="actions sbi-clear">
343
+ <div class="status">
344
+ <strong>
345
+ <?php
346
+ printf(
347
+ /* translators: %s - addon status label. */
348
+ esc_html__( 'Status: %s', 'instagram-feed' ),
349
+ '<span class="status-label ' . esc_attr( $plugin_data['status_class'] ) . '">' . wp_kses_post( $plugin_data['status_text'] ) . '</span>'
350
+ );
351
+ ?>
352
+ </strong>
353
+ </div>
354
+ <div class="action-button">
355
+ <button class="<?php echo esc_attr( $plugin_data['action_class'] ); ?>" data-plugin="<?php echo esc_attr( $plugin_data['plugin_src'] ); ?>" data-type="plugin">
356
+ <?php echo wp_kses_post( $plugin_data['action_text'] ); ?>
357
+ </button>
358
+ </div>
359
+ </div>
360
+ </div>
361
+ </div>
362
+ <?php endforeach; ?>
363
+ </div>
364
+ </div>
365
+ <?php
366
+ }
367
+
368
+ /**
369
+ * Get AM plugin data to display in the Addons section of About tab.
370
+ *
371
+ * @since 1.5.8
372
+ *
373
+ * @param string $plugin Plugin slug.
374
+ * @param array $details Plugin details.
375
+ * @param array $all_plugins List of all plugins.
376
+ *
377
+ * @return array
378
+ */
379
+ protected function get_plugin_data( $plugin, $details, $all_plugins ) {
380
+
381
+ $have_pro = ( ! empty( $details['pro'] ) && ! empty( $details['pro']['plug'] ) );
382
+ $show_pro = false;
383
+
384
+ $plugin_data = array();
385
+
386
+ if ( $have_pro ) {
387
+ if ( array_key_exists( $plugin, $all_plugins ) ) {
388
+ if ( is_plugin_active( $plugin ) ) {
389
+ $show_pro = true;
390
+ }
391
+ }
392
+ if ( array_key_exists( $details['pro']['plug'], $all_plugins ) ) {
393
+ $show_pro = true;
394
+ }
395
+ if ( $show_pro ) {
396
+ $plugin = $details['pro']['plug'];
397
+ $details = $details['pro'];
398
+ }
399
+ }
400
+
401
+ if ( array_key_exists( $plugin, $all_plugins ) ) {
402
+ if ( is_plugin_active( $plugin ) ) {
403
+ // Status text/status.
404
+ $plugin_data['status_class'] = 'status-active';
405
+ $plugin_data['status_text'] = esc_html__( 'Active', 'instagram-feed' );
406
+ // Button text/status.
407
+ $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary disabled';
408
+ $plugin_data['action_text'] = esc_html__( 'Activated', 'instagram-feed' );
409
+ $plugin_data['plugin_src'] = esc_attr( $plugin );
410
+ } else {
411
+ // Status text/status.
412
+ $plugin_data['status_class'] = 'status-inactive';
413
+ $plugin_data['status_text'] = esc_html__( 'Inactive', 'instagram-feed' );
414
+ // Button text/status.
415
+ $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary';
416
+ $plugin_data['action_text'] = esc_html__( 'Activate', 'instagram-feed' );
417
+ $plugin_data['plugin_src'] = esc_attr( $plugin );
418
+ }
419
+ } else {
420
+ // Doesn't exist, install.
421
+ // Status text/status.
422
+ $plugin_data['status_class'] = 'status-download';
423
+ if ( isset( $details['act'] ) && 'go-to-url' === $details['act'] ) {
424
+ $plugin_data['status_class'] = 'status-go-to-url';
425
+ }
426
+ $plugin_data['status_text'] = esc_html__( 'Not Installed', 'instagram-feed' );
427
+ // Button text/status.
428
+ $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-primary';
429
+ $plugin_data['action_text'] = esc_html__( 'Install Plugin', 'instagram-feed' );
430
+ $plugin_data['plugin_src'] = esc_url( $details['url'] );
431
+ }
432
+
433
+ $plugin_data['details'] = $details;
434
+
435
+ return $plugin_data;
436
+ }
437
+
438
+ /**
439
+ * Display the Getting Started tab content.
440
+ *
441
+ * @since 2.4/5.5
442
+ */
443
+ protected function output_getting_started() {
444
+
445
+ $license = $this->get_license_type();
446
+ ?>
447
+
448
+ <div class="sbi-admin-about-section sbi-admin-about-section-first-form" style="display:flex;">
449
+
450
+ <div class="sbi-admin-about-section-first-form-text">
451
+
452
+ <h2>
453
+ <?php esc_html_e( 'Creating Your First Feed', 'instagram-feed' ); ?>
454
+ </h2>
455
+
456
+ <p>
457
+ <?php esc_html_e( 'Want to get started creating your first feed with Instagram Feed? By following the step by step instructions in this walkthrough, you can easily publish your first feed on your site.', 'instagram-feed' ); ?>
458
+ </p>
459
+
460
+ <p>
461
+ <?php esc_html_e( 'Navigate to Instagram Feed in the admin sidebar to go the Configure page.', 'instagram-feed' ); ?>
462
+ </p>
463
+
464
+ <p>
465
+ <?php esc_html_e( 'Click on the large blue button to connect your Instagram account. Select "Personal" if your Instagram account is a personal account, "Business" if it is a business or creator account.', 'instagram-feed' ); ?>
466
+ </p>
467
+
468
+ <p>
469
+ <?php esc_html_e( 'Once you connect an Instagram account, you can display your feed on any post, page or widget using the shortcode [instagram-feed]. You can also use the Instagram Feed Gutenberg block if your site has the WordPress block editor enabled.', 'instagram-feed' ); ?>
470
+ </p>
471
+
472
+ <ul class="list-plain">
473
+ <li>
474
+ <a href="https://smashballoon.com/display-multiple-instagram-feeds/?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted#multiple-feeds" target="_blank" rel="noopener noreferrer">
475
+ <?php esc_html_e( 'How to Display Multiple Feeds', 'instagram-feed' ); ?>
476
+ </a>
477
+ </li>
478
+ <li>
479
+ <a href="https://smashballoon.com/get-access-token-from-another-account/?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted#differentaccount" target="_blank" rel="noopener noreferrer">
480
+ <?php esc_html_e( 'Connect a Different Account', 'instagram-feed' ); ?>
481
+ </a>
482
+ </li>
483
+ <li>
484
+ <a href="https://smashballoon.com/differences-between-an-instagram-personal-and-business-account/?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted#display-form" target="_blank" rel="noopener noreferrer">
485
+ <?php esc_html_e( 'Personal Vs Business Accounts', 'instagram-feed' ); ?>
486
+ </a>
487
+ </li>
488
+ </ul>
489
+
490
+ </div>
491
+
492
+ <div class="sbi-admin-about-section-first-form-video">
493
+ <iframe src="https://www.youtube-nocookie.com/embed/q6ZXVU4g970?rel=0" width="540" height="304" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
494
+ </div>
495
+
496
+ </div>
497
+
498
+ <?php if ( ! in_array( $license, self::$licenses_top, true ) ) { ?>
499
+ <div class="sbi-admin-about-section sbi-admin-about-section-hero">
500
+
501
+ <div class="sbi-admin-about-section-hero-main">
502
+ <h2>
503
+ <?php esc_html_e( 'Get Instagram Feed Pro and Unlock all the Powerful Features', 'instagram-feed' ); ?>
504
+ </h2>
505
+
506
+ <p class="bigger">
507
+ <?php
508
+ echo wp_kses(
509
+ __( 'Thanks for being a loyal Instagram Feed Lite user. <strong>Upgrade to Instagram Feed Pro</strong> to unlock all the awesome features and experience<br>why Instagram Feed is the most popular Instagram plugin.', 'instagram-feed' ),
510
+ array(
511
+ 'br' => array(),
512
+ 'strong' => array(),
513
+ )
514
+ );
515
+ ?>
516
+ </p>
517
+
518
+ <p>
519
+ <?php
520
+ printf(
521
+ wp_kses(
522
+ /* translators: %s - stars. */
523
+ __( 'We know that you will truly love Instagram Feed. It has over <strong>2500+ five star ratings</strong> (%s) and is active on over 1 million websites.', 'instagram-feed' ),
524
+ array(
525
+ 'strong' => array(),
526
+ )
527
+ ),
528
+ '<i class="fa fa-star" aria-hidden="true"></i>' .
529
+ '<i class="fa fa-star" aria-hidden="true"></i>' .
530
+ '<i class="fa fa-star" aria-hidden="true"></i>' .
531
+ '<i class="fa fa-star" aria-hidden="true"></i>' .
532
+ '<i class="fa fa-star" aria-hidden="true"></i>'
533
+ );
534
+ ?>
535
+ </p>
536
+ </div>
537
+
538
+ <div class="sbi-admin-about-section-hero-extra">
539
+ <div class="sbi-admin-columns">
540
+ <div class="sbi-admin-column-50">
541
+ <ul class="list-features list-plain">
542
+ <li>
543
+ <i class="fa fa-check" aria-hidden="true"></i>
544
+ <?php esc_html_e( 'Recent hashtag, top Hashtag, and tagged feeds.', 'instagram-feed' ); ?>
545
+ </li>
546
+ <li>
547
+ <i class="fa fa-check" aria-hidden="true"></i>
548
+ <?php esc_html_e( 'More layouts - masonry, highlight, and carousel.', 'instagram-feed' ); ?>
549
+ </li>
550
+ <li>
551
+ <i class="fa fa-check" aria-hidden="true"></i>
552
+ <?php esc_html_e( 'Captions, comments, dates, likes, and comment counts.', 'instagram-feed' ); ?>
553
+ </li>
554
+ <li>
555
+ <i class="fa fa-check" aria-hidden="true"></i>
556
+ <?php esc_html_e( 'Pop-up lightbox to view images and watch videos.', 'instagram-feed' ); ?>
557
+ </li>
558
+ <li>
559
+ <i class="fa fa-check" aria-hidden="true"></i>
560
+ <?php esc_html_e( 'Filter feeds by word or hashtag.', 'instagram-feed' ); ?>
561
+ </li>
562
+ </ul>
563
+ </div>
564
+ <div class="sbi-admin-column-50 sbi-admin-column-last">
565
+ <ul class="list-features list-plain">
566
+ <li>
567
+ <i class="fa fa-check" aria-hidden="true"></i>
568
+ <?php esc_html_e( 'Display Instagram stories.', 'instagram-feed' ); ?>
569
+ </li>
570
+ <li>
571
+ <i class="fa fa-check" aria-hidden="true"></i>
572
+ <?php esc_html_e( 'Powerful visual moderation system.', 'instagram-feed' ); ?>
573
+ </li>
574
+ <li>
575
+ <i class="fa fa-check" aria-hidden="true"></i>
576
+ <?php esc_html_e( 'More customization for feed headers.', 'instagram-feed' ); ?>
577
+ </li>
578
+ <li>
579
+ <i class="fa fa-check" aria-hidden="true"></i>
580
+ <?php esc_html_e( 'Even more customization options for your feed.', 'instagram-feed' ); ?>
581
+ </li>
582
+ <li>
583
+ <i class="fa fa-check" aria-hidden="true"></i>
584
+ <?php esc_html_e( '"Shoppable" feeds.', 'instagram-feed' ); ?>
585
+ </li>
586
+ </ul>
587
+ </div>
588
+ </div>
589
+
590
+ <hr />
591
+
592
+ <h3 class="call-to-action">
593
+ <?php
594
+ if ( 'lite' === $license ) {
595
+ echo '<a href="https://smashballoon.com/instagram-feed/pricing?utm_source=plugin-free&utm_campaign=sbi" target="_blank" rel="noopener noreferrer">';
596
+ } else {
597
+ echo '<a href="https://smashballoon.com/instagram-feed/pricing?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer">';
598
+ }
599
+ esc_html_e( 'Get Instagram Feed Pro Today and Unlock all the Powerful Features', 'instagram-feed' );
600
+ ?>
601
+ </a>
602
+ </h3>
603
+
604
+ <?php if ( 'lite' === $license ) { ?>
605
+ <p>
606
+ <?php
607
+ echo wp_kses(
608
+ __( 'Bonus: Instagram Feed Lite users get <span class="price-20-off">50% off regular price</span>, automatically applied at checkout.', 'instagram-feed' ),
609
+ array(
610
+ 'span' => array(
611
+ 'class' => array(),
612
+ ),
613
+ )
614
+ );
615
+ ?>
616
+ </p>
617
+ <?php } ?>
618
+ </div>
619
+
620
+ </div>
621
+ <?php } ?>
622
+
623
+
624
+ <div class="sbi-admin-about-section sbi-admin-about-section-squashed sbi-admin-about-section-post sbi-admin-columns">
625
+ <div class="sbi-admin-column-20">
626
+ <img src="<?php echo SBI_PLUGIN_URL; ?>img/about/steps.png" alt="">
627
+ </div>
628
+ <div class="sbi-admin-column-80">
629
+ <h2>
630
+ <?php esc_html_e( 'Detailed Step-By-Step Guide', 'instagram-feed' ); ?>
631
+ </h2>
632
+
633
+ <p>
634
+ <?php esc_html_e( 'View detailed steps with related images on our website. We have a comprehensive guide to getting up and running with Instagram Feed.', 'instagram-feed' ); ?>
635
+ </p>
636
+
637
+ <a href="https://smashballoon.com/instagram-feed/free/?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="sbi-admin-about-section-post-link">
638
+ <?php esc_html_e( 'Read Documentation', 'instagram-feed' ); ?><i class="fa fa-external-link" aria-hidden="true"></i>
639
+ </a>
640
+ </div>
641
+ </div>
642
+
643
+ <div class="sbi-admin-about-section sbi-admin-about-section-squashed sbi-admin-about-section-post sbi-admin-columns">
644
+ <div class="sbi-admin-column-20">
645
+ <img src="<?php echo SBI_PLUGIN_URL; ?>img/about/api-error.png" alt="">
646
+ </div>
647
+ <div class="sbi-admin-column-80">
648
+ <h2>
649
+ <?php esc_html_e( 'Troubleshoot Connection and API Errors', 'instagram-feed' ); ?>
650
+ </h2>
651
+
652
+ <p>
653
+ <?php esc_html_e( 'Are you having trouble displaying your feed due to an error connecting an account or an Instagram API error? We have several articles to help you troubleshoot issues and help you solve them.', 'instagram-feed' ); ?>
654
+ </p>
655
+
656
+ <a href="https://smashballoon.com/instagram-feed/docs/errors/?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="sbi-admin-about-section-post-link">
657
+ <?php esc_html_e( 'Read Documentation', 'instagram-feed' ); ?><i class="fa fa-external-link" aria-hidden="true"></i>
658
+ </a>
659
+ </div>
660
+ </div>
661
+
662
+ <?php
663
+ }
664
+
665
+ /**
666
+ * Get the next license type. Helper for Versus tab content.
667
+ *
668
+ * @since 1.5.5
669
+ *
670
+ * @param string $current Current license type slug.
671
+ *
672
+ * @return string Next license type slug.
673
+ */
674
+ protected function get_next_license( $current ) {
675
+
676
+ $current = ucfirst( $current );
677
+ $license_pairs = array(
678
+ 'Lite' => 'Pro',
679
+ 'Basic' => 'Pro',
680
+ 'Plus' => 'Pro',
681
+ 'Pro' => 'Elite',
682
+ );
683
+
684
+ return ! empty( $license_pairs[ $current ] ) ? $license_pairs[ $current ] : 'Elite';
685
+ }
686
+
687
+ /**
688
+ * Display the Versus tab content.
689
+ *
690
+ * @since 2.4/5.5
691
+ */
692
+ protected function output_versus() {
693
+
694
+ //$license = $this->get_license_type();
695
+ //$next_license = $this->get_next_license( $license );
696
+ $license = 'lite';
697
+ $next_license = 'pro';
698
+ ?>
699
+
700
+ <div class="sbi-admin-about-section sbi-admin-about-section-squashed">
701
+ <h1 class="centered">
702
+ <strong><?php echo esc_html( ucfirst( $license ) ); ?></strong> vs <strong><?php echo esc_html( ucfirst( $next_license ) ); ?></strong>
703
+ </h1>
704
+
705
+ <p class="centered">
706
+ <?php esc_html_e( 'Get the most out of your Instagram Feeds by upgrading to Pro and unlocking all of the powerful features.', 'instagram-feed' ); ?>
707
+ </p>
708
+ </div>
709
+
710
+ <div class="sbi-admin-about-section sbi-admin-about-section-squashed sbi-admin-about-section-hero sbi-admin-about-section-table">
711
+
712
+ <div class="sbi-admin-about-section-hero-main sbi-admin-columns">
713
+ <div class="sbi-admin-column-33">
714
+ <h3 class="no-margin">
715
+ <?php esc_html_e( 'Feature', 'instagram-feed' ); ?>
716
+ </h3>
717
+ </div>
718
+ <div class="sbi-admin-column-33">
719
+ <h3 class="no-margin">
720
+ <?php echo esc_html( ucfirst( $license ) ); ?>
721
+ </h3>
722
+ </div>
723
+ <div class="sbi-admin-column-33">
724
+ <h3 class="no-margin">
725
+ <?php echo esc_html( ucfirst( $next_license ) ); ?>
726
+ </h3>
727
+ </div>
728
+ </div>
729
+ <div class="sbi-admin-about-section-hero-extra no-padding sbi-admin-columns">
730
+
731
+ <table>
732
+ <?php
733
+ foreach ( self::$licenses_features as $slug => $name ) {
734
+ $current = $this->get_license_data( $slug, $license );
735
+ $next = $this->get_license_data( $slug, strtolower( $next_license ) );
736
+
737
+ if ( empty( $current ) || empty( $next ) ) {
738
+ continue;
739
+ }
740
+ ?>
741
+ <tr class="sbi-admin-columns">
742
+ <td class="sbi-admin-column-33">
743
+ <p><?php echo esc_html( $name ); ?></p>
744
+ </td>
745
+ <td class="sbi-admin-column-33">
746
+ <?php if ( is_array( $current ) ) : ?>
747
+ <p class="features-<?php echo esc_attr( $current['status'] ); ?>">
748
+ <?php echo wp_kses_post( implode( '<br>', $current['text'] ) ); ?>
749
+ </p>
750
+ <?php endif; ?>
751
+ </td>
752
+ <td class="sbi-admin-column-33">
753
+ <?php if ( is_array( $current ) ) : ?>
754
+ <p class="features-full">
755
+ <?php echo wp_kses_post( implode( '<br>', $next['text'] ) ); ?>
756
+ </p>
757
+ <?php endif; ?>
758
+ </td>
759
+ </tr>
760
+ <?php
761
+ }
762
+ ?>
763
+ </table>
764
+
765
+ </div>
766
+
767
+ </div>
768
+
769
+ <div class="sbi-admin-about-section sbi-admin-about-section-hero">
770
+ <div class="sbi-admin-about-section-hero-main no-border">
771
+ <h3 class="call-to-action centered">
772
+ <?php
773
+ if ( 'lite' === $license ) {
774
+ echo '<a href="https://smashballoon.com/instagram-feed/pricing?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer">';
775
+ } else {
776
+ echo '<a href="https://smashballoon.com/instagram-feed/pricing?utm_source=WordPress&utm_medium=sbi-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer">';
777
+ }
778
+ printf( /* translators: %s - next license level. */
779
+ esc_html__( 'Get Instagram Feed Pro Today and Unlock all the Powerful Features', 'instagram-feed' ),
780
+ esc_html( $next_license )
781
+ );
782
+ ?>
783
+ </a>
784
+ </h3>
785
+
786
+ <?php if ( 'lite' === $license ) { ?>
787
+ <p class="centered">
788
+ <?php
789
+ echo wp_kses(
790
+ __( 'Bonus: Instagram Feed Lite users get <span class="price-20-off">50% off regular price</span>, automatically applied at checkout.', 'instagram-feed' ),
791
+ array(
792
+ 'span' => array(
793
+ 'class' => array(),
794
+ ),
795
+ )
796
+ );
797
+ ?>
798
+ </p>
799
+ <?php } ?>
800
+ </div>
801
+ </div>
802
+
803
+ <?php
804
+ }
805
+
806
+ /**
807
+ * List of AM plugins that we propose to install.
808
+ *
809
+ * @since 2.4/5.5
810
+ *
811
+ * @return array
812
+ */
813
+ protected function get_am_plugins() {
814
+
815
+ $images_url = SBI_PLUGIN_URL . 'img/about/';
816
+
817
+ return array(
818
+ 'custom-facebook-feed/custom-facebook-feed.php' => array(
819
+ 'icon' => $images_url . 'plugin-fb.png',
820
+ 'name' => esc_html__( 'Custom Facebook Feed', 'instagram-feed' ),
821
+ 'desc' => esc_html__( 'Custom Facebook Feed makes displaying your Facebook posts easy. Keep your site visitors informed and increase engagement with your Facebook page by displaying a feed on your website.', 'instagram-feed' ),
822
+ 'url' => 'https://downloads.wordpress.org/plugin/custom-facebook-feed.zip',
823
+ 'pro' => array(
824
+ 'plug' => 'custom-facebook-feed-pro/custom-facebook-feed.php',
825
+ 'icon' => $images_url . 'plugin-fb.png',
826
+ 'name' => esc_html__( 'Custom Facebook Feed Pro', 'instagram-feed' ),
827
+ 'desc' => esc_html__( 'Custom Facebook Feed makes displaying your Facebook posts easy. Keep your site visitors informed and increase engagement with your Facebook page by displaying a feed on your website.', 'instagram-feed' ),
828
+ 'url' => 'https://smashballoon.com/custom-facebook-feed/?utm_source=WordPress&utm_campaign=facebookliteplugin',
829
+ 'act' => 'go-to-url',
830
+ ),
831
+ ),
832
+
833
+ 'custom-twitter-feeds/custom-twitter-feed.php' => array(
834
+ 'icon' => $images_url . 'plugin-tw.jpg',
835
+ 'name' => esc_html__( 'Custom Twitter Feeds', 'instagram-feed' ),
836
+ 'desc' => esc_html__( 'Custom Twitter Feeds is a highly customizable way to display tweets from your Twitter account. Promote your latest content and update your site content automatically.', 'instagram-feed' ),
837
+ 'url' => 'https://downloads.wordpress.org/plugin/custom-twitter-feeds.zip',
838
+ 'pro' => array(
839
+ 'plug' => 'custom-twitter-feeds-pro/custom-twitter-feed.php',
840
+ 'icon' => $images_url . 'plugin-tw.jpg',
841
+ 'name' => esc_html__( 'Custom Twitter Feeds Pro', 'instagram-feed' ),
842
+ 'desc' => esc_html__( 'Custom Twitter Feeds is a highly customizable way to display tweets from your Twitter account. Promote your latest content and update your site content automatically.', 'instagram-feed' ),
843
+ 'url' => 'https://smashballoon.com/custom-twitter-feeds/?utm_source=plugin-free&utm_campaign=ctf',
844
+ 'act' => 'go-to-url',
845
+ ),
846
+ ),
847
+
848
+ 'feeds-for-youtube/youtube-feed.php' => array(
849
+ 'icon' => $images_url . 'plugin-yt.png',
850
+ 'name' => esc_html__( 'Feeds for YouTube', 'instagram-feed' ),
851
+ 'desc' => esc_html__( 'Feeds for YouTube is a simple yet powerful way to display videos from YouTube on your website. Increase engagement with your channel while keeping visitors on your website.', 'instagram-feed' ),
852
+ 'url' => 'https://downloads.wordpress.org/plugin/feeds-for-youtube.zip',
853
+ 'pro' => array(
854
+ 'plug' => 'youtube-feed-pro/youtube-feed.php',
855
+ 'icon' => $images_url . 'plugin-yt.png',
856
+ 'name' => esc_html__( 'Feeds for YouTube Pro', 'instagram-feed' ),
857
+ 'desc' => esc_html__( 'Feeds for YouTube is a simple yet powerful way to display videos from YouTube on your website. Increase engagement with your channel while keeping visitors on your website.', 'instagram-feed' ),
858
+ 'url' => 'https://smashballoon.com/youtube-feed/?utm_source=plugin-free&utm_campaign=sby',
859
+ 'act' => 'go-to-url',
860
+ ),
861
+ ),
862
+
863
+ 'wpforms-lite/wpforms.php' => array(
864
+ 'icon' => $images_url . 'plugin-wpforms.png',
865
+ 'name' => esc_html__( 'WPForms', 'instagram-feed' ),
866
+ 'desc' => esc_html__( 'The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!', 'instagram-feed' ),
867
+ 'url' => 'https://downloads.wordpress.org/plugin/wpforms-lite.zip',
868
+ 'pro' => array(
869
+ 'plug' => 'wpforms/wpforms.php',
870
+ 'icon' => $images_url . 'plugin-wpforms.png',
871
+ 'name' => esc_html__( 'WPForms', 'instagram-feed' ),
872
+ 'desc' => esc_html__( 'The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!', 'instagram-feed' ),
873
+ 'url' => 'https://wpforms.com/lite-upgrade/?utm_source=WordPress&utm_campaign=liteplugin&utm_medium=sbi-about-page',
874
+ 'act' => 'go-to-url',
875
+ ),
876
+ ),
877
+
878
+ 'google-analytics-for-wordpress/googleanalytics.php' => array(
879
+ 'icon' => $images_url . 'plugin-mi.png',
880
+ 'name' => esc_html__( 'MonsterInsights', 'instagram-feed' ),
881
+ 'desc' => esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'instagram-feed' ),
882
+ 'url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip',
883
+ 'pro' => array(
884
+ 'plug' => 'google-analytics-premium/googleanalytics-premium.php',
885
+ 'icon' => $images_url . 'plugin-mi.png',
886
+ 'name' => esc_html__( 'MonsterInsights Pro', 'instagram-feed' ),
887
+ 'desc' => esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'instagram-feed' ),
888
+ 'url' => 'https://www.monsterinsights.com/?utm_source=proplugin&utm_medium=sbi-about-page&utm_campaign=pluginurl&utm_content=7%2E0%2E0',
889
+ 'act' => 'go-to-url',
890
+ ),
891
+ ),
892
+
893
+ 'optinmonster/optin-monster-wp-api.php' => array(
894
+ 'icon' => $images_url . 'plugin-om.png',
895
+ 'name' => esc_html__( 'OptinMonster', 'instagram-feed' ),
896
+ 'desc' => esc_html__( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'instagram-feed' ),
897
+ 'url' => 'https://downloads.wordpress.org/plugin/optinmonster.zip',
898
+ ),
899
+
900
+ 'wp-mail-smtp/wp_mail_smtp.php' => array(
901
+ 'icon' => $images_url . 'plugin-smtp.png',
902
+ 'name' => esc_html__( 'WP Mail SMTP', 'instagram-feed' ),
903
+ 'desc' => esc_html__( 'Make sure your website\'s emails reach the inbox. Our goal is to make email deliverability easy and reliable. Trusted by over 1 million websites.', 'instagram-feed' ),
904
+ 'url' => 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip',
905
+ 'pro' => array(
906
+ 'plug' => 'wp-mail-smtp-pro/wp_mail_smtp.php',
907
+ 'icon' => $images_url . 'plugin-smtp.png',
908
+ 'name' => esc_html__( 'WP Mail SMTP Pro', 'instagram-feed' ),
909
+ 'desc' => esc_html__( 'Make sure your website\'s emails reach the inbox. Our goal is to make email deliverability easy and reliable. Trusted by over 1 million websites.', 'instagram-feed' ),
910
+ 'url' => 'https://wpmailsmtp.com/pricing/',
911
+ 'act' => 'go-to-url',
912
+ ),
913
+ ),
914
+
915
+ 'rafflepress/rafflepress.php' => array(
916
+ 'icon' => $images_url . 'plugin-rp.png',
917
+ 'name' => esc_html__( 'RafflePress', 'instagram-feed' ),
918
+ 'desc' => esc_html__( 'Turn your visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with powerful viral giveaways & contests.', 'instagram-feed' ),
919
+ 'url' => 'https://downloads.wordpress.org/plugin/rafflepress.zip',
920
+ 'pro' => array(
921
+ 'plug' => 'rafflepress-pro/rafflepress-pro.php',
922
+ 'icon' => $images_url . 'plugin-rp.png',
923
+ 'name' => esc_html__( 'RafflePress Pro', 'instagram-feed' ),
924
+ 'desc' => esc_html__( 'Turn your visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with powerful viral giveaways & contests.', 'instagram-feed' ),
925
+ 'url' => 'https://rafflepress.com/pricing/',
926
+ 'act' => 'go-to-url',
927
+ ),
928
+ ),
929
+
930
+ 'all-in-one-seo-pack/all_in_one_seo_pack.php' => array(
931
+ 'icon' => $images_url . 'plugin-seo.png',
932
+ 'name' => esc_html__( 'All In One SEO Pack', 'instagram-feed' ),
933
+ 'desc' => esc_html__( 'Out-of-the-box SEO for WordPress. Features like XML Sitemaps, SEO for custom post types, SEO for blogs or business sites, SEO for ecommerce sites, and much more. More than 50 million downloads since 2007.', 'instagram-feed' ),
934
+ 'url' => 'https://downloads.wordpress.org/plugin/all-in-one-seo-pack.zip',
935
+ ),
936
+ );
937
+ }
938
+
939
+ /**
940
+ * Get the array of data that compared the license data.
941
+ *
942
+ * @since 2.4/5.5
943
+ *
944
+ * @param string $feature Feature name.
945
+ * @param string $license License type to get data for.
946
+ *
947
+ * @return array|false
948
+ */
949
+ protected function get_license_data( $feature, $license ) {
950
+
951
+ $data = array(
952
+ 'entries' => array(
953
+ 'lite' => array(
954
+ 'status' => 'partial',
955
+ 'text' => array(
956
+ '<strong>' . esc_html__( 'User feeds only', 'instagram-feed' ) . '</strong>',
957
+ ),
958
+ ),
959
+ 'basic' => array(
960
+ 'status' => 'full',
961
+ 'text' => array(
962
+ '<strong>' . esc_html__( 'User, Hashtag, and Tagged Feeds', 'instagram-feed' ) . '</strong>',
963
+ ),
964
+ ),
965
+ 'plus' => array(
966
+ 'status' => 'full',
967
+ 'text' => array(
968
+ '<strong>' . esc_html__( 'Complete Entry Management inside WordPress', 'instagram-feed' ) . '</strong>',
969
+ ),
970
+ ),
971
+ 'pro' => array(
972
+ 'status' => 'full',
973
+ 'text' => array(
974
+ '<strong>' . esc_html__( 'User, hashtag, and tagged feeds', 'instagram-feed' ) . '</strong>',
975
+ ),
976
+ ),
977
+ ),
978
+ 'fields' => array(
979
+ 'lite' => array(
980
+ 'status' => 'partial',
981
+ 'text' => array(
982
+ '<strong>' . esc_html__( 'Grid layout only', 'instagram-feed' ) . '</strong>',
983
+ ),
984
+ ),
985
+ 'basic' => array(
986
+ 'status' => 'full',
987
+ 'text' => array(
988
+ '<strong>' . esc_html__( 'Access to all Standard and Fancy Fields', 'instagram-feed' ) . '</strong>',
989
+ esc_html__( 'Address, Phone, Website URL, Date/Time, Password, File Upload, HTML, Pagebreaks, Section Dividers, Ratings, and Hidden Field', 'instagram-feed' ),
990
+ ),
991
+ ),
992
+ 'plus' => array(
993
+ 'status' => 'full',
994
+ 'text' => array(
995
+ '<strong>' . esc_html__( 'Access to all Standard and Fancy Fields', 'instagram-feed' ) . '</strong>',
996
+ esc_html__( 'Address, Phone, Website URL, Date/Time, Password, File Upload, HTML, Pagebreaks, Section Dividers, Ratings, and Hidden Field', 'instagram-feed' ),
997
+ ),
998
+ ),
999
+ 'pro' => array(
1000
+ 'status' => 'full',
1001
+ 'text' => array(
1002
+ '<strong>' . esc_html__( 'Grid, highlight, masonry, and carousel layouts', 'instagram-feed' ) . '</strong>',
1003
+ ),
1004
+ ),
1005
+ ),
1006
+ 'conditionals' => array(
1007
+ 'lite' => array(
1008
+ 'status' => 'partial',
1009
+ 'text' => array(
1010
+ '<strong>' . esc_html__( 'Image, carousel, and video thumbnails', 'instagram-feed' ) . '</strong>',
1011
+ ),
1012
+ ),
1013
+ 'basic' => array(
1014
+ 'status' => 'full',
1015
+ 'text' => array(
1016
+ '<strong>' . esc_html__( 'Powerful Form Logic for Building Smart Forms', 'instagram-feed' ) . '</strong>',
1017
+ ),
1018
+ ),
1019
+ 'plus' => array(
1020
+ 'status' => 'full',
1021
+ 'text' => array(
1022
+ '<strong>' . esc_html__( 'Powerful Form Logic for Building Smart Forms', 'instagram-feed' ) . '</strong>',
1023
+ ),
1024
+ ),
1025
+ 'pro' => array(
1026
+ 'status' => 'full',
1027
+ 'text' => array(
1028
+ '<strong>' . esc_html__( 'Display images, swipe through carousel posts, and play videos in a pop-up lightbox', 'instagram-feed' ) . '</strong>',
1029
+ ),
1030
+ ),
1031
+ ),
1032
+ 'templates' => array(
1033
+ 'lite' => array(
1034
+ 'status' => 'partial',
1035
+ 'text' => array(
1036
+ '<strong>' . esc_html__( 'Images and link only', 'instagram-feed' ) . '</strong>',
1037
+ ),
1038
+ ),
1039
+ 'basic' => array(
1040
+ 'status' => 'partial',
1041
+ 'text' => array(
1042
+ '<strong>' . esc_html__( 'Basic Form Templates', 'instagram-feed' ) . '</strong>',
1043
+ ),
1044
+ ),
1045
+ 'plus' => array(
1046
+ 'status' => 'partial',
1047
+ 'text' => array(
1048
+ '<strong>' . esc_html__( 'Basic Form Templates', 'instagram-feed' ) . '</strong>',
1049
+ ),
1050
+ ),
1051
+ 'pro' => array(
1052
+ 'status' => 'full',
1053
+ 'text' => array(
1054
+ '<strong>' . esc_html__( 'Thumbnails, dates, caption, comments, like counts, and comment counts.', 'instagram-feed' ) . '</strong>',
1055
+ ),
1056
+ ),
1057
+ ),
1058
+ 'marketing' => array(
1059
+ 'lite' => array(
1060
+ 'status' => 'none',
1061
+ 'text' => array(
1062
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1063
+ ),
1064
+ ),
1065
+ 'basic' => array(
1066
+ 'status' => 'partial',
1067
+ 'text' => array(
1068
+ '<strong>' . esc_html__( 'Limited Marketing Integration', 'instagram-feed' ) . '</strong>',
1069
+ esc_html__( 'Constant Contact only', 'instagram-feed' ),
1070
+ ),
1071
+ ),
1072
+ 'plus' => array(
1073
+ 'status' => 'partial',
1074
+ 'text' => array(
1075
+ '<strong>' . esc_html__( '6 Email Marketing Integrations', 'instagram-feed' ) . '</strong>',
1076
+ esc_html__( 'Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip', 'instagram-feed' ),
1077
+ ),
1078
+ ),
1079
+ 'pro' => array(
1080
+ 'status' => 'full',
1081
+ 'text' => array(
1082
+ '<strong>' . esc_html__( 'Display your latest Instagram story in a pop-up lightbox', 'instagram-feed' ) . '</strong>',
1083
+ ),
1084
+ ),
1085
+ ),
1086
+ 'payments' => array(
1087
+ 'lite' => array(
1088
+ 'status' => 'none',
1089
+ 'text' => array(
1090
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1091
+ ),
1092
+ ),
1093
+ 'basic' => array(
1094
+ 'status' => 'none',
1095
+ 'text' => array(
1096
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1097
+ ),
1098
+ ),
1099
+ 'plus' => array(
1100
+ 'status' => 'none',
1101
+ 'text' => array(
1102
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1103
+ ),
1104
+ ),
1105
+ 'pro' => array(
1106
+ 'status' => 'full',
1107
+ 'text' => array(
1108
+ '<strong>' . esc_html__( 'Visual moderation system for removing posts or creating a "white list" of selected posts', 'instagram-feed' ) . '</strong>',
1109
+ ),
1110
+ ),
1111
+ ),
1112
+ 'surveys' => array(
1113
+ 'lite' => array(
1114
+ 'status' => 'partial',
1115
+ 'text' => array(
1116
+ '<strong>' . esc_html__( 'Standard or centered header', 'instagram-feed' ) . '</strong>',
1117
+ ),
1118
+ ),
1119
+ 'basic' => array(
1120
+ 'status' => 'none',
1121
+ 'text' => array(
1122
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1123
+ ),
1124
+ ),
1125
+ 'plus' => array(
1126
+ 'status' => 'none',
1127
+ 'text' => array(
1128
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1129
+ ),
1130
+ ),
1131
+ 'pro' => array(
1132
+ 'status' => 'full',
1133
+ 'text' => array(
1134
+ '<strong>' . esc_html__( 'Standard, centered, or boxed header that includes follower and post counts', 'instagram-feed' ) . '</strong>',
1135
+ ),
1136
+ ),
1137
+ ),
1138
+ 'advanced' => array(
1139
+ 'lite' => array(
1140
+ 'status' => 'partial',
1141
+ 'text' => array(
1142
+ '<strong>' . esc_html__( 'Posts link to the same post on Instagram', 'instagram-feed' ) . '</strong>',
1143
+ ),
1144
+ ),
1145
+ 'basic' => array(
1146
+ 'status' => 'partial',
1147
+ 'text' => array(
1148
+ '<strong>' . esc_html__( 'Limited Advanced Features', 'instagram-feed' ) . '</strong>',
1149
+ esc_html__( 'Multi-page Forms, File Upload Forms, Multiple Form Notifications, Conditional Form Confirmation', 'instagram-feed' ),
1150
+ ),
1151
+ ),
1152
+ 'plus' => array(
1153
+ 'status' => 'partial',
1154
+ 'text' => array(
1155
+ '<strong>' . esc_html__( 'Limited Advanced Features', 'instagram-feed' ) . '</strong>',
1156
+ esc_html__( 'Multi-page Forms, File Upload Forms, Multiple Form Notifications, Conditional Form Confirmation', 'instagram-feed' ),
1157
+ ),
1158
+ ),
1159
+ 'pro' => array(
1160
+ 'status' => 'full',
1161
+ 'text' => array(
1162
+ '<strong>' . esc_html__( 'Allow your posts to link to a URL in the caption or view in a lightbox', 'instagram-feed' ) . '</strong>',
1163
+ ),
1164
+ ),
1165
+ ),
1166
+ 'addons' => array(
1167
+ 'lite' => array(
1168
+ 'status' => 'none',
1169
+ 'text' => array(
1170
+ '<strong>' . esc_html__( 'Not available', 'instagram-feed' ) . '</strong>',
1171
+ ),
1172
+ ),
1173
+ 'basic' => array(
1174
+ 'status' => 'partial',
1175
+ 'text' => array(
1176
+ '<strong>' . esc_html__( 'Custom Captcha Addon included', 'instagram-feed' ) . '</strong>',
1177
+ ),
1178
+ ),
1179
+ 'plus' => array(
1180
+ 'status' => 'partial',
1181
+ 'text' => array(
1182
+ '<strong>' . esc_html__( 'Email Marketing Addons included', 'instagram-feed' ) . '</strong>',
1183
+ ),
1184
+ ),
1185
+ 'pro' => array(
1186
+ 'status' => 'full',
1187
+ 'text' => array(
1188
+ '<strong>' . esc_html__( 'Filter by word or hashtag', 'instagram-feed' ) . '</strong>',
1189
+ ),
1190
+ ),
1191
+ ),
1192
+ 'support' => array(
1193
+ 'lite' => array(
1194
+ 'status' => 'partial',
1195
+ 'text' => array(
1196
+ '<strong>' . esc_html__( 'Limited support', 'instagram-feed' ) . '</strong>',
1197
+ ),
1198
+ ),
1199
+ 'basic' => array(
1200
+ 'status' => 'partial',
1201
+ 'text' => array(
1202
+ '<strong>' . esc_html__( 'Standard Support', 'instagram-feed' ) . '</strong>',
1203
+ ),
1204
+ ),
1205
+ 'plus' => array(
1206
+ 'status' => 'partial',
1207
+ 'text' => array(
1208
+ '<strong>' . esc_html__( 'Standard Support', 'instagram-feed' ) . '</strong>',
1209
+ ),
1210
+ ),
1211
+ 'pro' => array(
1212
+ 'status' => 'full',
1213
+ 'text' => array(
1214
+ '<strong>' . esc_html__( 'Priority support', 'instagram-feed' ) . '</strong>',
1215
+ ),
1216
+ ),
1217
+ 'elite' => array(
1218
+ 'status' => 'full',
1219
+ 'text' => array(
1220
+ '<strong>' . esc_html__( 'Premium Support', 'instagram-feed' ) . '</strong>',
1221
+ ),
1222
+ ),
1223
+ 'ultimate' => array(
1224
+ 'status' => 'full',
1225
+ 'text' => array(
1226
+ '<strong>' . esc_html__( 'Premium Support', 'instagram-feed' ) . '</strong>',
1227
+ ),
1228
+ ),
1229
+ 'agency' => array(
1230
+ 'status' => 'full',
1231
+ 'text' => array(
1232
+ '<strong>' . esc_html__( 'Premium Support', 'instagram-feed' ) . '</strong>',
1233
+ ),
1234
+ ),
1235
+ ),
1236
+ 'sites' => array(
1237
+ 'basic' => array(
1238
+ 'status' => 'partial',
1239
+ 'text' => array(
1240
+ '<strong>' . esc_html__( '1 Site', 'instagram-feed' ) . '</strong>',
1241
+ ),
1242
+ ),
1243
+ 'plus' => array(
1244
+ 'status' => 'partial',
1245
+ 'text' => array(
1246
+ '<strong>' . esc_html__( '3 Sites', 'instagram-feed' ) . '</strong>',
1247
+ ),
1248
+ ),
1249
+ 'pro' => array(
1250
+ 'status' => 'full',
1251
+ 'text' => array(
1252
+ '<strong>' . esc_html__( '5 Sites', 'instagram-feed' ) . '</strong>',
1253
+ ),
1254
+ ),
1255
+ 'elite' => array(
1256
+ 'status' => 'full',
1257
+ 'text' => array(
1258
+ '<strong>' . esc_html__( 'Unlimited Sites', 'instagram-feed' ) . '</strong>',
1259
+ ),
1260
+ ),
1261
+ 'ultimate' => array(
1262
+ 'status' => 'full',
1263
+ 'text' => array(
1264
+ '<strong>' . esc_html__( 'Unlimited Sites', 'instagram-feed' ) . '</strong>',
1265
+ ),
1266
+ ),
1267
+ 'agency' => array(
1268
+ 'status' => 'full',
1269
+ 'text' => array(
1270
+ '<strong>' . esc_html__( 'Unlimited Sites', 'instagram-feed' ) . '</strong>',
1271
+ ),
1272
+ ),
1273
+ ),
1274
+ );
1275
+
1276
+ // Wrong feature?
1277
+ if ( ! isset( $data[ $feature ] ) ) {
1278
+ return false;
1279
+ }
1280
+
1281
+ // Is a top level license?
1282
+ $is_licenses_top = in_array( $license, self::$licenses_top, true );
1283
+
1284
+ // Wrong license type?
1285
+ if ( ! isset( $data[ $feature ][ $license ] ) && ! $is_licenses_top ) {
1286
+ return false;
1287
+ }
1288
+
1289
+ // Some licenses have partial data.
1290
+ if ( isset( $data[ $feature ][ $license ] ) ) {
1291
+ return $data[ $feature ][ $license ];
1292
+ }
1293
+
1294
+ // Top level plans has no feature difference with `pro` plan in most cases.
1295
+ return $is_licenses_top ? $data[ $feature ]['pro'] : $data[ $feature ][ $license ];
1296
+ }
1297
+
1298
+ /**
1299
+ * Get the current installation license type (always lowercase).
1300
+ *
1301
+ * @since 2.4/5.5
1302
+ *
1303
+ * @return string
1304
+ */
1305
+ protected function get_license_type() {
1306
+
1307
+ //$type = sbi_setting( 'type', '', 'sbi_license' );
1308
+
1309
+ //if ( empty( $type ) || ! sbi()->pro ) {
1310
+ $type = 'lite';
1311
+ //}
1312
+
1313
+ return strtolower( $type );
1314
+ }
1315
+ }
1316
+
1317
+ new SB_Instagram_About();
inc/admin/class-sbi-sitehealth.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SB_Instagram_SiteHealth {
4
+
5
+ /**
6
+ * Indicates if current integration is allowed to load.
7
+ *
8
+ * @since 1.5.5
9
+ *
10
+ * @return bool
11
+ */
12
+ public function allow_load() {
13
+
14
+ global $wp_version;
15
+
16
+ return version_compare( $wp_version, '5.2', '>=' );
17
+ }
18
+
19
+ /**
20
+ * Loads an integration.
21
+ *
22
+ * @since 1.5.5
23
+ */
24
+ public function load() {
25
+
26
+ $this->hooks();
27
+ }
28
+
29
+ /**
30
+ * Integration hooks.
31
+ *
32
+ * @since 1.5.5
33
+ */
34
+ protected function hooks() {
35
+ add_filter( 'site_status_tests', array( $this, 'add_tests' ) );
36
+ }
37
+
38
+ /**
39
+ * Add MonsterInsights WP Site Health tests.
40
+ *
41
+ * @param array $tests The current filters array.
42
+ *
43
+ * @return array
44
+ */
45
+ public function add_tests( $tests ) {
46
+ $tests['direct']['sbi_test_check_errors'] = array(
47
+ 'label' => __( 'Instagram Feed Errors', 'instagram-feed' ),
48
+ 'test' => array( $this, 'test_check_errors' )
49
+ );
50
+
51
+ return $tests;
52
+ }
53
+
54
+ /**
55
+ * Checks if there are Instagram API Errors
56
+ */
57
+ public function test_check_errors() {
58
+ $result = array(
59
+ 'label' => __( 'Instagram Feed has no critical errors', 'instagram-feed' ),
60
+ 'status' => 'good',
61
+ 'badge' => array(
62
+ 'label' => __( 'Instagram Feed', 'instagram-feed' ),
63
+ 'color' => 'blue',
64
+ ),
65
+ 'description' => __( 'No critical errors have been detected.', 'instagram-feed' ),
66
+ 'test' => 'sbi_test_check_errors',
67
+ );
68
+
69
+ global $sb_instagram_posts_manager;
70
+
71
+
72
+ if ( $sb_instagram_posts_manager->are_critical_errors() ) {
73
+ $link = admin_url( '?page=sb-instagram-feed');
74
+ $result['status'] = 'critical';
75
+ $result['label'] = __( 'Your Instagram Feed is experiencing an error.', 'instagram-feed' );
76
+ $result['description'] = sprintf( __( 'A critical issue has been detected with your Instagram Feed. Visit the %sInstagram Feed settings page%s to fix the issue.', 'instagram-feed' ), '<a href="' . esc_url( $link ) . '">', '</a>' );
77
+ }
78
+
79
+
80
+ return $result;
81
+ }
82
+ }
inc/admin/main.php CHANGED
@@ -1,2733 +1,2848 @@
1
- <?php
2
- /**
3
- * Includes functions for all admin page templates and
4
- * functions that add menu pages in the dashboard. Also
5
- * has code for saving settings with defaults.
6
- */
7
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
-
9
- function sb_instagram_menu() {
10
- $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
11
-
12
- $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
13
-
14
- add_menu_page(
15
- __( 'Instagram Feed', 'instagram-feed' ),
16
- __( 'Instagram Feed', 'instagram-feed' ),
17
- $cap,
18
- 'sb-instagram-feed',
19
- 'sb_instagram_settings_page'
20
- );
21
- add_submenu_page(
22
- 'sb-instagram-feed',
23
- __( 'Settings', 'instagram-feed' ),
24
- __( 'Settings', 'instagram-feed' ),
25
- $cap,
26
- 'sb-instagram-feed',
27
- 'sb_instagram_settings_page'
28
- );
29
- }
30
- add_action('admin_menu', 'sb_instagram_menu');
31
-
32
- function sb_instagram_settings_page() {
33
-
34
- //Hidden fields
35
- $sb_instagram_settings_hidden_field = 'sb_instagram_settings_hidden_field';
36
- $sb_instagram_configure_hidden_field = 'sb_instagram_configure_hidden_field';
37
- $sb_instagram_customize_hidden_field = 'sb_instagram_customize_hidden_field';
38
-
39
- //Declare defaults
40
- $sb_instagram_settings_defaults = array(
41
- 'sb_instagram_at' => '',
42
- 'sb_instagram_user_id' => '',
43
- 'sb_instagram_preserve_settings' => '',
44
- 'sb_instagram_cache_time' => 1,
45
- 'sb_instagram_cache_time_unit' => 'hours',
46
- 'sbi_caching_type' => 'page',
47
- 'sbi_cache_cron_interval' => '12hours',
48
- 'sbi_cache_cron_time' => '1',
49
- 'sbi_cache_cron_am_pm' => 'am',
50
- 'sb_instagram_width' => '100',
51
- 'sb_instagram_width_unit' => '%',
52
- 'sb_instagram_feed_width_resp' => false,
53
- 'sb_instagram_height' => '',
54
- 'sb_instagram_num' => '20',
55
- 'sb_instagram_height_unit' => '',
56
- 'sb_instagram_cols' => '4',
57
- 'sb_instagram_disable_mobile' => false,
58
- 'sb_instagram_image_padding' => '5',
59
- 'sb_instagram_image_padding_unit' => 'px',
60
- 'sb_instagram_sort' => 'none',
61
- 'sb_instagram_background' => '',
62
- 'sb_instagram_show_btn' => true,
63
- 'sb_instagram_btn_background' => '',
64
- 'sb_instagram_btn_text_color' => '',
65
- 'sb_instagram_btn_text' => __( 'Load More...', 'instagram-feed' ),
66
- 'sb_instagram_image_res' => 'auto',
67
- //Header
68
- 'sb_instagram_show_header' => true,
69
- 'sb_instagram_header_size' => 'small',
70
- 'sb_instagram_header_color' => '',
71
- 'sb_instagram_custom_bio' => '',
72
- 'sb_instagram_custom_avatar' => '',
73
- //Follow button
74
- 'sb_instagram_show_follow_btn' => true,
75
- 'sb_instagram_folow_btn_background' => '',
76
- 'sb_instagram_follow_btn_text_color' => '',
77
- 'sb_instagram_follow_btn_text' => __( 'Follow on Instagram', 'instagram-feed' ),
78
- //Misc
79
- 'sb_instagram_custom_css' => '',
80
- 'sb_instagram_custom_js' => '',
81
- 'sb_instagram_cron' => 'no',
82
- 'sb_instagram_backup' => true,
83
- 'sb_ajax_initial' => false,
84
- 'enqueue_css_in_shortcode' => false,
85
- 'sb_instagram_ajax_theme' => false,
86
- 'sb_instagram_disable_resize' => false,
87
- 'sb_instagram_favor_local' => false,
88
- 'sb_instagram_minnum' => 0,
89
- 'disable_js_image_loading' => false,
90
- 'enqueue_js_in_head' => false,
91
- 'sb_instagram_disable_mob_swipe' => false,
92
- 'sbi_font_method' => 'svg',
93
- 'sb_instagram_disable_awesome' => false,
94
- 'custom_template' => false
95
- );
96
- //Save defaults in an array
97
- $options = wp_parse_args(get_option('sb_instagram_settings'), $sb_instagram_settings_defaults);
98
- update_option( 'sb_instagram_settings', $options );
99
-
100
- //Set the page variables
101
- $sb_instagram_at = $options[ 'sb_instagram_at' ];
102
- $sb_instagram_user_id = $options[ 'sb_instagram_user_id' ];
103
- $sb_instagram_preserve_settings = $options[ 'sb_instagram_preserve_settings' ];
104
- $sb_instagram_ajax_theme = $options[ 'sb_instagram_ajax_theme' ];
105
- $enqueue_js_in_head = $options[ 'enqueue_js_in_head' ];
106
- $disable_js_image_loading = $options[ 'disable_js_image_loading' ];
107
- $sb_instagram_disable_resize = $options[ 'sb_instagram_disable_resize' ];
108
- $sb_instagram_favor_local = $options[ 'sb_instagram_favor_local' ];
109
- $sb_instagram_minnum = $options[ 'sb_instagram_minnum' ];
110
-
111
- $sb_instagram_cache_time = $options[ 'sb_instagram_cache_time' ];
112
- $sb_instagram_cache_time_unit = $options[ 'sb_instagram_cache_time_unit' ];
113
-
114
- $sbi_caching_type = $options[ 'sbi_caching_type' ];
115
- $sbi_cache_cron_interval = $options[ 'sbi_cache_cron_interval' ];
116
- $sbi_cache_cron_time = $options[ 'sbi_cache_cron_time' ];
117
- $sbi_cache_cron_am_pm = $options[ 'sbi_cache_cron_am_pm' ];
118
-
119
- $sb_instagram_width = $options[ 'sb_instagram_width' ];
120
- $sb_instagram_width_unit = $options[ 'sb_instagram_width_unit' ];
121
- $sb_instagram_feed_width_resp = $options[ 'sb_instagram_feed_width_resp' ];
122
- $sb_instagram_height = $options[ 'sb_instagram_height' ];
123
- $sb_instagram_height_unit = $options[ 'sb_instagram_height_unit' ];
124
- $sb_instagram_num = $options[ 'sb_instagram_num' ];
125
- $sb_instagram_cols = $options[ 'sb_instagram_cols' ];
126
- $sb_instagram_disable_mobile = $options[ 'sb_instagram_disable_mobile' ];
127
- $sb_instagram_image_padding = $options[ 'sb_instagram_image_padding' ];
128
- $sb_instagram_image_padding_unit = $options[ 'sb_instagram_image_padding_unit' ];
129
- $sb_instagram_sort = $options[ 'sb_instagram_sort' ];
130
- $sb_instagram_background = $options[ 'sb_instagram_background' ];
131
- $sb_instagram_show_btn = $options[ 'sb_instagram_show_btn' ];
132
- $sb_instagram_btn_background = $options[ 'sb_instagram_btn_background' ];
133
- $sb_instagram_btn_text_color = $options[ 'sb_instagram_btn_text_color' ];
134
- $sb_instagram_btn_text = $options[ 'sb_instagram_btn_text' ];
135
- $sb_instagram_image_res = $options[ 'sb_instagram_image_res' ];
136
- //Header
137
- $sb_instagram_show_header = $options[ 'sb_instagram_show_header' ];
138
- $sb_instagram_header_size = $options[ 'sb_instagram_header_size' ];
139
- $sb_instagram_show_bio = isset( $options[ 'sb_instagram_show_bio' ] ) ? $options[ 'sb_instagram_show_bio' ] : true;
140
- $sb_instagram_custom_bio = $options[ 'sb_instagram_custom_bio' ];
141
- $sb_instagram_custom_avatar = $options[ 'sb_instagram_custom_avatar' ];
142
- $sb_instagram_header_color = $options[ 'sb_instagram_header_color' ];
143
- //Follow button
144
- $sb_instagram_show_follow_btn = $options[ 'sb_instagram_show_follow_btn' ];
145
- $sb_instagram_folow_btn_background = $options[ 'sb_instagram_folow_btn_background' ];
146
- $sb_instagram_follow_btn_text_color = $options[ 'sb_instagram_follow_btn_text_color' ];
147
- $sb_instagram_follow_btn_text = $options[ 'sb_instagram_follow_btn_text' ];
148
- //Misc
149
- $sb_instagram_custom_css = $options[ 'sb_instagram_custom_css' ];
150
- $sb_instagram_custom_js = $options[ 'sb_instagram_custom_js' ];
151
- $sb_instagram_cron = $options[ 'sb_instagram_cron' ];
152
- $sb_instagram_backup = $options[ 'sb_instagram_backup' ];
153
- $sb_ajax_initial = $options[ 'sb_ajax_initial' ];
154
- $enqueue_css_in_shortcode = $options[ 'enqueue_css_in_shortcode' ];
155
- $sbi_font_method = $options[ 'sbi_font_method' ];
156
- $sb_instagram_disable_awesome = $options[ 'sb_instagram_disable_awesome' ];
157
- $sb_instagram_custom_template = $options[ 'custom_template' ];
158
-
159
-
160
-
161
- //Check nonce before saving data
162
- if ( ! isset( $_POST['sb_instagram_settings_nonce'] ) || ! wp_verify_nonce( $_POST['sb_instagram_settings_nonce'], 'sb_instagram_saving_settings' ) ) {
163
- //Nonce did not verify
164
- } else {
165
- // See if the user has posted us some information. If they did, this hidden field will be set to 'Y'.
166
- if( isset($_POST[ $sb_instagram_settings_hidden_field ]) && $_POST[ $sb_instagram_settings_hidden_field ] == 'Y' ) {
167
-
168
- if( isset($_POST[ $sb_instagram_configure_hidden_field ]) && $_POST[ $sb_instagram_configure_hidden_field ] == 'Y' ) {
169
-
170
- $sb_instagram_at = sanitize_text_field( $_POST[ 'sb_instagram_at' ] );
171
- $sb_instagram_user_id = array();
172
- if ( isset( $_POST[ 'sb_instagram_user_id' ] )) {
173
- if ( is_array( $_POST[ 'sb_instagram_user_id' ] ) ) {
174
- foreach( $_POST[ 'sb_instagram_user_id' ] as $user_id ) {
175
- $sb_instagram_user_id[] = sanitize_text_field( $user_id );
176
- }
177
- } else {
178
- $sb_instagram_user_id[] = sanitize_text_field( $_POST[ 'sb_instagram_user_id' ] );
179
- }
180
- }
181
- isset($_POST[ 'sb_instagram_preserve_settings' ]) ? $sb_instagram_preserve_settings = sanitize_text_field( $_POST[ 'sb_instagram_preserve_settings' ] ) : $sb_instagram_preserve_settings = '';
182
- isset($_POST[ 'sb_instagram_cache_time' ]) ? $sb_instagram_cache_time = sanitize_text_field( $_POST[ 'sb_instagram_cache_time' ] ) : $sb_instagram_cache_time = '';
183
- isset($_POST[ 'sb_instagram_cache_time_unit' ]) ? $sb_instagram_cache_time_unit = sanitize_text_field( $_POST[ 'sb_instagram_cache_time_unit' ] ) : $sb_instagram_cache_time_unit = '';
184
-
185
- isset($_POST[ 'sbi_caching_type' ]) ? $sbi_caching_type = sanitize_text_field( $_POST[ 'sbi_caching_type' ] ) : $sbi_caching_type = '';
186
- isset($_POST[ 'sbi_cache_cron_interval' ]) ? $sbi_cache_cron_interval = sanitize_text_field( $_POST[ 'sbi_cache_cron_interval' ] ) : $sbi_cache_cron_interval = '';
187
- isset($_POST[ 'sbi_cache_cron_time' ]) ? $sbi_cache_cron_time = sanitize_text_field( $_POST[ 'sbi_cache_cron_time' ] ) : $sbi_cache_cron_time = '';
188
- isset($_POST[ 'sbi_cache_cron_am_pm' ]) ? $sbi_cache_cron_am_pm = sanitize_text_field( $_POST[ 'sbi_cache_cron_am_pm' ] ) : $sbi_cache_cron_am_pm = '';
189
-
190
- $options[ 'sb_instagram_at' ] = $sb_instagram_at;
191
- $options[ 'sb_instagram_user_id' ] = $sb_instagram_user_id;
192
- $options[ 'sb_instagram_preserve_settings' ] = $sb_instagram_preserve_settings;
193
-
194
- $options[ 'sb_instagram_cache_time' ] = $sb_instagram_cache_time;
195
- $options[ 'sb_instagram_cache_time_unit' ] = $sb_instagram_cache_time_unit;
196
-
197
- $options[ 'sbi_caching_type' ] = $sbi_caching_type;
198
- $options[ 'sbi_cache_cron_interval' ] = $sbi_cache_cron_interval;
199
- $options[ 'sbi_cache_cron_time' ] = $sbi_cache_cron_time;
200
- $options[ 'sbi_cache_cron_am_pm' ] = $sbi_cache_cron_am_pm;
201
-
202
-
203
- //Delete all SBI transients
204
- global $wpdb;
205
- $table_name = $wpdb->prefix . "options";
206
- $wpdb->query( "
207
- DELETE
208
- FROM $table_name
209
- WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
210
- " );
211
- $wpdb->query( "
212
- DELETE
213
- FROM $table_name
214
- WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
215
- " );
216
- $wpdb->query( "
217
- DELETE
218
- FROM $table_name
219
- WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
220
- " );
221
- $wpdb->query( "
222
- DELETE
223
- FROM $table_name
224
- WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
225
- " );
226
-
227
- if ( $sbi_caching_type === 'background' ) {
228
- delete_option( 'sbi_cron_report' );
229
- SB_Instagram_Cron_Updater::start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm );
230
- }
231
-
232
- } //End config tab post
233
-
234
- if( isset($_POST[ $sb_instagram_customize_hidden_field ]) && $_POST[ $sb_instagram_customize_hidden_field ] == 'Y' ) {
235
-
236
- //Validate and sanitize width field
237
- $safe_width = intval( sanitize_text_field( $_POST['sb_instagram_width'] ) );
238
- if ( ! $safe_width ) $safe_width = '';
239
- if ( strlen( $safe_width ) > 4 ) $safe_width = substr( $safe_width, 0, 4 );
240
- $sb_instagram_width = $safe_width;
241
-
242
- $sb_instagram_width_unit = sanitize_text_field( $_POST[ 'sb_instagram_width_unit' ] );
243
- isset($_POST[ 'sb_instagram_feed_width_resp' ]) ? $sb_instagram_feed_width_resp = sanitize_text_field( $_POST[ 'sb_instagram_feed_width_resp' ] ) : $sb_instagram_feed_width_resp = '';
244
-
245
- //Validate and sanitize height field
246
- $safe_height = intval( sanitize_text_field( $_POST['sb_instagram_height'] ) );
247
- if ( ! $safe_height ) $safe_height = '';
248
- if ( strlen( $safe_height ) > 4 ) $safe_height = substr( $safe_height, 0, 4 );
249
- $sb_instagram_height = $safe_height;
250
-
251
- $sb_instagram_height_unit = sanitize_text_field( $_POST[ 'sb_instagram_height_unit' ] );
252
-
253
- //Validate and sanitize number of photos field
254
- $safe_num = intval( sanitize_text_field( $_POST['sb_instagram_num'] ) );
255
- if ( ! $safe_num ) $safe_num = '';
256
- if ( strlen( $safe_num ) > 4 ) $safe_num = substr( $safe_num, 0, 4 );
257
- $sb_instagram_num = $safe_num;
258
-
259
- $sb_instagram_cols = sanitize_text_field( $_POST[ 'sb_instagram_cols' ] );
260
- isset($_POST[ 'sb_instagram_disable_mobile' ]) ? $sb_instagram_disable_mobile = sanitize_text_field( $_POST[ 'sb_instagram_disable_mobile' ] ) : $sb_instagram_disable_mobile = '';
261
-
262
- //Validate and sanitize padding field
263
- $safe_padding = intval( sanitize_text_field( $_POST['sb_instagram_image_padding'] ) );
264
- if ( ! $safe_padding ) $safe_padding = '';
265
- if ( strlen( $safe_padding ) > 4 ) $safe_padding = substr( $safe_padding, 0, 4 );
266
- $sb_instagram_image_padding = $safe_padding;
267
-
268
- $sb_instagram_image_padding_unit = sanitize_text_field( $_POST[ 'sb_instagram_image_padding_unit' ] );
269
- $sb_instagram_sort = sanitize_text_field( $_POST[ 'sb_instagram_sort' ] );
270
- $sb_instagram_background = sanitize_text_field( $_POST[ 'sb_instagram_background' ] );
271
- isset($_POST[ 'sb_instagram_show_btn' ]) ? $sb_instagram_show_btn = sanitize_text_field( $_POST[ 'sb_instagram_show_btn' ] ) : $sb_instagram_show_btn = '';
272
- $sb_instagram_btn_background = sanitize_text_field( $_POST[ 'sb_instagram_btn_background' ] );
273
- $sb_instagram_btn_text_color = sanitize_text_field( $_POST[ 'sb_instagram_btn_text_color' ] );
274
- $sb_instagram_btn_text = sanitize_text_field( $_POST[ 'sb_instagram_btn_text' ] );
275
- $sb_instagram_image_res = sanitize_text_field( $_POST[ 'sb_instagram_image_res' ] );
276
- //Header
277
- isset($_POST[ 'sb_instagram_show_header' ]) ? $sb_instagram_show_header = sanitize_text_field( $_POST[ 'sb_instagram_show_header' ] ) : $sb_instagram_show_header = '';
278
- isset($_POST[ 'sb_instagram_show_bio' ]) ? $sb_instagram_show_bio = sanitize_text_field( $_POST[ 'sb_instagram_show_bio' ] ) : $sb_instagram_show_bio = '';
279
- isset($_POST[ 'sb_instagram_custom_bio' ]) ? $sb_instagram_custom_bio = sanitize_textarea_field( $_POST[ 'sb_instagram_custom_bio' ] ) : $sb_instagram_custom_bio = '';
280
- isset($_POST[ 'sb_instagram_custom_avatar' ]) ? $sb_instagram_custom_avatar = sanitize_text_field( $_POST[ 'sb_instagram_custom_avatar' ] ) : $sb_instagram_custom_avatar = '';
281
- if (isset($_POST[ 'sb_instagram_header_size' ]) ) $sb_instagram_header_size = $_POST[ 'sb_instagram_header_size' ];
282
-
283
- $sb_instagram_header_color = sanitize_text_field( $_POST[ 'sb_instagram_header_color' ] );
284
- //Follow button
285
- isset($_POST[ 'sb_instagram_show_follow_btn' ]) ? $sb_instagram_show_follow_btn = sanitize_text_field( $_POST[ 'sb_instagram_show_follow_btn' ] ) : $sb_instagram_show_follow_btn = '';
286
- $sb_instagram_folow_btn_background = sanitize_text_field( $_POST[ 'sb_instagram_folow_btn_background' ] );
287
- $sb_instagram_follow_btn_text_color = sanitize_text_field( $_POST[ 'sb_instagram_follow_btn_text_color' ] );
288
- $sb_instagram_follow_btn_text = sanitize_text_field( $_POST[ 'sb_instagram_follow_btn_text' ] );
289
- //Misc
290
- $sb_instagram_custom_css = $_POST[ 'sb_instagram_custom_css' ];
291
- $sb_instagram_custom_js = $_POST[ 'sb_instagram_custom_js' ];
292
- isset($_POST[ 'sb_instagram_ajax_theme' ]) ? $sb_instagram_ajax_theme = sanitize_text_field( $_POST[ 'sb_instagram_ajax_theme' ] ) : $sb_instagram_ajax_theme = '';
293
- isset($_POST[ 'enqueue_js_in_head' ]) ? $enqueue_js_in_head = $_POST[ 'enqueue_js_in_head' ] : $enqueue_js_in_head = '';
294
- isset($_POST[ 'disable_js_image_loading' ]) ? $disable_js_image_loading = $_POST[ 'disable_js_image_loading' ] : $disable_js_image_loading = '';
295
- isset($_POST[ 'sb_instagram_disable_resize' ]) ? $sb_instagram_disable_resize= sanitize_text_field( $_POST[ 'sb_instagram_disable_resize' ] ) : $sb_instagram_disable_resize = '';
296
- isset($_POST[ 'sb_instagram_favor_local' ]) ? $sb_instagram_favor_local = sanitize_text_field( $_POST[ 'sb_instagram_favor_local' ] ) : $sb_instagram_favor_local = '';
297
- isset($_POST[ 'sb_instagram_minnum' ]) ? $sb_instagram_minnum = sanitize_text_field( $_POST[ 'sb_instagram_minnum' ] ) : $sb_instagram_minnum = '';
298
-
299
- if (isset($_POST[ 'sb_instagram_cron' ]) ) $sb_instagram_cron = $_POST[ 'sb_instagram_cron' ];
300
- isset($_POST[ 'sb_instagram_backup' ]) ? $sb_instagram_backup = $_POST[ 'sb_instagram_backup' ] : $sb_instagram_backup = '';
301
- isset($_POST[ 'sb_ajax_initial' ]) ? $sb_ajax_initial = $_POST[ 'sb_ajax_initial' ] : $sb_ajax_initial = '';
302
- isset($_POST[ 'enqueue_css_in_shortcode' ]) ? $enqueue_css_in_shortcode = $_POST[ 'enqueue_css_in_shortcode' ] : $enqueue_css_in_shortcode = '';
303
- isset($_POST[ 'sbi_font_method' ]) ? $sbi_font_method = $_POST[ 'sbi_font_method' ] : $sbi_font_method = 'svg';
304
- isset($_POST[ 'sb_instagram_disable_awesome' ]) ? $sb_instagram_disable_awesome = sanitize_text_field( $_POST[ 'sb_instagram_disable_awesome' ] ) : $sb_instagram_disable_awesome = '';
305
-
306
- $options[ 'sb_instagram_width' ] = $sb_instagram_width;
307
- $options[ 'sb_instagram_width_unit' ] = $sb_instagram_width_unit;
308
- $options[ 'sb_instagram_feed_width_resp' ] = $sb_instagram_feed_width_resp;
309
- $options[ 'sb_instagram_height' ] = $sb_instagram_height;
310
- $options[ 'sb_instagram_height_unit' ] = $sb_instagram_height_unit;
311
- $options[ 'sb_instagram_num' ] = $sb_instagram_num;
312
- $options[ 'sb_instagram_cols' ] = $sb_instagram_cols;
313
- $options[ 'sb_instagram_disable_mobile' ] = $sb_instagram_disable_mobile;
314
- $options[ 'sb_instagram_image_padding' ] = $sb_instagram_image_padding;
315
- $options[ 'sb_instagram_image_padding_unit' ] = $sb_instagram_image_padding_unit;
316
- $options[ 'sb_instagram_sort' ] = $sb_instagram_sort;
317
- $options[ 'sb_instagram_background' ] = $sb_instagram_background;
318
- $options[ 'sb_instagram_show_btn' ] = $sb_instagram_show_btn;
319
- $options[ 'sb_instagram_btn_background' ] = $sb_instagram_btn_background;
320
- $options[ 'sb_instagram_btn_text_color' ] = $sb_instagram_btn_text_color;
321
- $options[ 'sb_instagram_btn_text' ] = $sb_instagram_btn_text;
322
- $options[ 'sb_instagram_image_res' ] = $sb_instagram_image_res;
323
- //Header
324
- $options[ 'sb_instagram_show_header' ] = $sb_instagram_show_header;
325
- $options[ 'sb_instagram_header_size' ] = $sb_instagram_header_size;
326
- $options[ 'sb_instagram_show_bio' ] = $sb_instagram_show_bio;
327
- $options[ 'sb_instagram_custom_bio' ] = $sb_instagram_custom_bio;
328
- $options[ 'sb_instagram_custom_avatar' ] = $sb_instagram_custom_avatar;
329
- $options[ 'sb_instagram_custom_bio' ] = $sb_instagram_custom_bio;
330
- $options[ 'sb_instagram_custom_avatar' ] = $sb_instagram_custom_avatar;
331
- $options[ 'sb_instagram_header_color' ] = $sb_instagram_header_color;
332
- //Follow button
333
- $options[ 'sb_instagram_show_follow_btn' ] = $sb_instagram_show_follow_btn;
334
- $options[ 'sb_instagram_folow_btn_background' ] = $sb_instagram_folow_btn_background;
335
- $options[ 'sb_instagram_follow_btn_text_color' ] = $sb_instagram_follow_btn_text_color;
336
- $options[ 'sb_instagram_follow_btn_text' ] = $sb_instagram_follow_btn_text;
337
- //Misc
338
- $options[ 'sb_instagram_custom_css' ] = $sb_instagram_custom_css;
339
- $options[ 'sb_instagram_custom_js' ] = $sb_instagram_custom_js;
340
- $options[ 'sb_instagram_ajax_theme' ] = $sb_instagram_ajax_theme;
341
- $options[ 'enqueue_js_in_head' ] = $enqueue_js_in_head;
342
- $options[ 'disable_js_image_loading' ] = $disable_js_image_loading;
343
- $options[ 'sb_instagram_disable_resize' ] = $sb_instagram_disable_resize;
344
- $options[ 'sb_instagram_favor_local' ] = $sb_instagram_favor_local;
345
- $options[ 'sb_instagram_minnum' ] = $sb_instagram_minnum;
346
-
347
- $options[ 'sb_ajax_initial' ] = $sb_ajax_initial;
348
- $options[ 'sb_instagram_cron' ] = $sb_instagram_cron;
349
- $options['sb_instagram_backup'] = $sb_instagram_backup;
350
- $options['enqueue_css_in_shortcode'] = $enqueue_css_in_shortcode;
351
-
352
- $options['sbi_font_method'] = $sbi_font_method;
353
- $options[ 'sb_instagram_disable_awesome' ] = $sb_instagram_disable_awesome;
354
-
355
- isset($_POST[ 'sb_instagram_custom_template' ]) ? $sb_instagram_custom_template = $_POST[ 'sb_instagram_custom_template' ] : $sb_instagram_custom_template = '';
356
- $options['custom_template'] = $sb_instagram_custom_template;
357
-
358
- //clear expired tokens
359
- delete_option( 'sb_expired_tokens' );
360
-
361
- //Delete all SBI transients
362
- global $wpdb;
363
- $table_name = $wpdb->prefix . "options";
364
- $wpdb->query( "
365
- DELETE
366
- FROM $table_name
367
- WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
368
- " );
369
- $wpdb->query( "
370
- DELETE
371
- FROM $table_name
372
- WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
373
- " );
374
- $wpdb->query( "
375
- DELETE
376
- FROM $table_name
377
- WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
378
- " );
379
- $wpdb->query( "
380
- DELETE
381
- FROM $table_name
382
- WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
383
- " );
384
-
385
- if( $sb_instagram_cron == 'no' ) wp_clear_scheduled_hook('sb_instagram_cron_job');
386
-
387
- //Run cron when Misc settings are saved
388
- if( $sb_instagram_cron == 'yes' ){
389
- //Clear the existing cron event
390
- wp_clear_scheduled_hook('sb_instagram_cron_job');
391
-
392
- $sb_instagram_cache_time = $options[ 'sb_instagram_cache_time' ];
393
- $sb_instagram_cache_time_unit = $options[ 'sb_instagram_cache_time_unit' ];
394
-
395
- //Set the event schedule based on what the caching time is set to
396
- $sb_instagram_cron_schedule = 'hourly';
397
- if( $sb_instagram_cache_time_unit == 'hours' && $sb_instagram_cache_time > 5 ) $sb_instagram_cron_schedule = 'twicedaily';
398
- if( $sb_instagram_cache_time_unit == 'days' ) $sb_instagram_cron_schedule = 'daily';
399
-
400
- wp_schedule_event(time(), $sb_instagram_cron_schedule, 'sb_instagram_cron_job');
401
-
402
- sb_instagram_clear_page_caches();
403
- }
404
-
405
- } //End customize tab post
406
-
407
- //Save the settings to the settings array
408
- update_option( 'sb_instagram_settings', $options );
409
-
410
- ?>
411
- <div class="updated"><p><strong><?php _e( 'Settings saved.', 'instagram-feed' ); ?></strong></p></div>
412
- <?php } ?>
413
-
414
- <?php } //End nonce check ?>
415
-
416
-
417
- <div id="sbi_admin" class="wrap">
418
- <?php
419
- $lite_notice_dismissed = get_transient( 'instagram_feed_dismiss_lite' );
420
-
421
- if ( ! $lite_notice_dismissed ) :
422
- ?>
423
- <div id="sbi-notice-bar" style="display:none">
424
- <span class="sbi-notice-bar-message"><?php _e( 'You\'re using Instagram Feed Lite. To unlock more features consider <a href="https://smashballoon.com/instagram-feed/?utm_source=WordPress&utm_campaign=instagramliteplugin&utm_medium=notice-bar" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.', 'instagram-feed'); ?></span>
425
- <button type="button" class="dismiss" title="<?php _e( 'Dismiss this message.', 'instagram-feed'); ?>" data-page="overview">
426
- </button>
427
- </div>
428
- <?php endif; ?>
429
- <div id="header">
430
- <h1><?php _e( 'Instagram Feed', 'instagram-feed' ); ?></h1>
431
- </div>
432
- <?php
433
- $sb_instagram_type = 'user';
434
- $returned_data = sbi_get_connected_accounts_data( $sb_instagram_at );
435
- $sb_instagram_at = $returned_data['access_token'];
436
- $connected_accounts = $returned_data['connected_accounts'];
437
- $user_feeds_returned = isset( $returned_data['user_ids'] ) ? $returned_data['user_ids'] : false;
438
- if ( $user_feeds_returned ) {
439
- $user_feed_ids = $user_feeds_returned;
440
- } else {
441
- $user_feed_ids = ! is_array( $sb_instagram_user_id ) ? explode( ',', $sb_instagram_user_id ) : $sb_instagram_user_id;
442
- }
443
-
444
- $new_user_name = false;
445
-
446
-
447
-
448
-
449
- if( isset($_GET['access_token']) && isset($_GET['graph_api']) && empty($_POST) ) { ?>
450
- <?php
451
- $access_token = sbi_maybe_clean(urldecode($_GET['access_token']));
452
- //
453
- $url = 'https://graph.facebook.com/me/accounts?fields=instagram_business_account,access_token&limit=500&access_token='.$access_token;
454
- $args = array(
455
- 'timeout' => 60,
456
- 'sslverify' => false
457
- );
458
- $result = wp_remote_get( $url, $args );
459
- $pages_data = '{}';
460
- if ( ! is_wp_error( $result ) ) {
461
- $pages_data = $result['body'];
462
- } else {
463
- $page_error = $result;
464
- }
465
-
466
- $pages_data_arr = json_decode($pages_data);
467
- $num_accounts = 0;
468
- if(isset($pages_data_arr)){
469
- $num_accounts = is_array( $pages_data_arr->data ) ? count( $pages_data_arr->data ) : 0;
470
- }
471
- ?>
472
- <div id="sbi_config_info" class="sb_list_businesses sbi_num_businesses_<?php echo $num_accounts; ?>">
473
- <div class="sbi_config_modal">
474
- <div class="sbi-managed-pages">
475
- <?php if ( isset( $page_error ) && isset( $page_error->errors ) ) {
476
- foreach ($page_error->errors as $key => $item) {
477
- echo '<div class="sbi_user_id_error" style="display:block;"><strong>Connection Error: </strong>' . $key . ': ' . $item[0] . '</div>';
478
- }
479
- }
480
- ?>
481
- <?php if( empty($pages_data_arr->data) ) : ?>
482
- <span id="sbi-bus-account-error">
483
- <p style="margin-top: 5px;"><b style="font-size: 16px">Couldn't find Business Profile</b><br />
484
- Uh oh. It looks like this Facebook account is not currently connected to an Instagram Business profile. Please check that you are logged into the <a href="https://www.facebook.com/" target="_blank">Facebook account</a> in this browser which is associated with your Instagram Business Profile.</p>
485
- <p><b style="font-size: 16px">Why do I need a Business Profile?</b><br />
486
- A Business Profile is only required if you are displaying a Hashtag feed. If you want to display a regular User feed then you can do this by selecting to connect a Personal account instead. For directions on how to convert your Personal profile into a Business profile please <a href="https://smashballoon.com/instagram-business-profiles" target="_blank">see here</a>.</p>
487
- </span>
488
-
489
- <?php elseif ( $num_accounts === 0 ): ?>
490
- <span id="sbi-bus-account-error">
491
- <p style="margin-top: 5px;"><b style="font-size: 16px">Couldn't find Business Profile</b><br />
492
- Uh oh. It looks like this Facebook account is not currently connected to an Instagram Business profile. Please check that you are logged into the <a href="https://www.facebook.com/" target="_blank">Facebook account</a> in this browser which is associated with your Instagram Business Profile.</p>
493
- <p>If you are, in fact, logged-in to the correct account please make sure you have Instagram accounts connected with your Facebook account by following <a href="https://smashballoon.com/reconnecting-an-instagram-business-profile/" target="_blank">this FAQ</a></p>
494
- </span>
495
- <?php else: ?>
496
- <p class="sbi-managed-page-intro"><b style="font-size: 16px;">Instagram Business profiles for this account</b><br /><i style="color: #666;">Note: In order to display a Hashtag feed you first need to select a Business profile below.</i></p>
497
- <?php if ( $num_accounts > 1 ) : ?>
498
- <div class="sbi-managed-page-select-all"><input type="checkbox" id="sbi-select-all" class="sbi-select-all"><label for="sbi-select-all">Select All</label></div>
499
- <?php endif; ?>
500
- <div class="sbi-scrollable-accounts">
501
-
502
- <?php foreach ( $pages_data_arr->data as $page => $page_data ) : ?>
503
-
504
- <?php if( isset( $page_data->instagram_business_account ) ) :
505
-
506
- $instagram_business_id = $page_data->instagram_business_account->id;
507
-
508
- $page_access_token = isset( $page_data->access_token ) ? $page_data->access_token : '';
509
-
510
- //Make another request to get page info
511
- $instagram_account_url = 'https://graph.facebook.com/'.$instagram_business_id.'?fields=name,username,profile_picture_url&access_token='.$access_token;
512
-
513
- $args = array(
514
- 'timeout' => 60,
515
- 'sslverify' => false
516
- );
517
- $result = wp_remote_get( $instagram_account_url, $args );
518
- $instagram_account_info = '{}';
519
- if ( ! is_wp_error( $result ) ) {
520
- $instagram_account_info = $result['body'];
521
- } else {
522
- $page_error = $result;
523
- }
524
-
525
- $instagram_account_data = json_decode($instagram_account_info);
526
-
527
- $instagram_biz_img = isset( $instagram_account_data->profile_picture_url ) ? $instagram_account_data->profile_picture_url : false;
528
- $selected_class = $instagram_business_id == $sb_instagram_user_id ? ' sbi-page-selected' : '';
529
-
530
- ?>
531
- <?php if ( isset( $page_error ) && isset( $page_error->errors ) ) :
532
- foreach ($page_error->errors as $key => $item) {
533
- echo '<div class="sbi_user_id_error" style="display:block;"><strong>Connection Error: </strong>' . $key . ': ' . $item[0] . '</div>';
534
- }
535
- else : ?>
536
- <div class="sbi-managed-page<?php echo $selected_class; ?>" data-page-token="<?php echo esc_attr( $page_access_token ); ?>" data-token="<?php echo esc_attr( $access_token ); ?>" data-page-id="<?php echo esc_attr( $instagram_business_id ); ?>">
537
- <div class="sbi-add-checkbox">
538
- <input id="sbi-<?php echo esc_attr( $instagram_business_id ); ?>" type="checkbox" name="sbi_managed_pages[]" value="<?php echo esc_attr( $instagram_account_info ); ?>">
539
- </div>
540
- <div class="sbi-managed-page-details">
541
- <label for="sbi-<?php echo esc_attr( $instagram_business_id ); ?>"><img class="sbi-page-avatar" border="0" height="50" width="50" src="<?php echo esc_url( $instagram_biz_img ); ?>"><b style="font-size: 16px;"><?php echo esc_html( $instagram_account_data->name ); ?></b>
542
- <br />@<?php echo esc_html( $instagram_account_data->username); ?><span style="font-size: 11px; margin-left: 5px;">(<?php echo esc_html( $instagram_business_id ); ?>)</span></label>
543
- </div>
544
- </div>
545
- <?php endif; ?>
546
-
547
- <?php endif; ?>
548
-
549
- <?php endforeach; ?>
550
-
551
- </div> <!-- end scrollable -->
552
- <a href="JavaScript:void(0);" id="sbi-connect-business-accounts" class="button button-primary" disabled="disabled" style="margin-top: 20px;">Connect Accounts</a>
553
-
554
- <?php endif; ?>
555
-
556
- <a href="JavaScript:void(0);" class="sbi_modal_close"><i class="fa fa-times"></i></a>
557
- </div>
558
- </div>
559
- </div>
560
- <?php } elseif ( isset( $_GET['access_token'] ) && isset( $_GET['account_type'] ) && empty( $_POST ) ) {
561
- $access_token = sanitize_text_field( $_GET['access_token'] );
562
- $account_type = sanitize_text_field( $_GET['account_type'] );
563
- $user_id = sanitize_text_field( $_GET['id'] );
564
- $user_name = sanitize_text_field( $_GET['username'] );
565
- $expires_in = (int)$_GET['expires_in'];
566
- $expires_timestamp = time() + $expires_in;
567
-
568
- $new_account_details = array(
569
- 'access_token' => $access_token,
570
- 'account_type' => $account_type,
571
- 'user_id' => $user_id,
572
- 'username' => $user_name,
573
- 'expires_timestamp' => $expires_timestamp,
574
- 'type' => 'basic'
575
- );
576
-
577
-
578
- $matches_existing_personal = sbi_matches_existing_personal( $new_account_details );
579
- $button_text = $matches_existing_personal ? __( 'Update This Account', 'instagram-feed' ) : __( 'Connect This Account', 'instagram-feed' );
580
-
581
- $account_json = wp_json_encode( $new_account_details );
582
-
583
- $already_connected_as_business_account = (isset( $connected_accounts[ $user_id ] ) && $connected_accounts[ $user_id ]['type'] === 'business');
584
-
585
- ?>
586
-
587
- <div id="sbi_config_info" class="sb_get_token">
588
- <div class="sbi_config_modal">
589
- <div class="sbi_ca_username"><strong><?php echo esc_html( $user_name ); ?></strong></div>
590
- <form action="<?php echo admin_url( 'admin.php?page=sb-instagram-feed' ); ?>" method="post">
591
- <p class="sbi_submit">
592
- <?php if ( $already_connected_as_business_account ) :
593
- _e( 'The Instagram account you are logged into is already connected as a "business" account. Remove the business account if you\'d like to connect as a basic account instead (not recommended).', 'instagram-feed' );
594
- ?>
595
- <?php else : ?>
596
- <input type="submit" name="sbi_submit" id="sbi_connect_account" class="button button-primary" value="<?php echo esc_html( $button_text ); ?>">
597
- <?php endif; ?>
598
- <input type="hidden" name="sbi_account_json" value="<?php echo esc_attr( $account_json ) ; ?>">
599
- <input type="hidden" name="sbi_connect_username" value="<?php echo esc_attr( $user_name ); ?>">
600
- <a href="JavaScript:void(0);" class="button button-secondary" id="sbi_switch_accounts"><?php esc_html_e( 'Switch Accounts', 'instagram-feed' ); ?></a>
601
- </p>
602
- </form>
603
- <a href="JavaScript:void(0);"><i class="sbi_modal_close fa fa-times"></i></a>
604
- </div>
605
- </div>
606
- <?php
607
- } elseif ( isset( $_POST['sbi_connect_username'] ) ) {
608
-
609
- $new_user_name = sanitize_text_field( $_POST['sbi_connect_username'] );
610
- $new_account_details = json_decode( stripslashes( $_POST['sbi_account_json'] ), true );
611
- array_map( 'sanitize_text_field', $new_account_details );
612
-
613
- $updated_options = sbi_connect_basic_account( $new_account_details );
614
- $connected_accounts = $updated_options['connected_accounts'];
615
- $user_feed_ids = $updated_options['sb_instagram_user_id'];
616
- }?>
617
-
618
- <?php //Display connected page
619
- if (isset( $sbi_connected_page ) && strpos($sbi_connected_page, ':') !== false) {
620
-
621
- $sbi_connected_page_pieces = explode(":", $sbi_connected_page);
622
- $sbi_connected_page_id = $sbi_connected_page_pieces[0];
623
- $sbi_connected_page_name = $sbi_connected_page_pieces[1];
624
- $sbi_connected_page_image = $sbi_connected_page_pieces[2];
625
-
626
- echo '&nbsp;';
627
- echo '<p style="font-weight: bold; margin-bottom: 5px;">Connected Business Profile:</p>';
628
- echo '<div class="sbi-managed-page sbi-no-select">';
629
- echo '<p><img class="sbi-page-avatar" border="0" height="50" width="50" src="'.$sbi_connected_page_image.'"><b>'.$sbi_connected_page_name.'</b> &nbsp; ('.$sbi_connected_page_id.')</p>';
630
- echo '</div>';
631
- }
632
-
633
- ?>
634
-
635
- <form name="form1" method="post" action="">
636
- <input type="hidden" name="<?php echo $sb_instagram_settings_hidden_field; ?>" value="Y">
637
- <?php wp_nonce_field( 'sb_instagram_saving_settings', 'sb_instagram_settings_nonce' ); ?>
638
-
639
- <?php $sbi_active_tab = isset( $_GET[ 'tab' ] ) ? sanitize_text_field( $_GET['tab'] ) : 'configure'; ?>
640
- <h2 class="nav-tab-wrapper">
641
- <a href="?page=sb-instagram-feed&amp;tab=configure" class="nav-tab <?php echo $sbi_active_tab == 'configure' ? 'nav-tab-active' : ''; ?>"><?php _e( '1. Configure', 'instagram-feed' ); ?></a>
642
- <a href="?page=sb-instagram-feed&amp;tab=customize" class="nav-tab <?php echo $sbi_active_tab == 'customize' ? 'nav-tab-active' : ''; ?>"><?php _e( '2. Customize', 'instagram-feed' ); ?></a>
643
- <a href="?page=sb-instagram-feed&amp;tab=display" class="nav-tab <?php echo $sbi_active_tab == 'display' ? 'nav-tab-active' : ''; ?>"><?php _e( '3. Display Your Feed', 'instagram-feed' ); ?></a>
644
- <a href="?page=sb-instagram-feed&amp;tab=support" class="nav-tab <?php echo $sbi_active_tab == 'support' ? 'nav-tab-active' : ''; ?>"><?php _e( 'Support', 'instagram-feed' ); ?></a>
645
- </h2>
646
-
647
- <?php if( $sbi_active_tab == 'configure' ) { //Start Configure tab ?>
648
- <input type="hidden" name="<?php echo $sb_instagram_configure_hidden_field; ?>" value="Y">
649
-
650
- <table class="form-table">
651
- <tbody>
652
- <h3><?php _e( 'Configure', 'instagram-feed' ); ?></h3>
653
-
654
- <div id="sbi_config">
655
- <a data-personal-basic-api="https://api.instagram.com/oauth/authorize?app_id=423965861585747&redirect_uri=https://api.smashballoon.com/instagram-basic-display-redirect.php&response_type=code&scope=user_profile,user_media&state=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>"
656
- data-new-api="https://www.facebook.com/dialog/oauth?client_id=254638078422287&redirect_uri=https://api.smashballoon.com/instagram-graph-api-redirect.php&scope=manage_pages,instagram_basic,instagram_manage_insights,instagram_manage_comments&state=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>"
657
- data-old-api="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>&hl=en"
658
- href="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>&hl=en" class="sbi_admin_btn"><i class="fa fa-user-plus" aria-hidden="true" style="font-size: 20px;"></i>&nbsp; <?php _e('Connect an Instagram Account', 'instagram-feed' ); ?></a>
659
-
660
- <!--<a href="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>" class="sbi_admin_btn"><i class="fa fa-user-plus" aria-hidden="true" style="font-size: 20px;"></i>&nbsp; <?php _e('Connect an Instagram Account', 'instagram-feed' ); ?></a>
661
- -->
662
- <a href="https://smashballoon.com/instagram-feed/token/" target="_blank" style="position: relative; top: 14px; left: 15px;"><?php _e('Button not working?', 'instagram-feed'); ?></a>
663
- </div>
664
-
665
- <!-- Old Access Token -->
666
- <input name="sb_instagram_at" id="sb_instagram_at" type="hidden" value="<?php echo esc_attr( $sb_instagram_at ); ?>" size="80" maxlength="100" placeholder="Click button above to get your Access Token" />
667
-
668
- <tr valign="top">
669
- <th scope="row"><label><?php _e( 'Instagram Accounts', 'instagram-feed' ); ?></label><span style="font-weight:normal; font-style:italic; font-size: 12px; display: block;"><?php _e('Use the button above to connect an Instagram account', 'instagram-feed'); ?></span></th>
670
- <td class="sbi_connected_accounts_wrap">
671
- <?php if ( empty( $connected_accounts ) ) : ?>
672
- <p class="sbi_no_accounts"><?php _e( 'No Instagram accounts connected. Click the button above to connect an account.', 'instagram-feed' ); ?></p><br />
673
- <?php else:
674
- if ( sbi_is_after_deprecation_deadline() ) {
675
- $deprecated_connected_account_message = __( '<b>Action Needed:</b> Reconnect this account to allow feed to update.', 'instagram-feed' );
676
- } else {
677
- $deprecated_connected_account_message = __( '<b>Action Needed:</b> Reconnect this account before March 31, 2020 to avoid disruption with this feed.', 'instagram-feed' );
678
- }
679
-
680
- $accounts_that_need_updating = sbi_get_user_names_of_personal_accounts_not_also_already_updated();
681
- ?>
682
- <?php foreach ( $connected_accounts as $account ) :
683
- $username = $account['username'] ? $account['username'] : $account['user_id'];
684
- if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['sb_instagram_favor_local'] ) && $options['sb_instagram_favor_local' ] === 'on' ) {
685
- $upload = wp_upload_dir();
686
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
687
- $profile_picture = '<img class="sbi_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
688
- } else {
689
- $profile_picture = $account['profile_picture'] ? '<img class="sbi_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
690
- }
691
-
692
- $is_invalid_class = ! $account['is_valid'] ? ' sbi_account_invalid' : '';
693
- $in_user_feed = in_array( $account['user_id'], $user_feed_ids, true );
694
- $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
695
- $use_tagged = isset( $account['use_tagged'] ) && $account['use_tagged'] == '1';
696
-
697
- if ( empty( $profile_picture ) && $account_type === 'personal' ) {
698
- $account_update = sbi_account_data_for_token( $account['access_token'] );
699
- if ( isset( $account['is_valid'] ) ) {
700
- $split = explode( '.', $account['access_token'] );
701
- $connected_accounts[ $split[0] ] = array(
702
- 'access_token' => $account['access_token'],
703
- 'user_id' => $split[0],
704
- 'username' => $account_update['username'],
705
- 'is_valid' => true,
706
- 'last_checked' => time(),
707
- 'profile_picture' => $account_update['profile_picture']
708
- );
709
-
710
- $sbi_options = get_option( 'sb_instagram_settings', array() );
711
- $sbi_options['connected_accounts'] = $connected_accounts;
712
- update_option( 'sb_instagram_settings', $sbi_options );
713
- }
714
-
715
- }
716
- $updated_or_new_account_class = $new_user_name === $username && $account_type !== 'business' ? ' sbi_ca_new_or_updated' : '';
717
-
718
- ?>
719
- <div class="sbi_connected_account<?php echo $is_invalid_class . $updated_or_new_account_class; ?><?php if ( $in_user_feed ) echo ' sbi_account_active' ?> sbi_account_type_<?php echo $account_type; ?>" id="sbi_connected_account_<?php esc_attr_e( $account['user_id'] ); ?>" data-accesstoken="<?php esc_attr_e( $account['access_token'] ); ?>" data-userid="<?php esc_attr_e( $account['user_id'] ); ?>" data-username="<?php esc_attr_e( $account['username'] ); ?>" data-type="<?php esc_attr_e( $account_type ); ?>" data-permissions="<?php if ( $use_tagged ) echo 'tagged'; ?>">
720
- <?php if ( $account_type === 'personal' && in_array( $username, $accounts_that_need_updating, true ) ) : ?>
721
- <div class="sbi_deprecated">
722
- <span><i class="fa fa-exclamation-circle" aria-hidden="true"></i><?php echo $deprecated_connected_account_message; ?> <button class="sbi_reconnect button-primary">Reconnect</button></span>
723
- </div>
724
- <?php endif; ?>
725
- <div class="sbi_ca_alert">
726
- <span><?php _e( 'The Access Token for this account is expired or invalid. Click the button above to attempt to renew it.', 'instagram-feed' ) ?></span>
727
- </div>
728
- <div class="sbi_ca_info">
729
-
730
- <div class="sbi_ca_delete">
731
- <a href="JavaScript:void(0);" class="sbi_delete_account"><i class="fa fa-times"></i><span class="sbi_remove_text"><?php _e( 'Remove', 'instagram-feed' ); ?></span></a>
732
- </div>
733
-
734
- <div class="sbi_ca_username">
735
- <?php echo $profile_picture; ?>
736
- <strong><?php echo $username; ?><span><?php echo sbi_account_type_display( $account_type ); ?></span></strong>
737
- </div>
738
-
739
- <div class="sbi_ca_actions">
740
- <?php if ( ! $in_user_feed ) : ?>
741
- <a href="JavaScript:void(0);" class="sbi_use_in_user_feed button-primary"><i class="fa fa-plus-circle" aria-hidden="true"></i><?php _e( 'Add to Primary Feed', 'instagram-feed' ); ?></a>
742
- <?php else : ?>
743
- <a href="JavaScript:void(0);" class="sbi_remove_from_user_feed button-primary"><i class="fa fa-minus-circle" aria-hidden="true"></i><?php _e( 'Remove from Primary Feed', 'instagram-feed' ); ?></a>
744
- <?php endif; ?>
745
- <a class="sbi_ca_token_shortcode button-secondary" href="JavaScript:void(0);"><i class="fa fa-chevron-circle-right" aria-hidden="true"></i><?php _e( 'Add to another Feed', 'instagram-feed' ); ?></a>
746
- <a class="sbi_ca_show_token button-secondary" href="JavaScript:void(0);" title="<?php _e('Show access token and account info', 'instagram-feed'); ?>"><i class="fa fa-cog"></i></a>
747
-
748
- </div>
749
-
750
- <div class="sbi_ca_shortcode">
751
-
752
- <p><?php _e('Copy and paste this shortcode into your page or widget area', 'instagram-feed'); ?>:<br>
753
- <?php if ( !empty( $account['username'] ) ) : ?>
754
- <code>[instagram-feed user="<?php echo $account['username']; ?>"]</code>
755
- <?php else : ?>
756
- <code>[instagram-feed accesstoken="<?php echo $account['access_token']; ?>"]</code>
757
- <?php endif; ?>
758
- </p>
759
-
760
- <p><?php _e('To add multiple users in the same feed, simply separate them using commas', 'instagram-feed'); ?>:<br>
761
- <?php if ( !empty( $account['username'] ) ) : ?>
762
- <code>[instagram-feed user="<?php echo $account['username']; ?>, a_second_user, a_third_user"]</code>
763
- <?php else : ?>
764
- <code>[instagram-feed accesstoken="<?php echo $account['access_token']; ?>, another_access_token"]</code>
765
- <?php endif; ?>
766
-
767
- <p><?php echo sprintf( __('Click on the %s tab to learn more about shortcodes', 'instagram-feed'), '<a href="?page=sb-instagram-feed&tab=display" target="_blank">'. __( 'Display Your Feed', 'instagram-feed' ) . '</a>' ); ?></p>
768
- </div>
769
-
770
- <div class="sbi_ca_accesstoken">
771
- <span class="sbi_ca_token_label"><?php _e('Access Token', 'instagram-feed');?>:</span><input type="text" class="sbi_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).', 'instagram-feed');?>"><br>
772
- <span class="sbi_ca_token_label"><?php _e('User ID', 'instagram-feed');?>:</span><input type="text" class="sbi_ca_user_id" value="<?php echo $account['user_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).', 'instagram-feed');?>"><br>
773
- </div>
774
-
775
- </div>
776
-
777
- </div>
778
-
779
- <?php endforeach; ?>
780
- <?php endif; ?>
781
- <a href="JavaScript:void(0);" class="sbi_manually_connect button-secondary"><?php _e( 'Manually Connect an Account', 'instagram-feed' ); ?></a>
782
- <div class="sbi_manually_connect_wrap">
783
- <input name="sb_manual_at" id="sb_manual_at" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="64" minlength="15" maxlength="200" placeholder="Enter a valid Instagram Access Token" /><span class='sbi_business_profile_tag'><?php _e('Business or Basic Display', 'instagram-feed');?></span>
784
- <div class="sbi_manual_account_id_toggle">
785
- <label><?php _e('Please enter the User ID for this Profile:', 'instagram-feed');?></label>
786
- <input name="sb_manual_account_id" id="sb_manual_account_id" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="40" minlength="5" maxlength="100" placeholder="Eg: 15641403491391489" />
787
- </div>
788
- <p class="sbi_submit" style="display: inline-block;"><input type="sbi_submit" name="submit" id="sbi_manual_submit" class="button button-primary" style="text-align: center; padding: 0;" value="<?php _e('Connect This Account', 'instagram-feed' );?>"></p>
789
- </div>
790
- </td>
791
- </tr>
792
-
793
- <tr valign="top" class="sbi_feed_type">
794
- <th scope="row"><label><?php _e('Show Photos From:', 'instagram-feed'); ?></label><code class="sbi_shortcode"> type
795
- Eg: type=user id=12986477
796
- </code></th>
797
- <td>
798
- <div class="sbi_row">
799
- <div class="sbi_col sbi_one">
800
- <input type="radio" name="sb_instagram_type" id="sb_instagram_type_user" value="user" <?php if($sb_instagram_type == "user") echo "checked"; ?> />
801
- <label class="sbi_radio_label" for="sb_instagram_type_user"><?php _e( 'User Account:', 'instagram-feed' ); ?></label>
802
- </div>
803
- <div class="sbi_col sbi_two">
804
- <div class="sbi_user_feed_ids_wrap">
805
- <?php foreach ( $user_feed_ids as $feed_id ) : if ( $feed_id !== '' ) :?>
806
- <?php if( count($connected_accounts) > 0 ) { ?><div id="sbi_user_feed_id_<?php echo $feed_id; ?>" class="sbi_user_feed_account_wrap"><?php } ?>
807
-
808
- <?php if ( isset( $connected_accounts[ $feed_id ] ) && ! empty( $connected_accounts[ $feed_id ]['username'] ) ) : ?>
809
- <strong><?php echo $connected_accounts[ $feed_id ]['username']; ?></strong> <span>(<?php echo $feed_id; ?>)</span>
810
- <input name="sb_instagram_user_id[]" id="sb_instagram_user_id" type="hidden" value="<?php echo esc_attr( $feed_id ); ?>" />
811
- <?php elseif ( isset( $connected_accounts[ $feed_id ] ) && ! empty( $connected_accounts[ $feed_id ]['access_token'] ) ) : ?>
812
- <strong><?php echo $feed_id; ?></strong>
813
- <input name="sb_instagram_user_id[]" id="sb_instagram_user_id" type="hidden" value="<?php echo esc_attr( $feed_id ); ?>" />
814
- <?php endif; ?>
815
-
816
- <?php if( count($connected_accounts) > 0 ) { ?></div><?php } ?>
817
- <?php endif; endforeach; ?>
818
- </div>
819
-
820
- <?php if ( empty( $user_feed_ids ) ) : ?>
821
- <p class="sbi_no_accounts" style="margin-top: -3px; margin-right: 10px;"><?php _e( 'Connect a user account above', 'instagram-feed' ); ?></p>
822
- <?php endif; ?>
823
-
824
- <a class="sbi_tooltip_link" href="JavaScript:void(0);" style="margin: 5px 0 10px 0; display: inline-block; height: 19px;"><?php _e("How to display User feeds", 'instagram-feed' ); ?></a>
825
- <div class="sbi_tooltip"><?php _e("<p><b>Displaying Posts from Your User Account</b><br />Simply connect an account using the button above.</p><p style='padding-top:8px;'><b>Displaying Posts from Other Instagram Accounts</b><br />Due to recent changes in the Instagram API it is no longer possible to display photos from other Instagram accounts which you do not have access to. You can only display the user feed of an account which you connect above. You can connect as many account as you like by logging in using the button above, or manually copy/pasting an Access Token by selecting the 'Manually Connect an Account' option.</p><p style='padding-top:10px;'><b>Multiple Acounts</b><br />It is only possible to display feeds from Instagram accounts which you own. In order to display feeds from multiple accounts, first connect them above and then use the buttons to add the account either to your primary feed or to another feed on your site.</p>", 'instagram-feed'); ?></div><br />
826
- </div>
827
-
828
- </div>
829
-
830
- <div class="sbi_pro sbi_row">
831
- <div class="sbi_col sbi_one">
832
- <input disabled type="radio" name="sb_instagram_type" id="sb_instagram_type_hashtag" value="hashtag" <?php if($sb_instagram_type == "hashtag") echo "checked"; ?> />
833
- <label class="sbi_radio_label" for="sb_instagram_type_hashtag"><?php _e( 'Hashtag:', 'instagram-feed' ); ?></label>
834
- </div>
835
- <div class="sbi_col sbi_two">
836
-
837
- <p class="sbi_pro_tooltip"><?php _e( 'Upgrade to the Pro version to display Hashtag and Tagged feeds', 'instagram-feed' ); ?><i class="fa fa-caret-down" aria-hidden="true"></i></p>
838
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi_lock"><i class="fa fa-rocket"></i><?php _e('Pro', 'instagram-feed'); ?></a>
839
-
840
- <input readonly type="text" size="25" style="height: 32px; top: -2px; position: relative; box-shadow: none;" disabled />
841
- &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed' ); ?></a>
842
-
843
- <p class="sbi_tooltip"><?php _e( 'Display posts from a specific hashtag instead of from a user', 'instagram-feed' ); ?></p>
844
- </div>
845
- </div>
846
-
847
- <div class="sbi_pro sbi_row">
848
- <div class="sbi_col sbi_one">
849
- <input disabled type="radio" name="sb_instagram_type" id="sb_instagram_type_tagged" value="tagged" <?php if($sb_instagram_type == "tagged") echo "checked"; ?> />
850
- <label class="sbi_radio_label" for="sb_instagram_type_tagged"><?php _e( 'Tagged:', 'instagram-feed' ); ?></label>
851
- </div>
852
- <div class="sbi_col sbi_two">
853
- <input readonly type="text" size="25" style="height: 32px; top: -2px; position: relative; box-shadow: none;" disabled />
854
- &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed' ); ?></a>
855
-
856
- <p class="sbi_tooltip"><?php _e( 'Display posts that your account has been tagged in.', 'instagram-feed' ); ?></p>
857
- </div>
858
- </div>
859
-
860
- <div class="sbi_row sbi_pro">
861
- <br>
862
- <a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);" style="margin-left: 0;"><i class="fa fa-question-circle" aria-hidden="true" style="margin-right: 6px;"></i><?php _e('Combine multiple feed types into a single feed', 'instagram-feed'); ?></a>
863
- <p class="sbi_tooltip">
864
- <b><?php _e( 'Please note: this is only available in the <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Pro version</a>', 'instagram-feed' ); ?>.</b><br />
865
- <?php echo sprintf( __('To display multiple feed types in a single feed, use %s in your shortcode and then add each user name or hashtag of each feed into the shortcode, like so: %s. This will combine a user feed and a hashtag feed into the same feed.', 'instagram-feed'), 'type="mixed"', '<code>[instagram-feed type="mixed" user="smashballoon" hashtag="#awesomeplugins"]</code>' ); ?>
866
- </p>
867
- </div>
868
-
869
- </td>
870
- </tr>
871
-
872
- <tr>
873
- <th class="bump-left"><label for="sb_instagram_preserve_settings" class="bump-left"><?php _e("Preserve settings when plugin is removed", 'instagram-feed'); ?></label></th>
874
- <td>
875
- <input name="sb_instagram_preserve_settings" type="checkbox" id="sb_instagram_preserve_settings" <?php if($sb_instagram_preserve_settings == true) echo "checked"; ?> />
876
- <label for="sb_instagram_preserve_settings"><?php _e('Yes', 'instagram-feed'); ?></label>
877
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
878
- <p class="sbi_tooltip"><?php _e('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.', 'instagram-feed'); ?></p>
879
- </td>
880
- </tr>
881
-
882
-
883
- <tr valign="top" class="sbi_cron_cache_opts">
884
- <th scope="row"><?php _e( 'Check for new posts', 'instagram-feed' ); ?></th>
885
- <td>
886
-
887
- <div class="sbi_row">
888
- <input type="radio" name="sbi_caching_type" id="sbi_caching_type_page" value="page" <?php if ( $sbi_caching_type === 'page' ) echo 'checked'; ?>>
889
- <label for="sbi_caching_type_page"><?php _e( 'When the page loads', 'instagram-feed' ); ?></label>
890
- <a class="sbi_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><i class="fa fa-question-circle" aria-hidden="true"></i></a>
891
- <p class="sbi_tooltip sbi-more-info"><?php _e( 'Your Instagram post 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', 'instagram-feed' ); ?>:<br><br>
892
- <?php _e( '<b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check Facebook for new posts the next time that the feed is loaded. You can choose how long this data should be cached for. 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.', 'instagram-feed' ); ?>
893
- <br><br>
894
- <?php _e( '<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.</p>', 'instagram-feed' ); ?>
895
- </div>
896
- <div class="sbi_row sbi-caching-page-options" style="display: none;">
897
- <?php _e( 'Every', 'instagram-feed' ); ?>:
898
- <input name="sb_instagram_cache_time" type="text" value="<?php echo esc_attr( $sb_instagram_cache_time ); ?>" size="4" />
899
- <select name="sb_instagram_cache_time_unit">
900
- <option value="minutes" <?php if($sb_instagram_cache_time_unit == "minutes") echo 'selected="selected"' ?> ><?php _e('Minutes', 'instagram-feed'); ?></option>
901
- <option value="hours" <?php if($sb_instagram_cache_time_unit == "hours") echo 'selected="selected"' ?> ><?php _e('Hours', 'instagram-feed'); ?></option>
902
- <option value="days" <?php if($sb_instagram_cache_time_unit == "days") echo 'selected="selected"' ?> ><?php _e('Days', 'instagram-feed'); ?></option>
903
- </select>
904
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
905
- <p class="sbi_tooltip"><?php _e('Your Instagram 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 Instagram for posts again.', 'instagram-feed'); ?></p>
906
- </div>
907
-
908
- <div class="sbi_row">
909
- <input type="radio" name="sbi_caching_type" id="sbi_caching_type_cron" value="background" <?php if ( $sbi_caching_type === 'background' ) echo 'checked'; ?>>
910
- <label for="sbi_caching_type_cron"><?php _e( 'In the background', 'instagram-feed' ); ?></label>
911
- </div>
912
- <div class="sbi_row sbi-caching-cron-options" style="display: block;">
913
-
914
- <select name="sbi_cache_cron_interval" id="sbi_cache_cron_interval">
915
- <option value="30mins" <?php if ( $sbi_cache_cron_interval === '30mins' ) echo 'selected'; ?>><?php _e( 'Every 30 minutes', 'instagram-feed' ); ?></option>
916
- <option value="1hour" <?php if ( $sbi_cache_cron_interval === '1hour' ) echo 'selected'; ?>><?php _e( 'Every hour', 'instagram-feed' ); ?></option>
917
- <option value="12hours" <?php if ( $sbi_cache_cron_interval === '12hours' ) echo 'selected'; ?>><?php _e( 'Every 12 hours', 'instagram-feed' ); ?></option>
918
- <option value="24hours" <?php if ( $sbi_cache_cron_interval === '24hours' ) echo 'selected'; ?>><?php _e( 'Every 24 hours', 'instagram-feed' ); ?></option>
919
- </select>
920
-
921
- <div id="sbi-caching-time-settings" style="display: none;">
922
- <?php _e('at' ); ?>
923
-
924
- <select name="sbi_cache_cron_time" style="width: 80px">
925
- <option value="1" <?php if ( $sbi_cache_cron_time === '1' ) echo 'selected'; ?>>1:00</option>
926
- <option value="2" <?php if ( $sbi_cache_cron_time === '2' ) echo 'selected'; ?>>2:00</option>
927
- <option value="3" <?php if ( $sbi_cache_cron_time === '3' ) echo 'selected'; ?>>3:00</option>
928
- <option value="4" <?php if ( $sbi_cache_cron_time === '4' ) echo 'selected'; ?>>4:00</option>
929
- <option value="5" <?php if ( $sbi_cache_cron_time === '5' ) echo 'selected'; ?>>5:00</option>
930
- <option value="6" <?php if ( $sbi_cache_cron_time === '6' ) echo 'selected'; ?>>6:00</option>
931
- <option value="7" <?php if ( $sbi_cache_cron_time === '7' ) echo 'selected'; ?>>7:00</option>
932
- <option value="8" <?php if ( $sbi_cache_cron_time === '8' ) echo 'selected'; ?>>8:00</option>
933
- <option value="9" <?php if ( $sbi_cache_cron_time === '9' ) echo 'selected'; ?>>9:00</option>
934
- <option value="10" <?php if ( $sbi_cache_cron_time === '10' ) echo 'selected'; ?>>10:00</option>
935
- <option value="11" <?php if ( $sbi_cache_cron_time === '11' ) echo 'selected'; ?>>11:00</option>
936
- <option value="0" <?php if ( $sbi_cache_cron_time === '0' ) echo 'selected'; ?>>12:00</option>
937
- </select>
938
-
939
- <select name="sbi_cache_cron_am_pm" style="width: 50px">
940
- <option value="am" <?php if ( $sbi_cache_cron_am_pm === 'am' ) echo 'selected'; ?>>AM</option>
941
- <option value="pm" <?php if ( $sbi_cache_cron_am_pm === 'pm' ) echo 'selected'; ?>>PM</option>
942
- </select>
943
- </div>
944
-
945
- <?php
946
- if ( wp_next_scheduled( 'sbi_feed_update' ) ) {
947
- $time_format = get_option( 'time_format' );
948
- if ( ! $time_format ) {
949
- $time_format = 'g:i a';
950
- }
951
- //
952
- $schedule = wp_get_schedule( 'sbi_feed_update' );
953
- if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', 'instagram-feed' );
954
- if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', 'instagram-feed' );
955
- $sbi_next_cron_event = wp_next_scheduled( 'sbi_feed_update' );
956
- echo '<p class="sbi-caching-sched-notice"><span><b>' . __( 'Next check', 'instagram-feed' ) . ': ' . date( $time_format, $sbi_next_cron_event + sbi_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', 'instagram-feed' ) . '</span></p>';
957
- } else {
958
- echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', 'instagram-feed' ) . '</p>';
959
- }
960
- ?>
961
-
962
- </div>
963
-
964
- </td>
965
- </tr>
966
-
967
- </tbody>
968
- </table>
969
-
970
- <?php submit_button(); ?>
971
- </form>
972
-
973
- <p><i class="fa fa-chevron-circle-right" aria-hidden="true"></i>&nbsp; <?php _e('Next Step: <a href="?page=sb-instagram-feed&tab=customize">Customize your Feed</a>', 'instagram-feed'); ?></p>
974
-
975
- <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
976
-
977
-
978
- <?php } // End Configure tab ?>
979
-
980
-
981
-
982
- <?php if( $sbi_active_tab == 'customize' ) { //Start Configure tab ?>
983
-
984
- <p class="sb_instagram_contents_links" id="general">
985
- <span><?php _e( 'Quick links:', 'instagram-feed' ); ?> </span>
986
- <a href="#general"><?php _e( 'General', 'instagram-feed' ); ?></a>
987
- <a href="#layout"><?php _e( 'Layout', 'instagram-feed' ); ?></a>
988
- <a href="#photos"><?php _e( 'Photos', 'instagram-feed' ); ?></a>
989
- <a href="#headeroptions"><?php _e( 'Header', 'instagram-feed' ); ?></a>
990
- <a href="#loadmore"><?php _e( "'Load More' Button", 'instagram-feed' ); ?></a>
991
- <a href="#follow"><?php _e( "'Follow' Button", 'instagram-feed' ); ?></a>
992
- <a href="#customcss"><?php _e( 'Custom CSS', 'instagram-feed' ); ?></a>
993
- <a href="#customjs"><?php _e( 'Custom JavaScript', 'instagram-feed' ); ?></a>
994
- </p>
995
-
996
- <input type="hidden" name="<?php echo $sb_instagram_customize_hidden_field; ?>" value="Y">
997
-
998
- <h3><?php _e( 'General', 'instagram-feed' ); ?></h3>
999
-
1000
- <table class="form-table">
1001
- <tbody>
1002
- <tr valign="top">
1003
- <th scope="row"><label><?php _e('Width of Feed', 'instagram-feed'); ?></label><code class="sbi_shortcode"> width widthunit
1004
- Eg: width=50 widthunit=%</code></th>
1005
- <td>
1006
- <input name="sb_instagram_width" type="text" value="<?php echo esc_attr( $sb_instagram_width ); ?>" id="sb_instagram_width" size="4" maxlength="4" />
1007
- <select name="sb_instagram_width_unit" id="sb_instagram_width_unit">
1008
- <option value="px" <?php if($sb_instagram_width_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1009
- <option value="%" <?php if($sb_instagram_width_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1010
- </select>
1011
- <div id="sb_instagram_width_options">
1012
- <input name="sb_instagram_feed_width_resp" type="checkbox" id="sb_instagram_feed_width_resp" <?php if($sb_instagram_feed_width_resp == true) echo "checked"; ?> /><label for="sb_instagram_feed_width_resp"><?php _e('Set to be 100% width on mobile?', 'instagram-feed'); ?></label>
1013
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does this mean?', 'instagram-feed' ); ?></a>
1014
- <p class="sbi_tooltip"><?php _e("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.", 'instagram-feed'); ?></p>
1015
- </div>
1016
- </td>
1017
- </tr>
1018
- <tr valign="top">
1019
- <th scope="row"><label><?php _e('Height of Feed', 'instagram-feed'); ?></label><code class="sbi_shortcode"> height heightunit
1020
- Eg: height=500 heightunit=px</code></th>
1021
- <td>
1022
- <input name="sb_instagram_height" type="text" value="<?php echo esc_attr( $sb_instagram_height ); ?>" size="4" maxlength="4" />
1023
- <select name="sb_instagram_height_unit">
1024
- <option value="px" <?php if($sb_instagram_height_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1025
- <option value="%" <?php if($sb_instagram_height_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1026
- </select>
1027
- </td>
1028
- </tr>
1029
- <tr valign="top">
1030
- <th scope="row"><label><?php _e('Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> background
1031
- Eg: background=d89531</code></th>
1032
- <td>
1033
- <input name="sb_instagram_background" type="text" value="<?php echo esc_attr( $sb_instagram_background ); ?>" class="sbi_colorpick" />
1034
- </td>
1035
- </tr>
1036
- </tbody>
1037
- </table>
1038
-
1039
- <hr id="layout" />
1040
- <h3><?php _e('Layout', 'instagram-feed'); ?></h3>
1041
-
1042
- <table class="form-table">
1043
- <tbody>
1044
- <?php
1045
- $selected_type = isset( $sb_instagram_layout_type ) ? $sb_instagram_layout_type : 'grid';
1046
- $layout_types = array(
1047
- 'grid' => __( 'Grid', 'instagram-feed' ),
1048
- 'carousel' => __( 'Carousel', 'instagram-feed' ),
1049
- 'masonry' => __( 'Masonry', 'instagram-feed' ),
1050
- 'highlight' => __( 'Highlight', 'instagram-feed' )
1051
- );
1052
- $layout_images = array(
1053
- 'grid' => SBI_PLUGIN_URL . 'img/grid.png',
1054
- 'carousel' => SBI_PLUGIN_URL . 'img/carousel.png',
1055
- 'masonry' => SBI_PLUGIN_URL . 'img/masonry.png',
1056
- 'highlight' => SBI_PLUGIN_URL . 'img/highlight.png'
1057
- );
1058
- ?>
1059
- <tr valign="top">
1060
- <th scope="row" class="sbi_pro"><label title="<?php _e('Click for shortcode option', 'instagram-feed'); ?>"><?php _e('Layout Type', 'instagram-feed'); ?></label><br /><span class="sbi_note" style="margin: 5px 0 0 0; font-weight: normal;"><?php _e('Select a layout to see associated<br />options', 'instagram-feed'); ?></span></th>
1061
- <td>
1062
- <div class="sbi_layouts">
1063
- <?php foreach( $layout_types as $layout_type => $label ) : ?>
1064
- <div class="sbi_layout_cell sbi_pro">
1065
- <input class="sb_layout_type" id="sb_layout_type_<?php echo esc_attr( $layout_type ); ?>" name="sb_instagram_layout_type" type="radio" value="<?php echo esc_attr( $layout_type ); ?>" <?php if ( $selected_type === $layout_type ) echo 'checked'; ?>/><label for="sb_layout_type_<?php echo esc_attr( $layout_type ); ?>"><span class="sbi_label"><?php echo esc_html( $label ); ?></span><img src="<?php echo esc_url( $layout_images[ $layout_type ] ); ?>" /></label>
1066
- </div>
1067
- <?php endforeach; ?>
1068
-
1069
- <p class="sbi_pro_tooltip"><?php _e('Upgrade to the Pro version to unlock these layouts', 'instagram-feed'); ?><i class="fa fa-caret-down" aria-hidden="true"></i></p>
1070
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi_lock"><i class="fa fa-rocket"></i><?php _e('Pro', 'instagram-feed'); ?></a>
1071
-
1072
- </div>
1073
- <div class="sb_layout_options_wrap sbi_pro">
1074
- <a href="JavaScript:void(0);" class="sbi_close_options"><i class="fa fa-close"></i></a>
1075
- <div class="sb_instagram_layout_settings sbi_layout_type_grid">
1076
- <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('A uniform grid of square-cropped images.', 'instagram-feed'); ?></span>
1077
- </div>
1078
- <div class="sb_instagram_layout_settings sbi_layout_type_masonry">
1079
- <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Images in their original aspect ratios with no vertical space between posts.', 'instagram-feed'); ?></span>
1080
- </div>
1081
- <div class="sb_instagram_layout_settings sbi_layout_type_carousel">
1082
- <div class="sb_instagram_layout_setting">
1083
- <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Posts are displayed in a slideshow carousel.', 'instagram-feed'); ?></span>
1084
- </div>
1085
- <div class="sb_instagram_layout_setting">
1086
-
1087
- <label><?php _e('Number of Rows', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselrows
1088
- Eg: carouselrows=2</code>
1089
- <br>
1090
- <span class="sbi_note" style="margin: -5px 0 -10px 0; display: block;"><?php _e('Use the "Number of Columns" setting below this section to set how many posts are visible in the carousel at a given time.', 'instagram-feed'); ?></span>
1091
- <br>
1092
- <select name="sb_instagram_carousel_rows" id="sb_instagram_carousel_rows">
1093
- <option value="1">1</option>
1094
- <option value="2" selected="selected">2</option>
1095
- </select>
1096
- </div>
1097
- <div class="sb_instagram_layout_setting">
1098
- <label><?php _e('Loop Type', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselloop
1099
- Eg: carouselloop=rewind
1100
- carouselloop=infinity</code>
1101
- <br>
1102
- <select name="sb_instagram_carousel_loop" id="sb_instagram_carousel_loop">
1103
- <option value="rewind"><?php _e('Rewind', 'instagram-feed'); ?></option>
1104
- <option value="infinity" selected="selected"><?php _e('Infinity', 'instagram-feed'); ?></option>
1105
- </select>
1106
- </div>
1107
- <div class="sb_instagram_layout_setting">
1108
- <input type="checkbox" name="sb_instagram_carousel_arrows" id="sb_instagram_carousel_arrows" checked="checked">
1109
- <label><?php _e('Show Navigation Arrows', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselarrows
1110
- Eg: carouselarrows=true</code>
1111
- </div>
1112
- <div class="sb_instagram_layout_setting">
1113
- <input type="checkbox" name="sb_instagram_carousel_pag" id="sb_instagram_carousel_pag">
1114
- <label><?php _e('Show Pagination', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselpag
1115
- Eg: carouselpag=true</code>
1116
- </div>
1117
- <div class="sb_instagram_layout_setting">
1118
- <input type="checkbox" name="sb_instagram_carousel_autoplay" id="sb_instagram_carousel_autoplay">
1119
- <label><?php _e('Enable Autoplay', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselautoplay
1120
- Eg: carouselautoplay=true</code>
1121
- </div>
1122
- <div class="sb_instagram_layout_setting">
1123
- <label><?php _e('Interval Time', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouseltime
1124
- Eg: carouseltime=8000</code>
1125
- <br>
1126
- <input name="sb_instagram_carousel_interval" type="text" value="5000" size="6"><?php _e("miliseconds", 'instagram-feed'); ?>
1127
- </div>
1128
- </div>
1129
-
1130
- <div class="sb_instagram_layout_settings sbi_layout_type_highlight">
1131
- <div class="sb_instagram_layout_setting">
1132
- <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Masonry style, square-cropped, image only (no captions or likes/comments below image). "Highlighted" posts are twice as large.', 'instagram-feed'); ?></span>
1133
- </div>
1134
- <div class="sb_instagram_layout_setting">
1135
- <label title="Click for shortcode option"><?php _e('Highlighting Type', 'instagram-feed'); ?></label><code class="sbi_shortcode"> highlighttype
1136
- Eg: highlighttype=pattern</code>
1137
- <br>
1138
- <select name="sb_instagram_highlight_type" id="sb_instagram_highlight_type">
1139
- <option value="pattern" selected="selected"><?php _e('Pattern', 'instagram-feed'); ?></option>
1140
- <option value="id"><?php _e('Post ID', 'instagram-feed'); ?></option>
1141
- <option value="hashtag"><?php _e('Hashtag', 'instagram-feed'); ?></option>
1142
- </select>
1143
- </div>
1144
- <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_pattern sb_instagram_layout_setting" style="display: block;">
1145
- <label></label><code class="sbi_shortcode"> highlightoffset
1146
- Eg: highlightoffset=2</code>
1147
- <br>
1148
- <input name="sb_instagram_highlight_offset" type="number" min="0" value="0" style="width: 50px;">
1149
- </div>
1150
- <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_pattern sb_instagram_layout_setting" style="display: block;">
1151
- <label><?php _e('Pattern', 'instagram-feed'); ?></label><code class="sbi_shortcode"> highlightpattern
1152
- Eg: highlightpattern=3</code>
1153
- <br>
1154
- <span><?php _e('Highlight every', 'instagram-feed'); ?></span><input name="sb_instagram_highlight_factor" type="number" min="2" value="6" style="width: 50px;"><span><?php _e('posts', 'instagram-feed'); ?></span>
1155
- </div>
1156
- <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_hashtag sb_instagram_layout_setting" style="display: none;">
1157
- <label><?php _e('Highlight Posts with these Hashtags', 'instagram-feed'); ?></label>
1158
- <input name="sb_instagram_highlight_hashtag" id="sb_instagram_highlight_hashtag" type="text" size="40" value="#fishing">&nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What is this?', 'instagram-feed'); ?></a>
1159
- <br>
1160
- <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate multiple hashtags using commas', 'instagram-feed'); ?></span>
1161
-
1162
-
1163
- <p class="sbi_tooltip"><?php _e('You can use this setting to highlight posts by a hashtag. Use a specified hashtag in your posts and they will be automatically highlighted in your feed.', 'instagram-feed'); ?></p>
1164
- </div>
1165
- <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_ids sb_instagram_layout_setting" style="display: none;">
1166
- <label><?php _e('Highlight Posts by ID', 'instagram-feed'); ?></label>
1167
- <textarea name="sb_instagram_highlight_ids" id="sb_instagram_highlight_ids" style="width: 100%;" rows="3">sbi_1852317219231323590_3269008872</textarea>
1168
- <br>
1169
- <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate IDs using commas', 'instagram-feed'); ?></span>
1170
-
1171
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What is this?', 'instagram-feed'); ?></a>
1172
- <p class="sbi_tooltip"><?php _e('You can use this setting to highlight posts by their ID. Enable and use "moderation mode", check the box to show post IDs underneath posts, then copy and paste IDs into this text box.', 'instagram-feed'); ?></p>
1173
- </div>
1174
- </div>
1175
-
1176
- </div>
1177
- </td>
1178
- </tr>
1179
- <tr valign="top">
1180
- <th scope="row"><label><?php _e('Number of Photos', 'instagram-feed'); ?></label><code class="sbi_shortcode"> num
1181
- Eg: num=6</code></th>
1182
- <td>
1183
- <input name="sb_instagram_num" type="text" value="<?php echo esc_attr( $sb_instagram_num ); ?>" size="4" maxlength="4" />
1184
- <span class="sbi_note"><?php _e('Number of photos to show initially.', 'instagram-feed'); ?></span>
1185
- </td>
1186
- </tr>
1187
- <tr valign="top">
1188
- <th scope="row"><label><?php _e('Number of Columns', 'instagram-feed'); ?></label><code class="sbi_shortcode"> cols
1189
- Eg: cols=3</code></th>
1190
- <td>
1191
- <select name="sb_instagram_cols">
1192
- <option value="1" <?php if($sb_instagram_cols == "1") echo 'selected="selected"' ?> ><?php _e('1', 'instagram-feed'); ?></option>
1193
- <option value="2" <?php if($sb_instagram_cols == "2") echo 'selected="selected"' ?> ><?php _e('2', 'instagram-feed'); ?></option>
1194
- <option value="3" <?php if($sb_instagram_cols == "3") echo 'selected="selected"' ?> ><?php _e('3', 'instagram-feed'); ?></option>
1195
- <option value="4" <?php if($sb_instagram_cols == "4") echo 'selected="selected"' ?> ><?php _e('4', 'instagram-feed'); ?></option>
1196
- <option value="5" <?php if($sb_instagram_cols == "5") echo 'selected="selected"' ?> ><?php _e('5', 'instagram-feed'); ?></option>
1197
- <option value="6" <?php if($sb_instagram_cols == "6") echo 'selected="selected"' ?> ><?php _e('6', 'instagram-feed'); ?></option>
1198
- <option value="7" <?php if($sb_instagram_cols == "7") echo 'selected="selected"' ?> ><?php _e('7', 'instagram-feed'); ?></option>
1199
- <option value="8" <?php if($sb_instagram_cols == "8") echo 'selected="selected"' ?> ><?php _e('8', 'instagram-feed'); ?></option>
1200
- <option value="9" <?php if($sb_instagram_cols == "9") echo 'selected="selected"' ?> ><?php _e('9', 'instagram-feed'); ?></option>
1201
- <option value="10" <?php if($sb_instagram_cols == "10") echo 'selected="selected"' ?> ><?php _e('10', 'instagram-feed'); ?></option>
1202
- </select>
1203
- </td>
1204
- </tr>
1205
- <tr valign="top">
1206
- <th scope="row"><label><?php _e('Padding around Images', 'instagram-feed'); ?></label><code class="sbi_shortcode"> imagepadding imagepaddingunit</code></th>
1207
- <td>
1208
- <input name="sb_instagram_image_padding" type="text" value="<?php echo esc_attr( $sb_instagram_image_padding ); ?>" size="4" maxlength="4" />
1209
- <select name="sb_instagram_image_padding_unit">
1210
- <option value="px" <?php if($sb_instagram_image_padding_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1211
- <option value="%" <?php if($sb_instagram_image_padding_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1212
- </select>
1213
- </td>
1214
- </tr>
1215
- <tr valign="top">
1216
- <th scope="row"><label><?php _e("Disable mobile layout", 'instagram-feed'); ?></label><code class="sbi_shortcode"> disablemobile
1217
- Eg: disablemobile=true</code></th>
1218
- <td>
1219
- <input type="checkbox" name="sb_instagram_disable_mobile" id="sb_instagram_disable_mobile" <?php if($sb_instagram_disable_mobile == true) echo 'checked="checked"' ?> />
1220
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does this mean?', 'instagram-feed' ); ?></a>
1221
- <p class="sbi_tooltip"><?php _e("By default on mobile devices the layout automatically changes to use fewer columns. Checking this setting disables the mobile layout.", 'instagram-feed'); ?></p>
1222
- </td>
1223
- </tr>
1224
- </tbody>
1225
- </table>
1226
-
1227
- <?php submit_button(); ?>
1228
-
1229
- <hr id="photos" />
1230
- <h3><?php _e('Photos', 'instagram-feed'); ?></h3>
1231
-
1232
- <table class="form-table">
1233
- <tbody>
1234
- <tr valign="top">
1235
- <th scope="row"><label><?php _e('Sort Photos By', 'instagram-feed'); ?></label><code class="sbi_shortcode"> sortby
1236
- Eg: sortby=random</code></th>
1237
- <td>
1238
- <select name="sb_instagram_sort">
1239
- <option value="none" <?php if($sb_instagram_sort == "none") echo 'selected="selected"' ?> ><?php _e('Newest to oldest', 'instagram-feed'); ?></option>
1240
- <option value="random" <?php if($sb_instagram_sort == "random") echo 'selected="selected"' ?> ><?php _e('Random', 'instagram-feed'); ?></option>
1241
- </select>
1242
- </td>
1243
- </tr>
1244
- <tr valign="top">
1245
- <th scope="row"><label><?php _e('Image Resolution', 'instagram-feed'); ?></label><code class="sbi_shortcode"> imageres
1246
- Eg: imageres=thumb</code></th>
1247
- <td>
1248
-
1249
- <select name="sb_instagram_image_res">
1250
- <option value="auto" <?php if($sb_instagram_image_res == "auto") echo 'selected="selected"' ?> ><?php _e('Auto-detect (recommended)', 'instagram-feed'); ?></option>
1251
- <option value="thumb" <?php if($sb_instagram_image_res == "thumb") echo 'selected="selected"' ?> ><?php _e('Thumbnail (150x150)', 'instagram-feed'); ?></option>
1252
- <option value="medium" <?php if($sb_instagram_image_res == "medium") echo 'selected="selected"' ?> ><?php _e('Medium (320x320)', 'instagram-feed'); ?></option>
1253
- <option value="full" <?php if($sb_instagram_image_res == "full") echo 'selected="selected"' ?> ><?php _e('Full size (640x640)', 'instagram-feed'); ?></option>
1254
- </select>
1255
-
1256
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does Auto-detect mean?', 'instagram-feed'); ?></a>
1257
- <p class="sbi_tooltip"><?php _e("Auto-detect means that the plugin automatically sets the image resolution based on the size of your feed.", 'instagram-feed'); ?></p>
1258
-
1259
- </td>
1260
- </tr>
1261
- </tbody>
1262
- </table>
1263
-
1264
- <span><a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a></span>
1265
-
1266
- <div class="sbi-pro-options">
1267
- <p class="sbi-upgrade-link">
1268
- <i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable these settings', 'instagram-feed'); ?></a>
1269
- </p>
1270
- <table class="form-table">
1271
- <tbody>
1272
- <tr valign="top" class="sbi_pro">
1273
- <th scope="row"><label><?php _e('Media Type to Display','instagram-feed'); ?></label></th>
1274
- <td>
1275
- <select name="sb_instagram_media_type" disabled>
1276
- <option value="all"><?php _e('All','instagram-feed'); ?></option>
1277
- <option value="photos"><?php _e('Photos only','instagram-feed'); ?></option>
1278
- <option value="videos"><?php _e('Videos only','instagram-feed'); ?></option>
1279
- </select>
1280
- </td>
1281
- </tr>
1282
-
1283
- <tr valign="top" class="sbi_pro">
1284
- <th scope="row"><label><?php _e("Enable Pop-up Lightbox", 'instagram-feed'); ?></label></th>
1285
- <td>
1286
- <input type="checkbox" name="sb_instagram_captionlinks" id="sb_instagram_captionlinks" disabled />
1287
- </td>
1288
- </tr>
1289
-
1290
- <tr valign="top" class="sbi_pro">
1291
- <th scope="row"><label><?php _e("Link Posts to URL in Caption (Shoppable feed)",'instagram-feed'); ?></label></th>
1292
- <td>
1293
- <input type="checkbox" name="sb_instagram_captionlinks" id="sb_instagram_captionlinks" disabled />
1294
- &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e("What will this do?",'instagram-feed'); ?></a>
1295
- <p class="sbi_tooltip"><?php _e("Checking this box will change the link for each post to any url included in the caption for that Instagram post. The lightbox will be disabled. Visit <a href='https://smashballoon.com/make-a-shoppable-feed?utm_source=plugin-free&utm_campaign=sbi'>this link</a> to learn how this works.",'instagram-feed'); ?></p>
1296
- </td>
1297
- </tr>
1298
- </tbody>
1299
- </table>
1300
- </div>
1301
-
1302
-
1303
- <hr />
1304
- <h3><?php _e('Photo Hover Style','instagram-feed'); ?></h3>
1305
-
1306
- <p style="padding-bottom: 18px;">
1307
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Photo Hover styles','instagram-feed'); ?></a><br />
1308
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options','instagram-feed'); ?></a>
1309
- </p>
1310
-
1311
- <div class="sbi-pro-options" style="margin-top: -15px;">
1312
- <table class="form-table">
1313
- <tbody>
1314
- <tr valign="top" class="sbi_pro">
1315
- <th scope="row"><label><?php _e('Hover Background Color', 'instagram-feed'); ?></label></th>
1316
- <td>
1317
- <input name="sb_hover_background" type="text" disabled class="sbi_colorpick" />
1318
- </td>
1319
- </tr>
1320
- <tr valign="top" class="sbi_pro">
1321
- <th scope="row"><label><?php _e('Hover Text Color', 'instagram-feed'); ?></label></th>
1322
- <td>
1323
- <input name="sb_hover_text" type="text" disabled class="sbi_colorpick" />
1324
- </td>
1325
- </tr>
1326
- <tr valign="top" class="sbi_pro">
1327
- <th scope="row"><label><?php _e('Information to display', 'instagram-feed'); ?></label></th>
1328
- <td>
1329
- <div>
1330
- <input name="sbi_hover_inc_username" type="checkbox" disabled />
1331
- <label for="sbi_hover_inc_username"><?php _e('Username', 'instagram-feed'); ?></label>
1332
- </div>
1333
- <div>
1334
- <input name="sbi_hover_inc_icon" type="checkbox" disabled />
1335
- <label for="sbi_hover_inc_icon"><?php _e('Expand Icon', 'instagram-feed'); ?></label>
1336
- </div>
1337
- <div>
1338
- <input name="sbi_hover_inc_date" type="checkbox" disabled />
1339
- <label for="sbi_hover_inc_date"><?php _e('Date', 'instagram-feed'); ?></label>
1340
- </div>
1341
- <div>
1342
- <input name="sbi_hover_inc_instagram" type="checkbox" disabled />
1343
- <label for="sbi_hover_inc_instagram"><?php _e('Instagram Icon/Link', 'instagram-feed'); ?></label>
1344
- </div>
1345
- <div>
1346
- <input name="sbi_hover_inc_location" type="checkbox" disabled />
1347
- <label for="sbi_hover_inc_location"><?php _e('Location', 'instagram-feed'); ?></label>
1348
- </div>
1349
- <div>
1350
- <input name="sbi_hover_inc_caption" type="checkbox" disabled />
1351
- <label for="sbi_hover_inc_caption"><?php _e('Caption', 'instagram-feed'); ?></label>
1352
- </div>
1353
- <div>
1354
- <input name="sbi_hover_inc_likes" type="checkbox" disabled />
1355
- <label for="sbi_hover_inc_likes"><?php _e('Like/Comment Icons', 'instagram-feed'); ?></label>
1356
- </div>
1357
- </td>
1358
- </tr>
1359
-
1360
- </tbody>
1361
- </table>
1362
- </div>
1363
-
1364
-
1365
- <hr />
1366
- <h3><?php _e( 'Carousel', 'instagram-feed' ); ?></h3>
1367
- <p style="padding-bottom: 18px;">
1368
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Carousels', 'instagram-feed'); ?></a><br />
1369
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1370
- </p>
1371
-
1372
- <div class="sbi-pro-options" style="margin-top: -15px;">
1373
- <table class="form-table">
1374
- <tbody>
1375
- <tr valign="top" class="sbi_pro">
1376
- <th scope="row"><label><?php _e("Enable Carousel", 'instagram-feed'); ?></label></th>
1377
- <td>
1378
- <input type="checkbox" disabled />
1379
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1380
- <p class="sbi_tooltip"><?php _e("Enable this setting to create a carousel slider out of your photos.", 'instagram-feed'); ?></p>
1381
- </td>
1382
- </tr>
1383
- <tr valign="top" class="sbi_pro">
1384
- <th scope="row"><label><?php _e("Show Navigation Arrows", 'instagram-feed'); ?></label></th>
1385
- <td>
1386
- <input type="checkbox" disabled />
1387
- </td>
1388
- </tr>
1389
- <tr valign="top" class="sbi_pro">
1390
- <th scope="row"><label><?php _e("Show Pagination", 'instagram-feed'); ?></label></th>
1391
- <td>
1392
- <input type="checkbox" disabled />
1393
- </td>
1394
- </tr>
1395
- <tr valign="top" class="sbi_pro">
1396
- <th scope="row"><label><?php _e("Enable Autoplay", 'instagram-feed'); ?></label></th>
1397
- <td>
1398
- <input type="checkbox" disabled />
1399
- </td>
1400
- </tr>
1401
- <tr valign="top" class="sbi_pro">
1402
- <th scope="row"><label><?php _e("Interval Time", 'instagram-feed'); ?></label></th>
1403
- <td>
1404
- <input name="sb_instagram_carousel_interval" type="text" disabled size="6" /><?php _e("milliseconds", 'instagram-feed'); ?>
1405
- </td>
1406
- </tr>
1407
- </tbody>
1408
- </table>
1409
- </div>
1410
-
1411
-
1412
-
1413
- <hr id="headeroptions" />
1414
- <h3><?php _e("Header", 'instagram-feed'); ?></h3>
1415
- <table class="form-table">
1416
- <tbody>
1417
- <tr valign="top">
1418
- <th scope="row"><label><?php _e("Show Feed Header", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showheader
1419
- Eg: showheader=false</code></th>
1420
- <td>
1421
- <input type="checkbox" name="sb_instagram_show_header" id="sb_instagram_show_header" <?php if($sb_instagram_show_header == true) echo 'checked="checked"' ?> />
1422
- </td>
1423
- </tr>
1424
- <tr valign="top">
1425
- <th scope="row"><label><?php _e('Header Size', 'instagram-feed'); ?></label><code class="sbi_shortcode"> headersize
1426
- Eg: headersize=medium</code></th>
1427
- <td>
1428
- <select name="sb_instagram_header_size" id="sb_instagram_header_size" style="float: left;">
1429
- <option value="small" <?php if($sb_instagram_header_size == "small") echo 'selected="selected"' ?> ><?php _e('Small', 'instagram-feed'); ?></option>
1430
- <option value="medium" <?php if($sb_instagram_header_size == "medium") echo 'selected="selected"' ?> ><?php _e('Medium', 'instagram-feed'); ?></option>
1431
- <option value="large" <?php if($sb_instagram_header_size == "large") echo 'selected="selected"' ?> ><?php _e('Large', 'instagram-feed'); ?></option>
1432
- </select>
1433
- </td>
1434
- </tr>
1435
- <tr valign="top">
1436
- <th scope="row"><label><?php _e("Show Bio Text", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showbio
1437
- Eg: showbio=false</code></th>
1438
- <td>
1439
- <?php $sb_instagram_show_bio = isset( $sb_instagram_show_bio ) ? $sb_instagram_show_bio : true; ?>
1440
- <input type="checkbox" name="sb_instagram_show_bio" id="sb_instagram_show_bio" <?php if($sb_instagram_show_bio == true) echo 'checked="checked"' ?> />
1441
- <span class="sbi_note"><?php _e("Only applies for Instagram accounts with bios", 'instagram-feed'); ?></span>
1442
- <div class="sb_instagram_box" style="display: block;">
1443
- <div class="sb_instagram_box_setting" style="display: block;">
1444
- <label style="padding-bottom: 0;"><?php _e("Add Custom Bio Text", 'instagram-feed'); ?></label><code class="sbi_shortcode" style="margin-top: 5px;"> custombio
1445
- Eg: custombio="My custom bio."</code>
1446
- <br>
1447
- <span class="sbi_aside" style="padding-bottom: 5px; display: block;"><?php _e("Use your own custom bio text in the feed header. Bio text is automatically retrieved from Instagram for Business accounts.", 'instagram-feed'); ?></span>
1448
-
1449
- <textarea type="text" name="sb_instagram_custom_bio" id="sb_instagram_custom_bio" ><?php echo esc_textarea( stripslashes( $sb_instagram_custom_bio ) ); ?></textarea>
1450
- &nbsp;<a class="sbi_tooltip_link sbi_tooltip_under" href="JavaScript:void(0);"><?php _e("Why is my bio not displaying automatically?", 'instagram-feed'); ?></a>
1451
- <p class="sbi_tooltip" style="padding: 10px 0 0 0; width: 99%;"><?php echo sprintf( __("Instagram is deprecating their old API for Personal accounts on March 31, 2020. The plugin supports their new API, however, their new API does not yet include the bio text for Personal accounts. If you require this feature then it is available if you convert your Instagram account from a Personal to a Business account by following %s. Note: If you previously had a Personal account connected then the plugin has saved the avatar for that feed and will continue to use it automatically.", 'instagram-feed'), '<a href="https://smashballoon.com/instagram-business-profiles/" target="_blank">these directions</a>' ); ?></p>
1452
- </div>
1453
- </div>
1454
-
1455
- </td>
1456
- </tr>
1457
-
1458
- <tr valign="top">
1459
- <th scope="row"><label><?php _e("Use Custom Avatar", 'instagram-feed'); ?></label><code class="sbi_shortcode"> customavatar
1460
- Eg: customavatar="https://my-website.com/avatar.jpg"</code></th>
1461
- <td>
1462
- <input type="text" name="sb_instagram_custom_avatar" class="large-text" id="sb_instagram_custom_avatar" value="<?php echo esc_attr( stripslashes( $sb_instagram_custom_avatar ) ); ?>" placeholder="https://example.com/avatar.jpg" />
1463
- <span class="sbi_aside"><?php _e("Avatar is automatically retrieved from Instagram for Business accounts", 'instagram-feed'); ?></span>
1464
- <br>
1465
- <a class="sbi_tooltip_link sbi_tooltip_under" href="JavaScript:void(0);"><?php _e("Why is my avatar not displaying automatically?", 'instagram-feed'); ?></a>
1466
-
1467
- <p class="sbi_tooltip sbi_tooltip_under_text" style="padding: 10px 0 0 0;"><?php echo sprintf( __("Instagram is deprecating their old API for Personal accounts on March 31, 2020. The plugin supports their new API, however, their new API does not yet include the avatar image for Personal accounts. If you require this feature then it is available if you convert your Instagram account from a Personal to a Business account by following %s. Note: If you previously had a Personal account connected then the plugin has saved the bio text for that feed and will continue to use it automatically.", 'instagram-feed'), '<a href="https://smashballoon.com/instagram-business-profiles/" target="_blank">these directions</a>' ); ?></p>
1468
-
1469
- </td>
1470
- </tr>
1471
- <tr valign="top">
1472
- <th scope="row"><label><?php _e('Header Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> headercolor
1473
- Eg: headercolor=fff</code></th>
1474
- <td>
1475
- <input name="sb_instagram_header_color" type="text" value="<?php echo esc_attr( $sb_instagram_header_color ); ?>" class="sbi_colorpick" />
1476
- </td>
1477
- </tr>
1478
- </tbody>
1479
- </table>
1480
-
1481
- <span><a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a></span>
1482
-
1483
- <div class="sbi-pro-options">
1484
- <p class="sbi-upgrade-link">
1485
- <i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable these settings', 'instagram-feed'); ?></a>
1486
- </p>
1487
- <table class="form-table">
1488
- <tbody>
1489
- <tr valign="top" class="sbi_pro">
1490
- <th scope="row"><label><?php _e('Header Style','instagram-feed'); ?></label></th>
1491
- <td>
1492
- <select name="sb_instagram_header_style" style="float: left;">
1493
- <option value="circle"><?php _e('Standard','instagram-feed'); ?></option>
1494
- <option value="boxed"><?php _e('Boxed','instagram-feed'); ?></option>
1495
- <option value="centered"><?php _e('Centered','instagram-feed'); ?></option>
1496
- </select>
1497
- </td>
1498
- </tr>
1499
- <tr valign="top" class="sbi_pro">
1500
- <th scope="row"><label><?php _e("Show Number of Followers",'instagram-feed'); ?></label></th>
1501
- <td>
1502
- <input type="checkbox" disabled />
1503
- <span class="sbi_note"><?php _e("This only applies when displaying photos from a User ID",'instagram-feed'); ?></span>
1504
- </td>
1505
- </tr>
1506
- </tbody>
1507
- </table>
1508
- </div>
1509
-
1510
- <?php submit_button(); ?>
1511
-
1512
-
1513
- <hr />
1514
- <h3><?php _e("Caption", 'instagram-feed'); ?></h3>
1515
- <p style="padding-bottom: 18px;">
1516
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e("Upgrade to Pro to enable Photo Captions", 'instagram-feed'); ?></a><br />
1517
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e("Show Pro Options", 'instagram-feed'); ?></a>
1518
- </p>
1519
-
1520
- <div class="sbi-pro-options" style="margin-top: -15px;">
1521
- <table class="form-table">
1522
- <tbody>
1523
- <tr valign="top" class="sbi_pro">
1524
- <th scope="row"><label><?php _e("Show Caption", 'instagram-feed'); ?></label></th>
1525
- <td>
1526
- <input type="checkbox" disabled />
1527
- </td>
1528
- </tr>
1529
- <tr valign="top" class="sbi_pro">
1530
- <th scope="row"><label><?php _e("Maximum Text Length", 'instagram-feed'); ?></label></th>
1531
- <td>
1532
- <input disabled size="4" />Characters
1533
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1534
- <p class="sbi_tooltip"><?php _e("The number of characters of text to display in the caption. An elipsis link will be added to allow the user to reveal more text if desired.", 'instagram-feed'); ?></p>
1535
- </td>
1536
- </tr>
1537
- <tr valign="top" class="sbi_pro">
1538
- <th scope="row"><label><?php _e('Text Color', 'instagram-feed'); ?></label></th>
1539
- <td>
1540
- <input type="text" disabled class="sbi_colorpick" />
1541
- </td>
1542
- </tr>
1543
- <tr valign="top" class="sbi_pro">
1544
- <th scope="row"><label><?php _e('Text Size', 'instagram-feed'); ?></label></th>
1545
- <td>
1546
- <select name="sb_instagram_caption_size" style="width: 180px;" disabled>
1547
- <option value="inherit" ><?php _e('Inherit from theme', 'instagram-feed'); ?></option>
1548
- <option value="10" >10px</option>
1549
- <option value="11" >11px</option>
1550
- <option value="12" >12px</option>
1551
- <option value="13" >13px</option>
1552
- <option value="14" >14px</option>
1553
- <option value="16" >16px</option>
1554
- <option value="18" >18px</option>
1555
- <option value="20" >20px</option>
1556
- <option value="24" >24px</option>
1557
- <option value="28" >28px</option>
1558
- <option value="32" >32px</option>
1559
- <option value="36" >36px</option>
1560
- <option value="40" >40px</option>
1561
- </select>
1562
- </td>
1563
- </tr>
1564
- </tbody>
1565
- </table>
1566
- </div>
1567
-
1568
-
1569
- <hr />
1570
- <h3><?php _e("Likes &amp; Comments", 'instagram-feed'); ?></h3>
1571
- <p style="padding-bottom: 18px;">
1572
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e("Upgrade to Pro to enable Likes &amp; Comments", 'instagram-feed'); ?></a><br />
1573
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e("Show Pro Options", 'instagram-feed'); ?></a>
1574
- </p>
1575
-
1576
- <div class="sbi-pro-options" style="margin-top: -15px;">
1577
- <table class="form-table">
1578
- <tbody>
1579
- <tr valign="top" class="sbi_pro">
1580
- <th scope="row"><label><?php _e("Show Icons", 'instagram-feed'); ?></label></th>
1581
- <td>
1582
- <input type="checkbox" disabled />
1583
- </td>
1584
- </tr>
1585
- <tr valign="top" class="sbi_pro">
1586
- <th scope="row"><label><?php _e('Icon Color', 'instagram-feed'); ?></label></th>
1587
- <td>
1588
- <input type="text" disabled class="sbi_colorpick" />
1589
- </td>
1590
- </tr>
1591
- <tr valign="top" class="sbi_pro">
1592
- <th scope="row"><label><?php _e('Icon Size', 'instagram-feed'); ?></label></th>
1593
- <td>
1594
- <select disabled name="sb_instagram_meta_size" style="width: 180px;">
1595
- <option value="inherit"><?php _e('Inherit from theme', 'instagram-feed'); ?></option>
1596
- <option value="10" >10px</option>
1597
- <option value="11" >11px</option>
1598
- <option value="12" >12px</option>
1599
- <option value="13" >13px</option>
1600
- <option value="14" >14px</option>
1601
- <option value="16" >16px</option>
1602
- <option value="18" >18px</option>
1603
- <option value="20" >20px</option>
1604
- <option value="24" >24px</option>
1605
- <option value="28" >28px</option>
1606
- <option value="32" >32px</option>
1607
- <option value="36" >36px</option>
1608
- <option value="40" >40px</option>
1609
- </select>
1610
- </td>
1611
- </tr>
1612
- </tbody>
1613
- </table>
1614
- </div>
1615
-
1616
-
1617
- <hr />
1618
- <h3><?php _e('Lightbox Comments', 'instagram-feed'); ?></h3>
1619
-
1620
- <p style="padding-bottom: 18px;">
1621
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Comments', 'instagram-feed'); ?></a><br />
1622
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1623
- </p>
1624
-
1625
- <div class="sbi-pro-options" style="margin-top: -15px;">
1626
- <table class="form-table">
1627
- <tbody>
1628
-
1629
- <tr valign="top" class="sbi_pro">
1630
- <th scope="row"><label><?php _e('Show Comments in Lightbox', 'instagram-feed'); ?></label></th>
1631
- <td style="padding: 5px 10px 0 10px;">
1632
- <input type="checkbox" disabled style="margin-right: 15px;" />
1633
- <input class="button-secondary" style="margin-top: -5px;" disabled value="<?php echo esc_attr( 'Clear Comment Cache', 'instagram-feed' ); ?>" />
1634
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1635
- <p class="sbi_tooltip"><?php _e("This will remove the cached comments saved in the database", 'instagram-feed'); ?></p>
1636
- </td>
1637
- </tr>
1638
- <tr valign="top" class="sbi_pro">
1639
- <th scope="row"><label><?php _e('Number of Comments', 'instagram-feed'); ?></label></th>
1640
- <td>
1641
- <input name="sb_instagram_num_comments" type="text" disabled size="4" />
1642
- <span class="sbi_note"><?php _e('Max number of latest comments.', 'instagram-feed'); ?></span>
1643
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1644
- <p class="sbi_tooltip"><?php _e("This is the maximum number of comments that will be shown in the lightbox. If there are more comments available than the number set, only the latest comments will be shown", 'instagram-feed'); ?></p>
1645
- </td>
1646
- </tr>
1647
-
1648
- </tbody>
1649
- </table>
1650
- </div>
1651
-
1652
-
1653
- <hr id="loadmore" />
1654
- <h3><?php _e("'Load More' Button", 'instagram-feed'); ?></h3>
1655
- <table class="form-table">
1656
- <tbody>
1657
- <tr valign="top">
1658
- <th scope="row"><label><?php _e("Show the 'Load More' button", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showbutton
1659
- Eg: showbutton=false</code></th>
1660
- <td>
1661
- <input type="checkbox" name="sb_instagram_show_btn" id="sb_instagram_show_btn" <?php if($sb_instagram_show_btn == true) echo 'checked="checked"' ?> />
1662
- </td>
1663
- </tr>
1664
- <tr valign="top">
1665
- <th scope="row"><label><?php _e('Button Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttoncolor
1666
- Eg: buttoncolor=8224e3</code></th>
1667
- <td>
1668
- <input name="sb_instagram_btn_background" type="text" value="<?php echo esc_attr( $sb_instagram_btn_background ); ?>" class="sbi_colorpick" />
1669
- </td>
1670
- </tr>
1671
- <tr valign="top">
1672
- <th scope="row"><label><?php _e('Button Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttontextcolor
1673
- Eg: buttontextcolor=eeee22</code></th>
1674
- <td>
1675
- <input name="sb_instagram_btn_text_color" type="text" value="<?php echo esc_attr( $sb_instagram_btn_text_color ); ?>" class="sbi_colorpick" />
1676
- </td>
1677
- </tr>
1678
- <tr valign="top">
1679
- <th scope="row"><label><?php _e('Button Text', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttontext
1680
- Eg: buttontext="Show more.."</code></th>
1681
- <td>
1682
- <input name="sb_instagram_btn_text" type="text" value="<?php echo esc_attr( stripslashes( $sb_instagram_btn_text ) ); ?>" size="20" />
1683
- </td>
1684
- </tr>
1685
- </tbody>
1686
- </table>
1687
-
1688
- <?php submit_button(); ?>
1689
-
1690
- <hr id="follow" />
1691
- <h3><?php _e("'Follow' Button", 'instagram-feed'); ?></h3>
1692
- <table class="form-table">
1693
- <tbody>
1694
- <tr valign="top">
1695
- <th scope="row"><label><?php _e("Show the Follow button", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showfollow
1696
- Eg: showfollow=true</code></th>
1697
- <td>
1698
- <input type="checkbox" name="sb_instagram_show_follow_btn" id="sb_instagram_show_follow_btn" <?php if($sb_instagram_show_follow_btn == true) echo 'checked="checked"' ?> />
1699
- </td>
1700
- </tr>
1701
-
1702
- <tr valign="top">
1703
- <th scope="row"><label><?php _e('Button Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followcolor
1704
- Eg: followcolor=28a1bf</code></th>
1705
- <td>
1706
- <input name="sb_instagram_folow_btn_background" type="text" value="<?php echo esc_attr( $sb_instagram_folow_btn_background ); ?>" class="sbi_colorpick" />
1707
- </td>
1708
- </tr>
1709
- <tr valign="top">
1710
- <th scope="row"><label><?php _e('Button Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followtextcolor
1711
- Eg: followtextcolor=000</code></th>
1712
- <td>
1713
- <input name="sb_instagram_follow_btn_text_color" type="text" value="<?php echo esc_attr( $sb_instagram_follow_btn_text_color ); ?>" class="sbi_colorpick" />
1714
- </td>
1715
- </tr>
1716
- <tr valign="top">
1717
- <th scope="row"><label><?php _e('Button Text', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followtext
1718
- Eg: followtext="Follow me"</code></th>
1719
- <td>
1720
- <input name="sb_instagram_follow_btn_text" type="text" value="<?php echo esc_attr( stripslashes( $sb_instagram_follow_btn_text ) ); ?>" size="30" />
1721
- </td>
1722
- </tr>
1723
- </tbody>
1724
- </table>
1725
-
1726
- <hr id="filtering" />
1727
- <h3><?php _e('Post Filtering', 'instagram-feed'); ?></h3>
1728
-
1729
- <p style="padding-bottom: 18px;">
1730
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Post Filtering options', 'instagram-feed'); ?></a><br />
1731
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1732
- </p>
1733
-
1734
- <div class="sbi-pro-options" style="margin-top: -15px;">
1735
-
1736
- <table class="form-table">
1737
- <tbody>
1738
- <tr valign="top" class="sbi_pro">
1739
- <th scope="row"><label><?php _e('Remove photos containing these words or hashtags', 'instagram-feed'); ?></label></th>
1740
- <td>
1741
- <div class="sb_instagram_apply_labels">
1742
- <p><?php _e('Apply to:', 'instagram-feed'); ?></p>
1743
- <input class="sb_instagram_incex_one_all" type="radio" value="all" disabled /><label><?php _e('All feeds', 'instagram-feed'); ?></label>
1744
- <input class="sb_instagram_incex_one_all" type="radio" value="one" disabled /><label><?php _e('One feed', 'instagram-feed'); ?></label>
1745
- </div>
1746
-
1747
- <input disabled name="sb_instagram_exclude_words" id="sb_instagram_exclude_words" type="text" style="width: 70%;" value="" />
1748
- <br />
1749
- <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate words/hashtags using commas', 'instagram-feed'); ?></span>
1750
- &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed'); ?></a>
1751
- <p class="sbi_tooltip"><?php _e("You can use this setting to remove photos which contain certain words or hashtags in the caption. Separate multiple words or hashtags using commas.", 'instagram-feed'); ?></p>
1752
- </td>
1753
- </tr>
1754
-
1755
- <tr valign="top" class="sbi_pro">
1756
- <th scope="row"><label><?php _e('Show photos containing these words or hashtags', 'instagram-feed'); ?></label></th>
1757
- <td>
1758
- <div class="sb_instagram_apply_labels">
1759
- <p><?php _e('Apply to:', 'instagram-feed'); ?></p>
1760
- <input class="sb_instagram_incex_one_all" type="radio" value="all" disabled /><label><?php _e('All feeds', 'instagram-feed'); ?></label>
1761
- <input class="sb_instagram_incex_one_all" type="radio" value="one" disabled /><label><?php _e('One feed', 'instagram-feed'); ?></label>
1762
- </div>
1763
-
1764
- <input disabled name="sb_instagram_include_words" id="sb_instagram_include_words" type="text" style="width: 70%;" value="" />
1765
- <br />
1766
- <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate words/hashtags using commas', 'instagram-feed'); ?></span>
1767
- &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed'); ?></a>
1768
- <p class="sbi_tooltip"><?php _e("You can use this setting to only show photos which contain certain words or hashtags in the caption. For example, adding <code>sheep, cow, dog</code> will show any photos which contain either the word sheep, cow, or dog. Separate multiple words or hashtags using commas.", 'instagram-feed'); ?></p>
1769
- </td>
1770
- </tr>
1771
- </tbody>
1772
- </table>
1773
- </div>
1774
-
1775
-
1776
- <hr id="moderation" />
1777
- <h3><?php _e('Moderation', 'instagram-feed'); ?></h3>
1778
-
1779
- <p style="padding-bottom: 18px;">
1780
- <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Moderation options', 'instagram-feed'); ?></a><br />
1781
- <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1782
- </p>
1783
-
1784
- <div class="sbi-pro-options" style="margin-top: -15px;">
1785
- <table class="form-table">
1786
- <tbody>
1787
- <tr valign="top" class="sbi_pro">
1788
- <th scope="row"><label><?php _e('Moderation Type', 'instagram-feed'); ?></label></th>
1789
- <td>
1790
- <input class="sb_instagram_moderation_mode" checked="checked" disabled type="radio" value="visual" style="margin-top: 0;" /><label><?php _e('Visual', 'instagram-feed'); ?></label>
1791
- <input class="sb_instagram_moderation_mode" disabled type="radio" value="manual" style="margin-top: 0; margin-left: 10px;"/><label><?php _e('Manual', 'instagram-feed'); ?></label>
1792
-
1793
- <p class="sbi_tooltip" style="display: block;"><?php _e("<b>Visual Moderation Mode</b><br />This adds a button to each feed that will allow you to hide posts, block users, and create white lists from the front end using a visual interface. Visit <a href='https://smashballoon.com/guide-to-moderation-mode/?utm_source=plugin-free&utm_campaign=sbi' target='_blank'>this page</a> for details", 'instagram-feed'); ?></p>
1794
-
1795
- </td>
1796
- </tr>
1797
-
1798
- <tr valign="top" class="sbi_pro">
1799
- <th scope="row"><label><?php _e('Only show posts by these users', 'instagram-feed'); ?></label></th>
1800
- <td>
1801
- <input type="text" style="width: 70%;" disabled /><br />
1802
- <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate usernames using commas', 'instagram-feed'); ?></span>
1803
-
1804
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1805
- <p class="sbi_tooltip"><?php _e("You can use this setting to show photos only from certain users in your feed. Just enter the usernames here which you want to show. Separate multiple usernames using commas.", 'instagram-feed'); ?></p>
1806
- </td>
1807
- </tr>
1808
- <tr valign="top" class="sbi_pro">
1809
- <th scope="row"><label><?php _e('White lists', 'instagram-feed'); ?></label></th>
1810
- <td>
1811
- <div class="sbi_white_list_names_wrapper">
1812
- <?php _e("No white lists currently created", 'instagram-feed'); ?>
1813
- </div>
1814
-
1815
- <input disabled class="button-secondary" type="submit" value="<?php esc_attr_e( 'Clear White Lists', 'instagram-feed' ); ?>" />
1816
- &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);" style="display: inline-block; margin-top: 5px;"><?php _e("What is this?", 'instagram-feed'); ?></a>
1817
- <p class="sbi_tooltip"><?php _e("This will remove all of the white lists from the database", 'instagram-feed'); ?></p>
1818
- </td>
1819
- </tr>
1820
-
1821
- </tbody>
1822
- </table>
1823
- </div>
1824
-
1825
-
1826
-
1827
- <hr id="customcss" />
1828
- <h3><?php _e('Misc', 'instagram-feed'); ?></h3>
1829
-
1830
- <table class="form-table">
1831
- <tbody>
1832
- <tr valign="top">
1833
- <td style="padding-bottom: 0;">
1834
- <?php _e('<strong style="font-size: 15px;">Custom CSS</strong><br />Enter your own custom CSS in the box below', 'instagram-feed'); ?>
1835
- </td>
1836
- </tr>
1837
- <tr valign="top">
1838
- <td>
1839
- <textarea name="sb_instagram_custom_css" id="sb_instagram_custom_css" style="width: 70%;" rows="7"><?php echo esc_textarea( stripslashes($sb_instagram_custom_css), 'instagram-feed' ); ?></textarea>
1840
- </td>
1841
- </tr>
1842
- <tr valign="top" id="customjs">
1843
- <td style="padding-bottom: 0;">
1844
- <?php _e('<strong style="font-size: 15px;">Custom JavaScript</strong><br />Enter your own custom JavaScript/jQuery in the box below', 'instagram-feed'); ?>
1845
- </td>
1846
- </tr>
1847
- <tr valign="top">
1848
- <td>
1849
- <textarea name="sb_instagram_custom_js" id="sb_instagram_custom_js" style="width: 70%;" rows="7"><?php echo esc_textarea( stripslashes($sb_instagram_custom_js), 'instagram-feed' ); ?></textarea>
1850
- </td>
1851
- </tr>
1852
- </tbody>
1853
- </table>
1854
- <table class="form-table">
1855
- <tbody>
1856
-
1857
- <tr valign="top">
1858
- <th scope="row"><label for="sb_instagram_ajax_theme" class="bump-left"><?php _e("Are you using an Ajax powered theme?", 'instagram-feed'); ?></label></th>
1859
- <td>
1860
- <input name="sb_instagram_ajax_theme" type="checkbox" id="sb_instagram_ajax_theme" <?php if($sb_instagram_ajax_theme == true) echo "checked"; ?> />
1861
- <label for="sb_instagram_ajax_theme"><?php _e('Yes', 'instagram-feed'); ?></label>
1862
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1863
- <p class="sbi_tooltip"><?php _e("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 please check with the theme author.", 'instagram-feed'); ?></p>
1864
- </td>
1865
- </tr>
1866
-
1867
- <tr>
1868
- <th class="bump-left"><label class="bump-left"><?php _e("Image Resizing", 'instagram-feed'); ?></label></th>
1869
- <td>
1870
- <input name="sb_instagram_disable_resize" type="checkbox" id="sb_instagram_disable_resize" <?php if($sb_instagram_disable_resize == true) echo "checked"; ?> />
1871
- <label for="sb_instagram_disable_resize"><?php _e('Disable Local Image Storing and Resizing', 'instagram-feed'); ?></label><br><br>
1872
- <input name="sb_instagram_favor_local" type="checkbox" id="sb_instagram_favor_local" <?php if($sb_instagram_favor_local == true) echo "checked"; ?> />
1873
- <label for="sb_instagram_favor_local"><?php _e('Favor Local Images', 'instagram-feed'); ?></label><br><br>
1874
-
1875
- <input id="sbi_reset_resized" class="button-secondary" type="submit" value="<?php esc_attr_e( 'Reset Resized Images' ); ?>" style="vertical-align: middle;"/>
1876
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1877
- <p class="sbi_tooltip"><?php _e("The plugin creates and stores resized versions of images in order to serve a more optimized resolution size in the feed. Click this button to clear all data related to resized images. Enable the setting to favor local images to always use a local, resized image if one is available.", 'instagram-feed'); ?></p>
1878
- </td>
1879
- </tr>
1880
-
1881
- <tr valign="top">
1882
- <th scope="row"><label><?php _e('API request size', 'instagram-feed'); ?></label><code class="sbi_shortcode"> minnum
1883
- Eg: minnum=25</code></th>
1884
- <td>
1885
- <input name="sb_instagram_minnum" type="number" min="0" max="100" value="<?php echo esc_attr( $sb_instagram_minnum ); ?>" />
1886
- <span class="sbi_note"><?php _e('Leave at "0" for default', 'instagram-feed'); ?></span>
1887
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1888
- <p class="sbi_tooltip"><?php _e("If your feed contains a lot of IG TV posts or your feed is not displaying any posts despite there being posts available on Instagram.com, try increasing this number to 25 or more.", 'instagram-feed'); ?></p>
1889
- </td>
1890
- </tr>
1891
-
1892
- <tr valign="top">
1893
- <th scope="row"><label><?php _e('Enqueue JS file in head', 'instagram-feed'); ?></label></th>
1894
- <td>
1895
- <input type="checkbox" name="enqueue_js_in_head" id="sb_instagram_enqueue_js_in_head" <?php if($enqueue_js_in_head == true) echo 'checked="checked"' ?> />
1896
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1897
- <p class="sbi_tooltip"><?php _e("Check this box if you'd like to enqueue the JavaScript file for the plugin in the head instead of the footer.", 'instagram-feed'); ?></p>
1898
- </td>
1899
- </tr>
1900
-
1901
- <tr valign="top">
1902
- <th scope="row"><label><?php _e('Enqueue CSS file with shortcode', 'instagram-feed'); ?></label></th>
1903
- <td>
1904
- <input type="checkbox" name="enqueue_css_in_shortcode" id="sb_instagram_enqueue_css_in_shortcode" <?php if($enqueue_css_in_shortcode == true) echo 'checked="checked"' ?> />
1905
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1906
- <p class="sbi_tooltip"><?php _e("Check this box if you'd like to only include the CSS file for the plugin when the feed is on the page.", 'instagram-feed'); ?></p>
1907
- </td>
1908
- </tr>
1909
-
1910
- <tr valign="top">
1911
- <th scope="row"><label><?php _e('Disable JS Image Loading', 'instagram-feed'); ?></label></th>
1912
- <td>
1913
- <input type="checkbox" name="disable_js_image_loading" id="sb_instagram_disable_js_image_loading" <?php if($disable_js_image_loading == true) echo 'checked="checked"' ?> />
1914
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1915
- <p class="sbi_tooltip"><?php _e("Check this box to have images loaded server side instead of with JS.", 'instagram-feed'); ?></p>
1916
- </td>
1917
- </tr>
1918
-
1919
- <tr valign="top">
1920
- <th><label><?php _e("Enable Backup Caching", 'instagram-feed'); ?></label></th>
1921
- <td class="sbi-customize-tab-opt">
1922
- <input name="sb_instagram_backup" type="checkbox" id="sb_instagram_backup" <?php if($sb_instagram_backup == true) echo "checked"; ?> />
1923
- <input id="sbi_clear_backups" class="button-secondary" type="submit" style="position: relative; top: -4px;" value="<?php esc_attr_e( 'Clear Backup Cache', 'instagram-feed' ); ?>" />
1924
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1925
- <p class="sbi_tooltip"><?php _e('Every feed will save a duplicate version of itself in the database to be used if the normal cache is not available.', 'instagram-feed'); ?></p>
1926
- </td>
1927
- </tr>
1928
-
1929
- <tr>
1930
- <th class="bump-left">
1931
- <label class="bump-left"><?php _e("Load initial posts with AJAX", 'instagram-feed'); ?></label>
1932
- </th>
1933
- <td>
1934
- <input name="sb_ajax_initial" type="checkbox" id="sb_ajax_initial" <?php if($sb_ajax_initial == true) echo "checked"; ?> />
1935
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1936
- <p class="sbi_tooltip"><?php _e("Initial posts will be loaded using AJAX instead of added to the page directly. If you use page caching, this will allow the feed to update according to the \"Check for new posts every\" setting on the \"Configure\" tab.", 'instagram-feed'); ?></p>
1937
- </td>
1938
- </tr>
1939
-
1940
- <tr>
1941
- <th class="bump-left">
1942
- <label for="sb_instagram_cron" class="bump-left"><?php _e("Force cache to clear on interval", 'instagram-feed'); ?></label>
1943
- </th>
1944
- <td>
1945
- <select name="sb_instagram_cron">
1946
- <option value="unset" <?php if($sb_instagram_cron == "unset") echo 'selected="selected"' ?> > - </option>
1947
- <option value="yes" <?php if($sb_instagram_cron == "yes") echo 'selected="selected"' ?> ><?php _e('Yes', 'instagram-feed'); ?></option>
1948
- <option value="no" <?php if($sb_instagram_cron == "no") echo 'selected="selected"' ?> ><?php _e('No', 'instagram-feed'); ?></option>
1949
- </select>
1950
-
1951
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1952
- <p class="sbi_tooltip"><?php _e("If you're experiencing an issue with the plugin not auto-updating then you can set this to 'Yes' to run a scheduled event behind the scenes which forces the plugin cache to clear on a regular basis and retrieve new data from Instagram.", 'instagram-feed'); ?></p>
1953
- </td>
1954
- </tr>
1955
- </tbody>
1956
- </table>
1957
- <table class="form-table">
1958
- <tbody>
1959
- <tr valign="top">
1960
- <th scope="row"><label><?php _e("Disable Icon Font", 'instagram-feed'); ?></label></th>
1961
- <td>
1962
- <input type="checkbox" name="sb_instagram_disable_awesome" id="sb_instagram_disable_awesome" <?php if($sb_instagram_disable_awesome == true) echo 'checked="checked"' ?> /> <?php _e( 'Yes', 'instagram-feed' ); ?>
1963
- </td>
1964
- </tr>
1965
- <tr>
1966
- <th scope="row"><label for="sbi_font_method"><?php _e("Icon Method", 'instagram-feed'); ?></label></th>
1967
- <td>
1968
- <select name="sbi_font_method" id="sbi_font_method" class="default-text">
1969
- <option value="svg" id="sbi-font_method" class="default-text" <?php if($sbi_font_method == 'svg') echo 'selected="selected"' ?>>SVG</option>
1970
- <option value="fontfile" id="sbi-font_method" class="default-text" <?php if($sbi_font_method == 'fontfile') echo 'selected="selected"' ?>><?php _e("Font File", 'instagram-feed'); ?></option>
1971
- </select>
1972
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1973
- <p class="sbi_tooltip"><?php _e("This plugin uses SVGs for all icons in the feed. Use this setting to switch to font icons.", 'instagram-feed'); ?></p>
1974
- </td>
1975
- </tr>
1976
- <tr>
1977
- <th class="bump-left"><label class="bump-left"><?php _e("Enable Custom Templates", 'instagram-feed'); ?></label></th>
1978
- <td>
1979
- <input name="sb_instagram_custom_template" type="checkbox" id="sb_instagram_custom_template" <?php if($sb_instagram_custom_template == true) echo "checked"; ?> />
1980
- <label for="sb_instagram_custom_template"><?php _e('Yes', 'instagram-feed'); ?></label>
1981
- <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1982
- <p class="sbi_tooltip"><?php _e("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/guide-to-creating-custom-templates/\" target=\"_blank\">this guide</a>", 'instagram-feed'); ?></p>
1983
- </td>
1984
- </tr>
1985
- </tbody>
1986
- </table>
1987
-
1988
- <?php submit_button(); ?>
1989
-
1990
- </form>
1991
-
1992
- <p><i class="fa fa-chevron-circle-right" aria-hidden="true"></i>&nbsp; <?php _e('Next Step: <a href="?page=sb-instagram-feed&tab=display">Display your Feed</a>', 'instagram-feed'); ?></p>
1993
-
1994
- <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
1995
-
1996
-
1997
- <?php } //End Customize tab ?>
1998
-
1999
-
2000
-
2001
- <?php if( $sbi_active_tab == 'display' ) { //Start Display tab ?>
2002
-
2003
- <h3><?php _e('Display your Feed', 'instagram-feed'); ?></h3>
2004
- <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:", 'instagram-feed'); ?></p>
2005
- <input type="text" value="[instagram-feed]" size="16" 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).', 'instagram-feed'); ?>" />
2006
-
2007
- <h3 style="padding-top: 10px;"><?php _e( 'Multiple Feeds', 'instagram-feed' ); ?></h3>
2008
- <p><?php _e("If you'd like to display multiple feeds then you can set different settings directly in the shortcode like so:", 'instagram-feed'); ?>
2009
- <code>[instagram-feed num=9 cols=3]</code></p>
2010
- <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:', 'instagram-feed' ); ?><br />
2011
- <code>[instagram-feed]</code><br />
2012
- <code>[instagram-feed num=4 cols=4 showfollow=false]</code><br />
2013
- <code>[instagram-feed accesstoken="ANOTHER_ACCESS_TOKEN"]</code>
2014
- </p>
2015
- <p><?php _e("See the table below for a full list of available shortcode options:", 'instagram-feed'); ?></p>
2016
-
2017
- <p><span class="sbi_table_key"></span><?php _e('Pro version only', 'instagram-feed'); ?></p>
2018
-
2019
- <table class="sbi_shortcode_table">
2020
- <tbody>
2021
- <tr valign="top">
2022
- <th scope="row"><?php _e('Shortcode option', 'instagram-feed'); ?></th>
2023
- <th scope="row"><?php _e('Description', 'instagram-feed'); ?></th>
2024
- <th scope="row"><?php _e('Example', 'instagram-feed'); ?></th>
2025
- </tr>
2026
-
2027
- <tr class="sbi_table_header"><td colspan=3><?php _e("Configure Options", 'instagram-feed'); ?></td></tr>
2028
- <tr class="sbi_pro">
2029
- <td>type</td>
2030
- <td><?php _e("Display photos from a User ID (user)<br />Display posts from a Hashtag (hashtag)", 'instagram-feed'); ?><br /><?php _e("Display photos that the account was tagged in (tagged)", 'instagram-feed'); ?></td>
2031
- <td><code>[instagram-feed type=user]</code><br /><code>[instagram-feed type=hashtag]</code><br /><code>[instagram-feed type=tagged]</code></td>
2032
- </tr>
2033
- <tr>
2034
- <td>user</td>
2035
- <td><?php _e('Your Instagram User Name. This must be from a connected account on the "Configure" tab.', 'instagram-feed'); ?></td>
2036
- <td><code>[instagram-feed user="smashballoon"]</code></td>
2037
- </tr>
2038
- <tr class="sbi_pro">
2039
- <td>hashtag</td>
2040
- <td><?php _e('Any hashtag. Separate multiple hashtags by commas.', 'instagram-feed'); ?></td>
2041
- <td><code>[instagram-feed hashtag="#awesome"]</code></td>
2042
- </tr>
2043
- <tr class="sbi_pro">
2044
- <td>tagged</td>
2045
- <td><?php _e('Your Instagram User Name. Separate multiple users by commas.', 'instagram-feed'); ?></td>
2046
- <td><code>[instagram-feed tagged="smashballoon"]</code></td>
2047
- </tr>
2048
-
2049
- <tr class="sbi_table_header"><td colspan=3><?php _e("Customize Options", 'instagram-feed'); ?></td></tr>
2050
- <tr>
2051
- <td>width</td>
2052
- <td><?php _e("The width of your feed. Any number.", 'instagram-feed'); ?></td>
2053
- <td><code>[instagram-feed width=50]</code></td>
2054
- </tr>
2055
- <tr>
2056
- <td>widthunit</td>
2057
- <td><?php _e("The unit of the width. 'px' or '%'", 'instagram-feed'); ?></td>
2058
- <td><code>[instagram-feed widthunit=%]</code></td>
2059
- </tr>
2060
- <tr>
2061
- <td>height</td>
2062
- <td><?php _e("The height of your feed. Any number.", 'instagram-feed'); ?></td>
2063
- <td><code>[instagram-feed height=250]</code></td>
2064
- </tr>
2065
- <tr>
2066
- <td>heightunit</td>
2067
- <td><?php _e("The unit of the height. 'px' or '%'", 'instagram-feed'); ?></td>
2068
- <td><code>[instagram-feed heightunit=px]</code></td>
2069
- </tr>
2070
- <tr>
2071
- <td>background</td>
2072
- <td><?php _e("The background color of the feed. Any hex color code.", 'instagram-feed'); ?></td>
2073
- <td><code>[instagram-feed background=#ffff00]</code></td>
2074
- </tr>
2075
- <tr>
2076
- <td>class</td>
2077
- <td><?php _e("Add a CSS class to the feed container", 'instagram-feed'); ?></td>
2078
- <td><code>[instagram-feed class=feedOne]</code></td>
2079
- </tr>
2080
-
2081
- <tr class="sbi_table_header"><td colspan=3><?php _e("Layout Options", 'instagram-feed'); ?></td></tr>
2082
- <tr class="sbi_pro">
2083
- <td>layout</td>
2084
- <td><?php _e("How posts are arranged visually in the feed. There are four layouts: Grid, Carousel Slider, Masonry Grid, or Highlight Grid. Options:", 'instagram-feed' ); ?> 'grid', 'carousel', 'masonry', or 'highlight'</td>
2085
- <td><code>[instagram-feed layout=grid]</code></td>
2086
- </tr>
2087
- <tr>
2088
- <td>num</td>
2089
- <td><?php _e("The number of photos to display initially. Maximum is 33.", 'instagram-feed'); ?></td>
2090
- <td><code>[instagram-feed num=10]</code></td>
2091
- </tr>
2092
- <tr class="sbi_pro">
2093
- <td>nummobile</td>
2094
- <td><?php _e("The number of photos to display initially for mobile screens (smaller than 480 pixels).", 'instagram-feed'); ?></td>
2095
- <td><code>[instagram-feed nummobile=6]</code></td>
2096
- </tr>
2097
- <tr>
2098
- <td>cols</td>
2099
- <td><?php _e("The number of columns in your feed. 1 - 10.", 'instagram-feed'); ?></td>
2100
- <td><code>[instagram-feed cols=5]</code></td>
2101
- </tr>
2102
- <tr class="sbi_pro">
2103
- <td>colsmobile</td>
2104
- <td><?php _e("The number of columns in your feed for mobile screens (smaller than 480 pixels).", 'instagram-feed'); ?></td>
2105
- <td><code>[instagram-feed colsmobile=2]</code></td>
2106
- </tr>
2107
- <tr>
2108
- <td>imagepadding</td>
2109
- <td><?php _e("The spacing around your photos", 'instagram-feed'); ?></td>
2110
- <td><code>[instagram-feed imagepadding=10]</code></td>
2111
- </tr>
2112
- <tr>
2113
- <td>imagepaddingunit</td>
2114
- <td><?php _e("The unit of the padding. 'px' or '%'", 'instagram-feed'); ?></td>
2115
- <td><code>[instagram-feed imagepaddingunit=px]</code></td>
2116
- </tr>
2117
-
2118
- <tr class="sbi_table_header"><td colspan=3><?php _e("Carousel Options", 'instagram-feed'); ?></td></tr>
2119
- <tr class="sbi_pro">
2120
- <td>carouselrows</td>
2121
- <td><?php _e("Choose 1 or 2 rows of posts in the carousel", 'instagram-feed'); ?></td>
2122
- <td><code>[instagram-feed carouselrows=1]</code></td>
2123
- </tr>
2124
- <tr class="sbi_pro">
2125
- <td>carouselloop</td>
2126
- <td><?php _e("Infinitely loop through posts or rewind", 'instagram-feed'); ?></td>
2127
- <td><code>[instagram-feed carouselloop=rewind]</code></td>
2128
- </tr>
2129
- <tr class="sbi_pro">
2130
- <td>carouselarrows</td>
2131
- <td><?php _e("Display directional arrows on the carousel", 'instagram-feed'); ?></td>
2132
- <td><code>[instagram-feed carouselarrows=true]</code></td>
2133
- </tr>
2134
- <tr class="sbi_pro">
2135
- <td>carouselpag</td>
2136
- <td><?php _e("Display pagination links below the carousel", 'instagram-feed'); ?></td>
2137
- <td><code>[instagram-feed carouselpag=true]</code></td>
2138
- </tr>
2139
- <tr class="sbi_pro">
2140
- <td>carouselautoplay</td>
2141
- <td><?php _e("Make the carousel autoplay", 'instagram-feed'); ?></td>
2142
- <td><code>[instagram-feed carouselautoplay=true]</code></td>
2143
- </tr>
2144
- <tr class="sbi_pro">
2145
- <td>carouseltime</td>
2146
- <td><?php _e("The interval time between slides for autoplay. Time in miliseconds.", 'instagram-feed'); ?></td>
2147
- <td><code>[instagram-feed carouseltime=8000]</code></td>
2148
- </tr>
2149
-
2150
- <tr class="sbi_table_header"><td colspan=3><?php _e("Highlight Options", 'instagram-feed'); ?></td></tr>
2151
- <tr class="sbi_pro">
2152
- <td>highlighttype</td>
2153
- <td><?php _e("Choose from 3 different ways of highlighting posts including by pattern, hashtag, post id or. Options:", 'instagram-feed'); ?> 'pattern', 'hashtag', 'id'.</td>
2154
- <td><code>[instagram-feed highlighttype=hashtag]</code></td>
2155
- </tr>
2156
- <tr class="sbi_pro">
2157
- <td>highlightpattern</td>
2158
- <td><?php _e("How often a post is highlighted.", 'instagram-feed'); ?></td>
2159
- <td><code>[instagram-feed highlightpattern=7]</code></td>
2160
- </tr>
2161
- <tr class="sbi_pro">
2162
- <td>highlightoffset</td>
2163
- <td><?php _e("When to start the highlight pattern.", 'instagram-feed'); ?></td>
2164
- <td><code>[instagram-feed highlightoffset=3]</code></td>
2165
- </tr>
2166
- <tr class="sbi_pro">
2167
- <td>highlighthashtag</td>
2168
- <td><?php _e("Highlight posts with these hashtags.", 'instagram-feed'); ?></td>
2169
- <td><code>[instagram-feed highlighthashtag=best]</code></td>
2170
- </tr>
2171
-
2172
-
2173
-
2174
-
2175
-
2176
- <tr class="sbi_table_header"><td colspan=3><?php _e("Photos Options", 'instagram-feed'); ?></td></tr>
2177
- <tr>
2178
- <td>sortby</td>
2179
- <td><?php _e("Sort the posts by Newest to Oldest (none) or Random (random)", 'instagram-feed'); ?></td>
2180
- <td><code>[instagram-feed sortby=random]</code></td>
2181
- </tr>
2182
- <tr>
2183
- <td>imageres</td>
2184
- <td><?php _e("The resolution/size of the photos including full, medium, thumbnail, and auto (based on size of image on page). Options:", 'instagram-feed'); ?> 'auto', full', 'medium' or 'thumb'.</td>
2185
- <td><code>[instagram-feed imageres=full]</code></td>
2186
- </tr>
2187
- <tr class="sbi_pro">
2188
- <td>media</td>
2189
- <td><?php _e("Display all media, only photos, or only videos", 'instagram-feed'); ?></td>
2190
- <td><code>[instagram-feed media=photos]</code></td>
2191
- </tr>
2192
- <tr class="sbi_pro">
2193
- <td>disablelightbox</td>
2194
- <td><?php _e("Whether to disable the photo Lightbox. It is enabled by default.", 'instagram-feed'); ?></td>
2195
- <td><code>[instagram-feed disablelightbox=true]</code></td>
2196
- </tr>
2197
- <tr>
2198
- <td>disablemobile</td>
2199
- <td><?php _e("Disable the mobile layout. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2200
- <td><code>[instagram-feed disablemobile=true]</code></td>
2201
- </tr>
2202
- <tr class="sbi_pro">
2203
- <td>captionlinks</td>
2204
- <td><?php _e("Whether to use urls in captions for the photo's link instead of linking to instagram.com.", 'instagram-feed'); ?></td>
2205
- <td><code>[instagram-feed captionlinks=true]</code></td>
2206
- </tr>
2207
-
2208
- <tr class="sbi_table_header"><td colspan=3><?php _e("Lightbox Comments Options", 'instagram-feed'); ?></td></tr>
2209
- <tr class="sbi_pro">
2210
- <td>lightboxcomments</td>
2211
- <td><?php _e("Whether to show comments in the lightbox for this feed.", 'instagram-feed'); ?></td>
2212
- <td><code>[instagram-feed lightboxcomments=true]</code></td>
2213
- </tr>
2214
- <tr class="sbi_pro">
2215
- <td>numcomments</td>
2216
- <td><?php _e("Number of comments to show starting from the most recent.", 'instagram-feed'); ?></td>
2217
- <td><code>[instagram-feed numcomments=10]</code></td>
2218
- </tr>
2219
-
2220
- <tr class="sbi_table_header"><td colspan=3><?php _e("Photos Hover Style Options", 'instagram-feed'); ?></td></tr>
2221
- <tr class="sbi_pro">
2222
- <td>hovercolor</td>
2223
- <td><?php _e("The background color when hovering over a photo. Any hex color code.", 'instagram-feed'); ?></td>
2224
- <td><code>[instagram-feed hovercolor=#ff0000]</code></td>
2225
- </tr>
2226
- <tr class="sbi_pro">
2227
- <td>hovertextcolor</td>
2228
- <td><?php _e("The text/icon color when hovering over a photo. Any hex color code.", 'instagram-feed'); ?></td>
2229
- <td><code>[instagram-feed hovertextcolor=#fff]</code></td>
2230
- </tr>
2231
- <tr class="sbi_pro">
2232
- <td>hoverdisplay</td>
2233
- <td><?php _e("The info to display when hovering over the photo such as the user name, post date, Instagram icon, location, caption, and like counts. Options:", 'instagram-feed'); ?><br />username, date, instagram, location, caption, likes</td>
2234
- <td><code>[instagram-feed hoverdisplay="date, location, likes"]</code></td>
2235
- </tr>
2236
-
2237
- <tr class="sbi_table_header"><td colspan=3><?php _e("Header Options", 'instagram-feed'); ?></td></tr>
2238
- <tr>
2239
- <td>showheader</td>
2240
- <td><?php _e("Whether to show the feed Header. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2241
- <td><code>[instagram-feed showheader=false]</code></td>
2242
- </tr>
2243
- <tr>
2244
- <td>showbio</td>
2245
- <td><?php _e("Display the bio in the header. Options:", 'instagram-feed'); ?> 'true' or 'false'</td>
2246
- <td><code>[instagram-feed showbio=true]</code></td>
2247
- </tr>
2248
- <tr>
2249
- <td>custombio</td>
2250
- <td><?php _e("Display a custom bio in the header", 'instagram-feed'); ?></td>
2251
- <td><code>[instagram-feed custombio="My custom bio."]</code></td>
2252
- </tr>
2253
- <tr>
2254
- <td>customavatar</td>
2255
- <td><?php _e("Display a custom avatar in the header. Enter the full URL of an image file.", 'instagram-feed'); ?></td>
2256
- <td><code>[instagram-feed customavatar="https://example.com/avatar.jpg"]</code></td>
2257
- </tr>
2258
- <tr>
2259
- <td>headersize</td>
2260
- <td><?php _e("Size of the header including small, medium and large. Options:", 'instagram-feed'); ?> small, medium, or large.</td>
2261
- <td><code>[instagram-feed headersize=medium]</code></td>
2262
- </tr>
2263
- <tr>
2264
- <td>headercolor</td>
2265
- <td><?php _e("The color of the Header text. Any hex color code.", 'instagram-feed'); ?></td>
2266
- <td><code>[instagram-feed headercolor=#333]</code></td>
2267
- </tr>
2268
-
2269
- <tr class="sbi_table_header"><td colspan=3><?php _e("'Load More' Button Options", 'instagram-feed'); ?></td></tr>
2270
- <tr>
2271
- <td>showbutton</td>
2272
- <td><?php _e("Whether to show the 'Load More' button. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2273
- <td><code>[instagram-feed showbutton=false]</code></td>
2274
- </tr>
2275
- <tr>
2276
- <td>buttoncolor</td>
2277
- <td><?php _e("The background color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2278
- <td><code>[instagram-feed buttoncolor=#000]</code></td>
2279
- </tr>
2280
- <tr>
2281
- <td>buttontextcolor</td>
2282
- <td><?php _e("The text color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2283
- <td><code>[instagram-feed buttontextcolor=#fff]</code></td>
2284
- </tr>
2285
- <tr>
2286
- <td>buttontext</td>
2287
- <td><?php _e("The text used for the button.", 'instagram-feed'); ?></td>
2288
- <td><code>[instagram-feed buttontext="Load More Photos"]</code></td>
2289
- </tr>
2290
-
2291
- <tr class="sbi_table_header"><td colspan=3><?php _e("'Follow on Instagram' Button Options", 'instagram-feed'); ?></td></tr>
2292
- <tr>
2293
- <td>showfollow</td>
2294
- <td><?php _e("Whether to show the 'Follow on Instagram' button. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2295
- <td><code>[instagram-feed showfollow=false]</code></td>
2296
- </tr>
2297
- <tr>
2298
- <td>followcolor</td>
2299
- <td><?php _e("The background color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2300
- <td><code>[instagram-feed followcolor=#ff0000]</code></td>
2301
- </tr>
2302
- <tr>
2303
- <td>followtextcolor</td>
2304
- <td><?php _e("The text color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2305
- <td><code>[instagram-feed followtextcolor=#fff]</code></td>
2306
- </tr>
2307
- <tr>
2308
- <td>followtext</td>
2309
- <td><?php _e("The text used for the button.", 'instagram-feed'); ?></td>
2310
- <td><code>[instagram-feed followtext="Follow me"]</code></td>
2311
- </tr>
2312
-
2313
- <tr class="sbi_table_header"><td colspan=3><?php _e("Caption Options", 'instagram-feed'); ?></td></tr>
2314
- <tr class="sbi_pro">
2315
- <td>showcaption</td>
2316
- <td><?php _e("Whether to show the photo caption. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2317
- <td><code>[instagram-feed showcaption=false]</code></td>
2318
- </tr>
2319
- <tr class="sbi_pro">
2320
- <td>captionlength</td>
2321
- <td><?php _e("The number of characters of the caption to display", 'instagram-feed'); ?></td>
2322
- <td><code>[instagram-feed captionlength=50]</code></td>
2323
- </tr>
2324
- <tr class="sbi_pro">
2325
- <td>captioncolor</td>
2326
- <td><?php _e("The text color of the caption. Any hex color code.", 'instagram-feed'); ?></td>
2327
- <td><code>[instagram-feed captioncolor=#000]</code></td>
2328
- </tr>
2329
- <tr class="sbi_pro">
2330
- <td>captionsize</td>
2331
- <td><?php _e("The size of the caption text. Any number.", 'instagram-feed'); ?></td>
2332
- <td><code>[instagram-feed captionsize=24]</code></td>
2333
- </tr>
2334
-
2335
- <tr class="sbi_table_header"><td colspan=3><?php _e("Likes &amp; Comments Options", 'instagram-feed'); ?></td></tr>
2336
- <tr class="sbi_pro">
2337
- <td>showlikes</td>
2338
- <td><?php _e("Whether to show the Likes &amp; Comments. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2339
- <td><code>[instagram-feed showlikes=false]</code></td>
2340
- </tr>
2341
- <tr class="sbi_pro">
2342
- <td>likescolor</td>
2343
- <td><?php _e("The color of the Likes &amp; Comments. Any hex color code.", 'instagram-feed'); ?></td>
2344
- <td><code>[instagram-feed likescolor=#FF0000]</code></td>
2345
- </tr>
2346
- <tr class="sbi_pro">
2347
- <td>likessize</td>
2348
- <td><?php _e("The size of the Likes &amp; Comments. Any number.", 'instagram-feed'); ?></td>
2349
- <td><code>[instagram-feed likessize=14]</code></td>
2350
- </tr>
2351
-
2352
- <tr class="sbi_table_header"><td colspan=3><?php _e("Post Filtering Options", 'instagram-feed'); ?></td></tr>
2353
- <tr class="sbi_pro">
2354
- <td>excludewords</td>
2355
- <td><?php _e("Remove posts which contain certain words or hashtags in the caption.", 'instagram-feed'); ?></td>
2356
- <td><code>[instagram-feed excludewords="bad, words"]</code></td>
2357
- </tr>
2358
- <tr class="sbi_pro">
2359
- <td>includewords</td>
2360
- <td><?php _e("Only display posts which contain certain words or hashtags in the caption.", 'instagram-feed'); ?></td>
2361
- <td><code>[instagram-feed includewords="sunshine"]</code></td>
2362
- </tr>
2363
-
2364
- <tr class="sbi_table_header"><td colspan=3><?php _e("Auto Load More on Scroll", 'instagram-feed'); ?></td></tr>
2365
- <tr class="sbi_pro">
2366
- <td>autoscroll</td>
2367
- <td><?php _e("Load more posts automatically as the user scrolls down the page.", 'instagram-feed'); ?></td>
2368
- <td><code>[instagram-feed autoscroll=true]</code></td>
2369
- </tr>
2370
- <tr class="sbi_pro">
2371
- <td>autoscrolldistance</td>
2372
- <td><?php _e("Distance before the end of feed or page that triggers the loading of more posts.", 'instagram-feed'); ?></td>
2373
- <td><code>[instagram-feed autoscrolldistance=200]</code></td>
2374
- </tr>
2375
-
2376
- </tbody>
2377
- </table>
2378
-
2379
- <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
2380
-
2381
- <?php } //End Display tab ?>
2382
-
2383
-
2384
- <?php if( $sbi_active_tab == 'support' ) { //Start Support tab ?>
2385
-
2386
- <div class="sbi_support">
2387
-
2388
- <br/>
2389
- <h3 style="padding-bottom: 10px;"><?php _e("Need help?", 'instagram-feed'); ?></h3>
2390
-
2391
- <p>
2392
- <span class="sbi-support-title"><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <a
2393
- href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi"
2394
- target="_blank"><?php _e( 'Setup Directions', 'instagram-feed' ); ?></a></span>
2395
- <?php _e( 'A step-by-step guide on how to setup and use the plugin.', 'instagram-feed' ); ?>
2396
- </p>
2397
-
2398
- <p>
2399
- <span class="sbi-support-title"><i class="fa fa-youtube-play" aria-hidden="true"></i>&nbsp; <a
2400
- href="https://www.youtube.com/embed/q6ZXVU4g970" target="_blank"
2401
- id="sbi-play-support-video"><?php _e( 'Watch a Video', 'instagram-feed' ); ?></a></span>
2402
- <?php _e( "Watch a short video demonstrating how to set up, customize and use the plugin.<br /><b>Please note</b> that the video shows the set up and use of the <b><a href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi' target='_blank'>Pro version</a></b> of the plugin, but the process is the same for this free version. The only difference is some of the features available.", 'instagram-feed' ); ?>
2403
-
2404
- <iframe id="sbi-support-video"
2405
- src="//www.youtube.com/embed/q6ZXVU4g970?theme=light&amp;showinfo=0&amp;controls=2" width="960"
2406
- height="540" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
2407
- </p>
2408
-
2409
- <p>
2410
- <span class="sbi-support-title"><i class="fa fa-question-circle" aria-hidden="true"></i>&nbsp; <a
2411
- href="https://smashballoon.com/instagram-feed/support/faq/?utm_source=plugin-free&utm_campaign=sbi"
2412
- target="_blank"><?php _e( 'FAQs and Docs', 'instagram-feed' ); ?></a></span>
2413
- <?php _e( 'View our expansive library of FAQs and documentation to help solve your problem as quickly as possible.', 'instagram-feed' ); ?>
2414
- </p>
2415
-
2416
- <div class="sbi-support-faqs">
2417
-
2418
- <ul>
2419
- <li><b><?php _e( 'FAQs', 'instagram-feed' ); ?></b></li>
2420
- <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/my-photos-wont-load/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">My Instagram Feed Won\'t Load</a>', 'instagram-feed' ); ?></li>
2421
- <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/my-instagram-access-token-keep-expiring/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">My Access Token Keeps Expiring</a>', 'instagram-feed' ); ?></li>
2422
- <li style="margin-top: 8px; font-size: 12px;"><a href="https://smashballoon.com/instagram-feed/support/faq/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e( 'See All', 'instagram-feed' ); ?><i class="fa fa-chevron-right" aria-hidden="true"></i></a></li>
2423
- </ul>
2424
-
2425
- <ul>
2426
- <li><b><?php _e("Documentation", 'instagram-feed'); ?></b></li>
2427
- <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/instagram-feed/free?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Installation and Configuration</a>', 'instagram-feed' ); ?></li>
2428
- <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/display-multiple-instagram-feeds/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Displaying multiple feeds</a>', 'instagram-feed' ); ?></li>
2429
- <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/instagram-feed-faq/customization/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Customizing your Feed</a>', 'instagram-feed' ); ?></li>
2430
- </ul>
2431
- </div>
2432
-
2433
- <p>
2434
- <span class="sbi-support-title"><i class="fa fa-envelope" aria-hidden="true"></i>&nbsp; <a
2435
- href="https://smashballoon.com/instagram-feed/support/?utm_source=plugin-free&utm_campaign=sbi"
2436
- target="_blank"><?php _e( 'Request Support', 'instagram-feed' ); ?></a></span>
2437
- <?php _e( 'Still need help? Submit a ticket and one of our support experts will get back to you as soon as possible.<br /><b>Important:</b> Please include your <b>System Info</b> below with all support requests.', 'instagram-feed' ); ?>
2438
- </p>
2439
- </div>
2440
-
2441
- <hr />
2442
-
2443
- <h3><?php _e('System Info &nbsp; <i style="color: #666; font-size: 11px; font-weight: normal;">Click the text below to select all</i>', 'instagram-feed'); ?></h3>
2444
-
2445
-
2446
-
2447
-
2448
- <?php $sbi_options = get_option('sb_instagram_settings'); ?>
2449
- <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: 100%; max-width: 960px; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
2450
- ## SITE/SERVER INFO: ##
2451
- Site URL: <?php echo site_url() . "\n"; ?>
2452
- Home URL: <?php echo home_url() . "\n"; ?>
2453
- WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
2454
- PHP Version: <?php echo PHP_VERSION . "\n"; ?>
2455
- Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
2456
-
2457
- ## ACTIVE PLUGINS: ##
2458
- <?php
2459
- $plugins = get_plugins();
2460
- $active_plugins = get_option( 'active_plugins', array() );
2461
-
2462
- foreach ( $plugins as $plugin_path => $plugin ) {
2463
- // If the plugin isn't active, don't show it.
2464
- if ( ! in_array( $plugin_path, $active_plugins ) )
2465
- continue;
2466
-
2467
- echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
2468
- }
2469
- ?>
2470
-
2471
- ## PLUGIN SETTINGS: ##
2472
- sb_instagram_plugin_type => Instagram Feed Free
2473
- <?php
2474
- global $wpdb;
2475
- foreach( $sbi_options as $key => $val ) {
2476
- if ( $key !== 'connected_accounts' ) {
2477
- if ( is_array( $val ) ) {
2478
- foreach ( $val as $item ) {
2479
- if ( is_array( $item ) ) {
2480
- foreach ( $item as $key2 => $val2 ) {
2481
- echo "$key2 => $val2\n";
2482
- }
2483
- } else {
2484
- echo "$key => $item\n";
2485
- }
2486
- }
2487
- } else {
2488
- echo "$key => $val\n";
2489
- }
2490
- }
2491
-
2492
- }
2493
- ?>
2494
-
2495
- ## CONNECTED ACCOUNTS: ##<?php echo "\n";
2496
- $con_accounts = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
2497
- $business_accounts = array();
2498
- $basic_accounts = array();
2499
- if ( ! empty( $con_accounts ) ) {
2500
- foreach ( $con_accounts as $account ) {
2501
- $type = isset( $account['type'] ) ? $account['type'] : 'personal';
2502
-
2503
- if ( $type === 'business' ) {
2504
- $business_accounts[] = $account;
2505
- } elseif ( $type === 'basic' ) {
2506
- $basic_accounts[] = $account;
2507
- }
2508
- echo '*' . $account['user_id'] . '*' . "\n";
2509
- var_export( $account );
2510
- echo "\n";
2511
- }
2512
- }
2513
- ?>
2514
-
2515
- ## API RESPONSE: ##
2516
- <?php
2517
- $first_con_basic_account = isset( $basic_accounts[0] ) ? $basic_accounts[0] : array();
2518
- $first_con_business_account = isset( $business_accounts[0] ) ? $business_accounts[0] : array();
2519
-
2520
- if ( ! empty( $first_con_basic_account ) ) {
2521
- echo '*BASIC ACCOUNT*';
2522
- echo "\n";
2523
- $connection = new SB_Instagram_API_Connect( $first_con_basic_account, 'header' );
2524
- $connection->connect();
2525
- if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
2526
- foreach ( $connection->get_data() as $key => $item ) {
2527
- if ( is_array ( $item ) ) {
2528
- foreach ( $item as $key2 => $item2 ) {
2529
- echo $key2 . ' => ' . esc_html( $item2 ) . "\n";
2530
- }
2531
- } else {
2532
- echo $key . ' => ' . esc_html( $item ) . "\n";
2533
- }
2534
- }
2535
- } else {
2536
- if ( $connection->is_wp_error() ) {
2537
- $response = $connection->get_wp_error();
2538
- if ( isset( $response ) && isset( $response->errors ) ) {
2539
- foreach ( $response->errors as $key => $item ) {
2540
- echo $key . ' => ' . $item[0] . "\n";
2541
- }
2542
- }
2543
- } else {
2544
- $error = $connection->get_data();
2545
- var_export( $error );
2546
- }
2547
- }
2548
- echo "\n";
2549
- } else {
2550
- echo 'no connected basic accounts';
2551
- echo "\n";
2552
- }
2553
- if ( ! empty( $first_con_business_account ) ) {
2554
- echo '*BUSINESS ACCOUNT*';
2555
- echo "\n";
2556
- $connection = new SB_Instagram_API_Connect( $first_con_business_account, 'header' );
2557
- $connection->connect();
2558
- if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
2559
- foreach ( $connection->get_data() as $key => $item ) {
2560
- if ( is_array ( $item ) ) {
2561
- foreach ( $item as $key2 => $item2 ) {
2562
- echo $key2 . ' => ' . esc_html( $item2 ) . "\n";
2563
- }
2564
- } else {
2565
- echo $key . ' => ' . esc_html( $item ) . "\n";
2566
- }
2567
- }
2568
- } else {
2569
- if ( $connection->is_wp_error() ) {
2570
- $response = $connection->get_wp_error();
2571
- if ( isset( $response ) && isset( $response->errors ) ) {
2572
- foreach ( $response->errors as $key => $item ) {
2573
- echo $key . ' => ' . $item[0] . "\n";
2574
- }
2575
- }
2576
- } else {
2577
- $error = $connection->get_data();
2578
- var_export( $error );
2579
- }
2580
- }
2581
- } else {
2582
- echo 'no connected business accounts';
2583
- } ?>
2584
-
2585
- ## Cron Events: ##
2586
- <?php
2587
- $cron = _get_cron_array();
2588
- foreach ( $cron as $key => $data ) {
2589
- $is_target = false;
2590
- foreach ( $data as $key2 => $val ) {
2591
- if ( strpos( $key2, 'sbi' ) !== false || strpos( $key2, 'sb_instagram' ) !== false ) {
2592
- $is_target = true;
2593
- echo $key2;
2594
- echo "\n";
2595
- }
2596
- }
2597
- if ( $is_target) {
2598
- echo date( "Y-m-d H:i:s", $key );
2599
- echo "\n";
2600
- echo 'Next Scheduled: ' . ((int)$key - time())/60 . ' minutes';
2601
- echo "\n\n";
2602
- }
2603
- }
2604
- ?>
2605
- ## Cron Cache Report: ##
2606
- <?php $cron_report = get_option( 'sbi_cron_report', array() );
2607
- if ( ! empty( $cron_report ) ) {
2608
- var_export( $cron_report );
2609
- }
2610
- echo "\n";
2611
- ?>
2612
-
2613
- ## Access Token Refresh: ##
2614
- <?php $cron_report = get_option( 'sbi_refresh_report', array() );
2615
- if ( ! empty( $cron_report ) ) {
2616
- var_export( $cron_report );
2617
- }
2618
- echo "\n";
2619
- ?>
2620
-
2621
- ## Resizing: ##
2622
- <?php $upload = wp_upload_dir();
2623
- $upload_dir = $upload['basedir'];
2624
- $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
2625
- if ( file_exists( $upload_dir ) ) {
2626
- echo 'upload directory exists';
2627
- } else {
2628
- $created = wp_mkdir_p( $upload_dir );
2629
-
2630
- if ( ! $created ) {
2631
- echo 'cannot create upload directory';
2632
- }
2633
- }
2634
- echo "\n";
2635
- echo "\n";
2636
-
2637
- $table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE );
2638
- $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
2639
-
2640
- if ( $wpdb->get_var( "show tables like '$feeds_posts_table_name'" ) != $feeds_posts_table_name ) {
2641
- echo 'no feeds posts table';
2642
- echo "\n";
2643
-
2644
- } else {
2645
- $last_result = $wpdb->get_results( "SELECT * FROM $feeds_posts_table_name ORDER BY id DESC LIMIT 1;" );
2646
- if ( is_array( $last_result ) && isset( $last_result[0] ) ) {
2647
- echo '*FEEDS POSTS TABLE*';
2648
- echo "\n";
2649
-
2650
- foreach ( $last_result as $column ) {
2651
-
2652
- foreach ( $column as $key => $value ) {
2653
- echo $key . ': ' . esc_html( $value ) . "\n";;
2654
- }
2655
- }
2656
-
2657
- } else {
2658
- echo 'feeds posts has no rows';
2659
- echo "\n";
2660
- }
2661
- }
2662
- echo "\n";
2663
-
2664
- if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) {
2665
- echo 'no posts table';
2666
- echo "\n";
2667
-
2668
- } else {
2669
-
2670
-
2671
- $last_result = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY id DESC LIMIT 1;" );
2672
- if ( is_array( $last_result ) && isset( $last_result[0] ) ) {
2673
- echo '*POSTS TABLE*';
2674
- echo "\n";
2675
- foreach ( $last_result as $column ) {
2676
-
2677
- foreach ( $column as $key => $value ) {
2678
- echo $key . ': ' . esc_html( $value ) . "\n";;
2679
- }
2680
- }
2681
-
2682
- } else {
2683
- echo 'feeds posts has no rows';
2684
- echo "\n";
2685
- }
2686
- }
2687
-
2688
- ?>
2689
-
2690
- ## Error Log: ##
2691
- <?php
2692
- global $sb_instagram_posts_manager;
2693
- $errors = $sb_instagram_posts_manager->get_errors();
2694
- if ( ! empty( $errors ) ) :
2695
- foreach ( $errors as $type => $error ) :
2696
- echo $type . ': ' . $error[1] . "\n";
2697
- endforeach;
2698
- endif;
2699
- $ajax_statuses = $sb_instagram_posts_manager->get_ajax_status();
2700
- if ( ! $ajax_statuses['successful'] ) {
2701
- ## AJAX Status ##
2702
- echo 'test not successful';
2703
- }
2704
- ?>
2705
- </textarea>
2706
- <div><input id="sbi_reset_log" class="button-secondary" type="submit" value="<?php esc_attr_e( 'Reset Error Log' ); ?>" style="vertical-align: middle;"/></div>
2707
-
2708
- <?php
2709
- } //End Support tab
2710
- ?>
2711
-
2712
-
2713
- <div class="sbi_quickstart">
2714
- <h3><i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <?php _e('Display your feed', 'instagram-feed'); ?></h3>
2715
- <p><?php _e('Copy and paste this shortcode directly into the page, post or widget where you\'d like to display the feed:', 'instagram-feed'); ?> <input type="text" value="[instagram-feed]" size="15" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)."></p>
2716
- <p><?php _e('Find out how to display <a href="?page=sb-instagram-feed&amp;tab=display">multiple feeds</a>.', 'instagram-feed'); ?></p>
2717
- </div>
2718
-
2719
- <a href="https://smashballoon.com/instagram-feed/demo/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi-pro-notice">
2720
- <img src="<?php echo SBI_PLUGIN_URL . 'img/instagram-pro-promo.png?2019'; ?>" alt="<?php esc_attr_e( 'Instagram Feed Pro', 'instagram-feed' ); ?>">
2721
- </a>
2722
-
2723
- <p class="sbi_plugins_promo dashicons-before dashicons-admin-plugins"> <?php _e('Check out our other free plugins: <a href="https://wordpress.org/plugins/custom-facebook-feed/" target="_blank">Facebook</a>, <a href="https://wordpress.org/plugins/custom-twitter-feeds/" target="_blank">Twitter</a>, and <a href="https://wordpress.org/plugins/feeds-for-youtube/" target="_blank">YouTube</a>.', 'instagram-feed' ); ?></p>
2724
-
2725
- <div class="sbi_share_plugin">
2726
- <h3><?php _e('Like the plugin? Help spread the word!', 'instagram-feed'); ?></h3>
2727
-
2728
- <button id="sbi_admin_show_share_links" class="button secondary" style="margin-bottom: 1px;"><i class="fa fa-share-alt" aria-hidden="true"></i>&nbsp;&nbsp;Share the plugin</button> <div id="sbi_admin_share_links"></div>
2729
- </div>
2730
-
2731
- </div> <!-- end #sbi_admin -->
2732
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2733
  <?php } //End Settings page
1
+ <?php
2
+ /**
3
+ * Includes functions for all admin page templates and
4
+ * functions that add menu pages in the dashboard. Also
5
+ * has code for saving settings with defaults.
6
+ */
7
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
+
9
+ function sb_instagram_menu() {
10
+ $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
11
+
12
+ $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
13
+
14
+ global $sb_instagram_posts_manager;
15
+ $notice = '';
16
+ if ( $sb_instagram_posts_manager->are_critical_errors() ) {
17
+ $notice = ' <span class="update-plugins sbi-error-alert"><span>!</span></span>';
18
+ }
19
+
20
+ add_menu_page(
21
+ __( 'Instagram Feed', 'instagram-feed' ),
22
+ __( 'Instagram Feed', 'instagram-feed' ) . $notice,
23
+ $cap,
24
+ 'sb-instagram-feed',
25
+ 'sb_instagram_settings_page'
26
+ );
27
+ add_submenu_page(
28
+ 'sb-instagram-feed',
29
+ __( 'Settings', 'instagram-feed' ),
30
+ __( 'Settings', 'instagram-feed' ) . $notice,
31
+ $cap,
32
+ 'sb-instagram-feed',
33
+ 'sb_instagram_settings_page'
34
+ );
35
+ add_submenu_page(
36
+ 'sb-instagram-feed',
37
+ __( 'About Us', 'instagram-feed' ),
38
+ __( 'About Us', 'instagram-feed' ),
39
+ $cap,
40
+ 'sb-instagram-feed-about',
41
+ 'sb_instagram_about_page'
42
+ );
43
+ }
44
+ add_action('admin_menu', 'sb_instagram_menu');
45
+
46
+ function sb_instagram_about_page() {
47
+ do_action('sbi_admin_page' );
48
+ }
49
+
50
+ function sb_instagram_settings_page() {
51
+
52
+ //Hidden fields
53
+ $sb_instagram_settings_hidden_field = 'sb_instagram_settings_hidden_field';
54
+ $sb_instagram_configure_hidden_field = 'sb_instagram_configure_hidden_field';
55
+ $sb_instagram_customize_hidden_field = 'sb_instagram_customize_hidden_field';
56
+
57
+ //Declare defaults
58
+ $sb_instagram_settings_defaults = array(
59
+ 'sb_instagram_at' => '',
60
+ 'sb_instagram_user_id' => '',
61
+ 'sb_instagram_preserve_settings' => '',
62
+ 'sb_instagram_cache_time' => 1,
63
+ 'sb_instagram_cache_time_unit' => 'hours',
64
+ 'sbi_caching_type' => 'page',
65
+ 'sbi_cache_cron_interval' => '12hours',
66
+ 'sbi_cache_cron_time' => '1',
67
+ 'sbi_cache_cron_am_pm' => 'am',
68
+ 'sb_instagram_width' => '100',
69
+ 'sb_instagram_width_unit' => '%',
70
+ 'sb_instagram_feed_width_resp' => false,
71
+ 'sb_instagram_height' => '',
72
+ 'sb_instagram_num' => '20',
73
+ 'sb_instagram_height_unit' => '',
74
+ 'sb_instagram_cols' => '4',
75
+ 'sb_instagram_disable_mobile' => false,
76
+ 'sb_instagram_image_padding' => '5',
77
+ 'sb_instagram_image_padding_unit' => 'px',
78
+ 'sb_instagram_sort' => 'none',
79
+ 'sb_instagram_background' => '',
80
+ 'sb_instagram_show_btn' => true,
81
+ 'sb_instagram_btn_background' => '',
82
+ 'sb_instagram_btn_text_color' => '',
83
+ 'sb_instagram_btn_text' => __( 'Load More...', 'instagram-feed' ),
84
+ 'sb_instagram_image_res' => 'auto',
85
+ //Header
86
+ 'sb_instagram_show_header' => true,
87
+ 'sb_instagram_header_size' => 'small',
88
+ 'sb_instagram_header_color' => '',
89
+ 'sb_instagram_custom_bio' => '',
90
+ 'sb_instagram_custom_avatar' => '',
91
+ //Follow button
92
+ 'sb_instagram_show_follow_btn' => true,
93
+ 'sb_instagram_folow_btn_background' => '',
94
+ 'sb_instagram_follow_btn_text_color' => '',
95
+ 'sb_instagram_follow_btn_text' => __( 'Follow on Instagram', 'instagram-feed' ),
96
+ //Misc
97
+ 'sb_instagram_custom_css' => '',
98
+ 'sb_instagram_custom_js' => '',
99
+ 'sb_instagram_cron' => 'no',
100
+ 'sb_instagram_backup' => true,
101
+ 'sb_ajax_initial' => false,
102
+ 'enqueue_css_in_shortcode' => false,
103
+ 'sb_instagram_ajax_theme' => false,
104
+ 'sb_instagram_disable_resize' => false,
105
+ 'sb_instagram_favor_local' => false,
106
+ 'sb_instagram_minnum' => 0,
107
+ 'disable_js_image_loading' => false,
108
+ 'enqueue_js_in_head' => false,
109
+ 'sb_instagram_disable_mob_swipe' => false,
110
+ 'sbi_font_method' => 'svg',
111
+ 'sb_instagram_disable_awesome' => false,
112
+ 'custom_template' => false,
113
+ 'disable_admin_notice' => false,
114
+ 'enable_email_report' => 'on',
115
+ 'email_notification' => 'monday',
116
+ 'email_notification_addresses' => get_option( 'admin_email' ),
117
+ );
118
+ //Save defaults in an array
119
+ $options = wp_parse_args(get_option('sb_instagram_settings'), $sb_instagram_settings_defaults);
120
+ update_option( 'sb_instagram_settings', $options );
121
+
122
+ //Set the page variables
123
+ $sb_instagram_at = $options[ 'sb_instagram_at' ];
124
+ $sb_instagram_user_id = $options[ 'sb_instagram_user_id' ];
125
+ $sb_instagram_preserve_settings = $options[ 'sb_instagram_preserve_settings' ];
126
+ $sb_instagram_ajax_theme = $options[ 'sb_instagram_ajax_theme' ];
127
+ $enqueue_js_in_head = $options[ 'enqueue_js_in_head' ];
128
+ $disable_js_image_loading = $options[ 'disable_js_image_loading' ];
129
+ $sb_instagram_disable_resize = $options[ 'sb_instagram_disable_resize' ];
130
+ $sb_instagram_favor_local = $options[ 'sb_instagram_favor_local' ];
131
+ $sb_instagram_minnum = $options[ 'sb_instagram_minnum' ];
132
+
133
+ $sb_instagram_cache_time = $options[ 'sb_instagram_cache_time' ];
134
+ $sb_instagram_cache_time_unit = $options[ 'sb_instagram_cache_time_unit' ];
135
+
136
+ $sbi_caching_type = $options[ 'sbi_caching_type' ];
137
+ $sbi_cache_cron_interval = $options[ 'sbi_cache_cron_interval' ];
138
+ $sbi_cache_cron_time = $options[ 'sbi_cache_cron_time' ];
139
+ $sbi_cache_cron_am_pm = $options[ 'sbi_cache_cron_am_pm' ];
140
+
141
+ $sb_instagram_width = $options[ 'sb_instagram_width' ];
142
+ $sb_instagram_width_unit = $options[ 'sb_instagram_width_unit' ];
143
+ $sb_instagram_feed_width_resp = $options[ 'sb_instagram_feed_width_resp' ];
144
+ $sb_instagram_height = $options[ 'sb_instagram_height' ];
145
+ $sb_instagram_height_unit = $options[ 'sb_instagram_height_unit' ];
146
+ $sb_instagram_num = $options[ 'sb_instagram_num' ];
147
+ $sb_instagram_cols = $options[ 'sb_instagram_cols' ];
148
+ $sb_instagram_disable_mobile = $options[ 'sb_instagram_disable_mobile' ];
149
+ $sb_instagram_image_padding = $options[ 'sb_instagram_image_padding' ];
150
+ $sb_instagram_image_padding_unit = $options[ 'sb_instagram_image_padding_unit' ];
151
+ $sb_instagram_sort = $options[ 'sb_instagram_sort' ];
152
+ $sb_instagram_background = $options[ 'sb_instagram_background' ];
153
+ $sb_instagram_show_btn = $options[ 'sb_instagram_show_btn' ];
154
+ $sb_instagram_btn_background = $options[ 'sb_instagram_btn_background' ];
155
+ $sb_instagram_btn_text_color = $options[ 'sb_instagram_btn_text_color' ];
156
+ $sb_instagram_btn_text = $options[ 'sb_instagram_btn_text' ];
157
+ $sb_instagram_image_res = $options[ 'sb_instagram_image_res' ];
158
+ //Header
159
+ $sb_instagram_show_header = $options[ 'sb_instagram_show_header' ];
160
+ $sb_instagram_header_size = $options[ 'sb_instagram_header_size' ];
161
+ $sb_instagram_show_bio = isset( $options[ 'sb_instagram_show_bio' ] ) ? $options[ 'sb_instagram_show_bio' ] : true;
162
+ $sb_instagram_custom_bio = $options[ 'sb_instagram_custom_bio' ];
163
+ $sb_instagram_custom_avatar = $options[ 'sb_instagram_custom_avatar' ];
164
+ $sb_instagram_header_color = $options[ 'sb_instagram_header_color' ];
165
+ //Follow button
166
+ $sb_instagram_show_follow_btn = $options[ 'sb_instagram_show_follow_btn' ];
167
+ $sb_instagram_folow_btn_background = $options[ 'sb_instagram_folow_btn_background' ];
168
+ $sb_instagram_follow_btn_text_color = $options[ 'sb_instagram_follow_btn_text_color' ];
169
+ $sb_instagram_follow_btn_text = $options[ 'sb_instagram_follow_btn_text' ];
170
+ //Misc
171
+ $sb_instagram_custom_css = $options[ 'sb_instagram_custom_css' ];
172
+ $sb_instagram_custom_js = $options[ 'sb_instagram_custom_js' ];
173
+ $sb_instagram_cron = $options[ 'sb_instagram_cron' ];
174
+ $sb_instagram_backup = $options[ 'sb_instagram_backup' ];
175
+ $sb_ajax_initial = $options[ 'sb_ajax_initial' ];
176
+ $enqueue_css_in_shortcode = $options[ 'enqueue_css_in_shortcode' ];
177
+ $sbi_font_method = $options[ 'sbi_font_method' ];
178
+ $sb_instagram_disable_awesome = $options[ 'sb_instagram_disable_awesome' ];
179
+ $sb_instagram_custom_template = $options[ 'custom_template' ];
180
+ $sb_instagram_disable_admin_notice = $options[ 'disable_admin_notice' ];
181
+ $sb_instagram_enable_email_report = $options[ 'enable_email_report' ];
182
+ $sb_instagram_email_notification = $options[ 'email_notification' ];
183
+ $sb_instagram_email_notification_addresses = $options[ 'email_notification_addresses' ];
184
+ //Check nonce before saving data
185
+ if ( ! isset( $_POST['sb_instagram_settings_nonce'] ) || ! wp_verify_nonce( $_POST['sb_instagram_settings_nonce'], 'sb_instagram_saving_settings' ) ) {
186
+ //Nonce did not verify
187
+ } else {
188
+ // See if the user has posted us some information. If they did, this hidden field will be set to 'Y'.
189
+ if( isset($_POST[ $sb_instagram_settings_hidden_field ]) && $_POST[ $sb_instagram_settings_hidden_field ] == 'Y' ) {
190
+
191
+ if( isset($_POST[ $sb_instagram_configure_hidden_field ]) && $_POST[ $sb_instagram_configure_hidden_field ] == 'Y' ) {
192
+
193
+ $sb_instagram_at = sanitize_text_field( $_POST[ 'sb_instagram_at' ] );
194
+ $sb_instagram_user_id = array();
195
+ if ( isset( $_POST[ 'sb_instagram_user_id' ] )) {
196
+ if ( is_array( $_POST[ 'sb_instagram_user_id' ] ) ) {
197
+ foreach( $_POST[ 'sb_instagram_user_id' ] as $user_id ) {
198
+ $sb_instagram_user_id[] = sanitize_text_field( $user_id );
199
+ }
200
+ } else {
201
+ $sb_instagram_user_id[] = sanitize_text_field( $_POST[ 'sb_instagram_user_id' ] );
202
+ }
203
+ }
204
+ isset($_POST[ 'sb_instagram_preserve_settings' ]) ? $sb_instagram_preserve_settings = sanitize_text_field( $_POST[ 'sb_instagram_preserve_settings' ] ) : $sb_instagram_preserve_settings = '';
205
+ isset($_POST[ 'sb_instagram_cache_time' ]) ? $sb_instagram_cache_time = sanitize_text_field( $_POST[ 'sb_instagram_cache_time' ] ) : $sb_instagram_cache_time = '';
206
+ isset($_POST[ 'sb_instagram_cache_time_unit' ]) ? $sb_instagram_cache_time_unit = sanitize_text_field( $_POST[ 'sb_instagram_cache_time_unit' ] ) : $sb_instagram_cache_time_unit = '';
207
+
208
+ isset($_POST[ 'sbi_caching_type' ]) ? $sbi_caching_type = sanitize_text_field( $_POST[ 'sbi_caching_type' ] ) : $sbi_caching_type = '';
209
+ isset($_POST[ 'sbi_cache_cron_interval' ]) ? $sbi_cache_cron_interval = sanitize_text_field( $_POST[ 'sbi_cache_cron_interval' ] ) : $sbi_cache_cron_interval = '';
210
+ isset($_POST[ 'sbi_cache_cron_time' ]) ? $sbi_cache_cron_time = sanitize_text_field( $_POST[ 'sbi_cache_cron_time' ] ) : $sbi_cache_cron_time = '';
211
+ isset($_POST[ 'sbi_cache_cron_am_pm' ]) ? $sbi_cache_cron_am_pm = sanitize_text_field( $_POST[ 'sbi_cache_cron_am_pm' ] ) : $sbi_cache_cron_am_pm = '';
212
+
213
+ $options[ 'sb_instagram_at' ] = $sb_instagram_at;
214
+ $options[ 'sb_instagram_user_id' ] = $sb_instagram_user_id;
215
+ $options[ 'sb_instagram_preserve_settings' ] = $sb_instagram_preserve_settings;
216
+
217
+ $options[ 'sb_instagram_cache_time' ] = $sb_instagram_cache_time;
218
+ $options[ 'sb_instagram_cache_time_unit' ] = $sb_instagram_cache_time_unit;
219
+
220
+ $options[ 'sbi_caching_type' ] = $sbi_caching_type;
221
+ $options[ 'sbi_cache_cron_interval' ] = $sbi_cache_cron_interval;
222
+ $options[ 'sbi_cache_cron_time' ] = $sbi_cache_cron_time;
223
+ $options[ 'sbi_cache_cron_am_pm' ] = $sbi_cache_cron_am_pm;
224
+
225
+
226
+ //Delete all SBI transients
227
+ global $wpdb;
228
+ $table_name = $wpdb->prefix . "options";
229
+ $wpdb->query( "
230
+ DELETE
231
+ FROM $table_name
232
+ WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
233
+ " );
234
+ $wpdb->query( "
235
+ DELETE
236
+ FROM $table_name
237
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
238
+ " );
239
+ $wpdb->query( "
240
+ DELETE
241
+ FROM $table_name
242
+ WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
243
+ " );
244
+ $wpdb->query( "
245
+ DELETE
246
+ FROM $table_name
247
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
248
+ " );
249
+
250
+ if ( $sbi_caching_type === 'background' ) {
251
+ delete_option( 'sbi_cron_report' );
252
+ SB_Instagram_Cron_Updater::start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm );
253
+ }
254
+
255
+ } //End config tab post
256
+
257
+ if( isset($_POST[ $sb_instagram_customize_hidden_field ]) && $_POST[ $sb_instagram_customize_hidden_field ] == 'Y' ) {
258
+
259
+ //Validate and sanitize width field
260
+ $safe_width = intval( sanitize_text_field( $_POST['sb_instagram_width'] ) );
261
+ if ( ! $safe_width ) $safe_width = '';
262
+ if ( strlen( $safe_width ) > 4 ) $safe_width = substr( $safe_width, 0, 4 );
263
+ $sb_instagram_width = $safe_width;
264
+
265
+ $sb_instagram_width_unit = sanitize_text_field( $_POST[ 'sb_instagram_width_unit' ] );
266
+ isset($_POST[ 'sb_instagram_feed_width_resp' ]) ? $sb_instagram_feed_width_resp = sanitize_text_field( $_POST[ 'sb_instagram_feed_width_resp' ] ) : $sb_instagram_feed_width_resp = '';
267
+
268
+ //Validate and sanitize height field
269
+ $safe_height = intval( sanitize_text_field( $_POST['sb_instagram_height'] ) );
270
+ if ( ! $safe_height ) $safe_height = '';
271
+ if ( strlen( $safe_height ) > 4 ) $safe_height = substr( $safe_height, 0, 4 );
272
+ $sb_instagram_height = $safe_height;
273
+
274
+ $sb_instagram_height_unit = sanitize_text_field( $_POST[ 'sb_instagram_height_unit' ] );
275
+
276
+ //Validate and sanitize number of photos field
277
+ $safe_num = intval( sanitize_text_field( $_POST['sb_instagram_num'] ) );
278
+ if ( ! $safe_num ) $safe_num = '';
279
+ if ( strlen( $safe_num ) > 4 ) $safe_num = substr( $safe_num, 0, 4 );
280
+ $sb_instagram_num = $safe_num;
281
+
282
+ $sb_instagram_cols = sanitize_text_field( $_POST[ 'sb_instagram_cols' ] );
283
+ isset($_POST[ 'sb_instagram_disable_mobile' ]) ? $sb_instagram_disable_mobile = sanitize_text_field( $_POST[ 'sb_instagram_disable_mobile' ] ) : $sb_instagram_disable_mobile = '';
284
+
285
+ //Validate and sanitize padding field
286
+ $safe_padding = intval( sanitize_text_field( $_POST['sb_instagram_image_padding'] ) );
287
+ if ( ! $safe_padding ) $safe_padding = '';
288
+ if ( strlen( $safe_padding ) > 4 ) $safe_padding = substr( $safe_padding, 0, 4 );
289
+ $sb_instagram_image_padding = $safe_padding;
290
+
291
+ $sb_instagram_image_padding_unit = sanitize_text_field( $_POST[ 'sb_instagram_image_padding_unit' ] );
292
+ $sb_instagram_sort = sanitize_text_field( $_POST[ 'sb_instagram_sort' ] );
293
+ $sb_instagram_background = sanitize_text_field( $_POST[ 'sb_instagram_background' ] );
294
+ isset($_POST[ 'sb_instagram_show_btn' ]) ? $sb_instagram_show_btn = sanitize_text_field( $_POST[ 'sb_instagram_show_btn' ] ) : $sb_instagram_show_btn = '';
295
+ $sb_instagram_btn_background = sanitize_text_field( $_POST[ 'sb_instagram_btn_background' ] );
296
+ $sb_instagram_btn_text_color = sanitize_text_field( $_POST[ 'sb_instagram_btn_text_color' ] );
297
+ $sb_instagram_btn_text = sanitize_text_field( $_POST[ 'sb_instagram_btn_text' ] );
298
+ $sb_instagram_image_res = sanitize_text_field( $_POST[ 'sb_instagram_image_res' ] );
299
+ //Header
300
+ isset($_POST[ 'sb_instagram_show_header' ]) ? $sb_instagram_show_header = sanitize_text_field( $_POST[ 'sb_instagram_show_header' ] ) : $sb_instagram_show_header = '';
301
+ isset($_POST[ 'sb_instagram_show_bio' ]) ? $sb_instagram_show_bio = sanitize_text_field( $_POST[ 'sb_instagram_show_bio' ] ) : $sb_instagram_show_bio = '';
302
+ isset($_POST[ 'sb_instagram_custom_bio' ]) ? $sb_instagram_custom_bio = sanitize_textarea_field( $_POST[ 'sb_instagram_custom_bio' ] ) : $sb_instagram_custom_bio = '';
303
+ isset($_POST[ 'sb_instagram_custom_avatar' ]) ? $sb_instagram_custom_avatar = sanitize_text_field( $_POST[ 'sb_instagram_custom_avatar' ] ) : $sb_instagram_custom_avatar = '';
304
+ if (isset($_POST[ 'sb_instagram_header_size' ]) ) $sb_instagram_header_size = $_POST[ 'sb_instagram_header_size' ];
305
+
306
+ $sb_instagram_header_color = sanitize_text_field( $_POST[ 'sb_instagram_header_color' ] );
307
+ //Follow button
308
+ isset($_POST[ 'sb_instagram_show_follow_btn' ]) ? $sb_instagram_show_follow_btn = sanitize_text_field( $_POST[ 'sb_instagram_show_follow_btn' ] ) : $sb_instagram_show_follow_btn = '';
309
+ $sb_instagram_folow_btn_background = sanitize_text_field( $_POST[ 'sb_instagram_folow_btn_background' ] );
310
+ $sb_instagram_follow_btn_text_color = sanitize_text_field( $_POST[ 'sb_instagram_follow_btn_text_color' ] );
311
+ $sb_instagram_follow_btn_text = sanitize_text_field( $_POST[ 'sb_instagram_follow_btn_text' ] );
312
+ //Misc
313
+ $sb_instagram_custom_css = $_POST[ 'sb_instagram_custom_css' ];
314
+ $sb_instagram_custom_js = $_POST[ 'sb_instagram_custom_js' ];
315
+ isset($_POST[ 'sb_instagram_ajax_theme' ]) ? $sb_instagram_ajax_theme = sanitize_text_field( $_POST[ 'sb_instagram_ajax_theme' ] ) : $sb_instagram_ajax_theme = '';
316
+ isset($_POST[ 'enqueue_js_in_head' ]) ? $enqueue_js_in_head = $_POST[ 'enqueue_js_in_head' ] : $enqueue_js_in_head = '';
317
+ isset($_POST[ 'disable_js_image_loading' ]) ? $disable_js_image_loading = $_POST[ 'disable_js_image_loading' ] : $disable_js_image_loading = '';
318
+ isset($_POST[ 'sb_instagram_disable_resize' ]) ? $sb_instagram_disable_resize= sanitize_text_field( $_POST[ 'sb_instagram_disable_resize' ] ) : $sb_instagram_disable_resize = '';
319
+ isset($_POST[ 'sb_instagram_favor_local' ]) ? $sb_instagram_favor_local = sanitize_text_field( $_POST[ 'sb_instagram_favor_local' ] ) : $sb_instagram_favor_local = '';
320
+ isset($_POST[ 'sb_instagram_minnum' ]) ? $sb_instagram_minnum = sanitize_text_field( $_POST[ 'sb_instagram_minnum' ] ) : $sb_instagram_minnum = '';
321
+
322
+ if (isset($_POST[ 'sb_instagram_cron' ]) ) $sb_instagram_cron = $_POST[ 'sb_instagram_cron' ];
323
+ isset($_POST[ 'sb_instagram_backup' ]) ? $sb_instagram_backup = $_POST[ 'sb_instagram_backup' ] : $sb_instagram_backup = '';
324
+ isset($_POST[ 'sb_ajax_initial' ]) ? $sb_ajax_initial = $_POST[ 'sb_ajax_initial' ] : $sb_ajax_initial = '';
325
+ isset($_POST[ 'enqueue_css_in_shortcode' ]) ? $enqueue_css_in_shortcode = $_POST[ 'enqueue_css_in_shortcode' ] : $enqueue_css_in_shortcode = '';
326
+ isset($_POST[ 'sbi_font_method' ]) ? $sbi_font_method = $_POST[ 'sbi_font_method' ] : $sbi_font_method = 'svg';
327
+ isset($_POST[ 'sb_instagram_disable_awesome' ]) ? $sb_instagram_disable_awesome = sanitize_text_field( $_POST[ 'sb_instagram_disable_awesome' ] ) : $sb_instagram_disable_awesome = '';
328
+
329
+ $options[ 'sb_instagram_width' ] = $sb_instagram_width;
330
+ $options[ 'sb_instagram_width_unit' ] = $sb_instagram_width_unit;
331
+ $options[ 'sb_instagram_feed_width_resp' ] = $sb_instagram_feed_width_resp;
332
+ $options[ 'sb_instagram_height' ] = $sb_instagram_height;
333
+ $options[ 'sb_instagram_height_unit' ] = $sb_instagram_height_unit;
334
+ $options[ 'sb_instagram_num' ] = $sb_instagram_num;
335
+ $options[ 'sb_instagram_cols' ] = $sb_instagram_cols;
336
+ $options[ 'sb_instagram_disable_mobile' ] = $sb_instagram_disable_mobile;
337
+ $options[ 'sb_instagram_image_padding' ] = $sb_instagram_image_padding;
338
+ $options[ 'sb_instagram_image_padding_unit' ] = $sb_instagram_image_padding_unit;
339
+ $options[ 'sb_instagram_sort' ] = $sb_instagram_sort;
340
+ $options[ 'sb_instagram_background' ] = $sb_instagram_background;
341
+ $options[ 'sb_instagram_show_btn' ] = $sb_instagram_show_btn;
342
+ $options[ 'sb_instagram_btn_background' ] = $sb_instagram_btn_background;
343
+ $options[ 'sb_instagram_btn_text_color' ] = $sb_instagram_btn_text_color;
344
+ $options[ 'sb_instagram_btn_text' ] = $sb_instagram_btn_text;
345
+ $options[ 'sb_instagram_image_res' ] = $sb_instagram_image_res;
346
+ //Header
347
+ $options[ 'sb_instagram_show_header' ] = $sb_instagram_show_header;
348
+ $options[ 'sb_instagram_header_size' ] = $sb_instagram_header_size;
349
+ $options[ 'sb_instagram_show_bio' ] = $sb_instagram_show_bio;
350
+ $options[ 'sb_instagram_custom_bio' ] = $sb_instagram_custom_bio;
351
+ $options[ 'sb_instagram_custom_avatar' ] = $sb_instagram_custom_avatar;
352
+ $options[ 'sb_instagram_custom_bio' ] = $sb_instagram_custom_bio;
353
+ $options[ 'sb_instagram_custom_avatar' ] = $sb_instagram_custom_avatar;
354
+ $options[ 'sb_instagram_header_color' ] = $sb_instagram_header_color;
355
+ //Follow button
356
+ $options[ 'sb_instagram_show_follow_btn' ] = $sb_instagram_show_follow_btn;
357
+ $options[ 'sb_instagram_folow_btn_background' ] = $sb_instagram_folow_btn_background;
358
+ $options[ 'sb_instagram_follow_btn_text_color' ] = $sb_instagram_follow_btn_text_color;
359
+ $options[ 'sb_instagram_follow_btn_text' ] = $sb_instagram_follow_btn_text;
360
+ //Misc
361
+ $options[ 'sb_instagram_custom_css' ] = $sb_instagram_custom_css;
362
+ $options[ 'sb_instagram_custom_js' ] = $sb_instagram_custom_js;
363
+ $options[ 'sb_instagram_ajax_theme' ] = $sb_instagram_ajax_theme;
364
+ $options[ 'enqueue_js_in_head' ] = $enqueue_js_in_head;
365
+ $options[ 'disable_js_image_loading' ] = $disable_js_image_loading;
366
+ $options[ 'sb_instagram_disable_resize' ] = $sb_instagram_disable_resize;
367
+ $options[ 'sb_instagram_favor_local' ] = $sb_instagram_favor_local;
368
+ $options[ 'sb_instagram_minnum' ] = $sb_instagram_minnum;
369
+
370
+ $options[ 'sb_ajax_initial' ] = $sb_ajax_initial;
371
+ $options[ 'sb_instagram_cron' ] = $sb_instagram_cron;
372
+ $options['sb_instagram_backup'] = $sb_instagram_backup;
373
+ $options['enqueue_css_in_shortcode'] = $enqueue_css_in_shortcode;
374
+
375
+ $options['sbi_font_method'] = $sbi_font_method;
376
+ $options[ 'sb_instagram_disable_awesome' ] = $sb_instagram_disable_awesome;
377
+
378
+ isset($_POST[ 'sb_instagram_custom_template' ]) ? $sb_instagram_custom_template = $_POST[ 'sb_instagram_custom_template' ] : $sb_instagram_custom_template = '';
379
+ $options['custom_template'] = $sb_instagram_custom_template;
380
+ isset($_POST[ 'sb_instagram_disable_admin_notice' ]) ? $sb_instagram_disable_admin_notice = $_POST[ 'sb_instagram_disable_admin_notice' ] : $sb_instagram_disable_admin_notice = '';
381
+ $options['disable_admin_notice'] = $sb_instagram_disable_admin_notice;
382
+ isset($_POST[ 'sb_instagram_enable_email_report' ]) ? $sb_instagram_enable_email_report = $_POST[ 'sb_instagram_enable_email_report' ] : $sb_instagram_enable_email_report = '';
383
+ $options['enable_email_report'] = $sb_instagram_enable_email_report;
384
+ isset($_POST[ 'sb_instagram_email_notification' ]) ? $sb_instagram_email_notification = $_POST[ 'sb_instagram_email_notification' ] : $sb_instagram_email_notification = '';
385
+ $original = $options['email_notification'];
386
+ $options['email_notification'] = $sb_instagram_email_notification;
387
+ isset($_POST[ 'sb_instagram_email_notification_addresses' ]) ? $sb_instagram_email_notification_addresses = $_POST[ 'sb_instagram_email_notification_addresses' ] : $sb_instagram_email_notification_addresses = get_option( 'admin_email' );
388
+ $options['email_notification_addresses'] = $sb_instagram_email_notification_addresses;
389
+
390
+ if ( $original !== $sb_instagram_email_notification && $sb_instagram_enable_email_report === 'on' ){
391
+ //Clear the existing cron event
392
+ wp_clear_scheduled_hook('sb_instagram_feed_issue_email');
393
+
394
+ $input = sanitize_text_field($_POST[ 'sb_instagram_email_notification' ] );
395
+ $timestamp = strtotime( 'next ' . $input );
396
+
397
+ if ( $timestamp - (3600 * 1) < time() ) {
398
+ $timestamp = $timestamp + (3600 * 24 * 7);
399
+ }
400
+ $six_am_local = $timestamp + sbi_get_utc_offset() + (6*60*60);
401
+
402
+ wp_schedule_event( $six_am_local, 'sbiweekly', 'sb_instagram_feed_issue_email' );
403
+ }
404
+
405
+
406
+ //Delete all SBI transients
407
+ global $wpdb;
408
+ $table_name = $wpdb->prefix . "options";
409
+ $wpdb->query( "
410
+ DELETE
411
+ FROM $table_name
412
+ WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
413
+ " );
414
+ $wpdb->query( "
415
+ DELETE
416
+ FROM $table_name
417
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
418
+ " );
419
+ $wpdb->query( "
420
+ DELETE
421
+ FROM $table_name
422
+ WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
423
+ " );
424
+ $wpdb->query( "
425
+ DELETE
426
+ FROM $table_name
427
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
428
+ " );
429
+
430
+ if( $sb_instagram_cron == 'no' ) wp_clear_scheduled_hook('sb_instagram_cron_job');
431
+
432
+ //Run cron when Misc settings are saved
433
+ if( $sb_instagram_cron == 'yes' ){
434
+ //Clear the existing cron event
435
+ wp_clear_scheduled_hook('sb_instagram_cron_job');
436
+
437
+ $sb_instagram_cache_time = $options[ 'sb_instagram_cache_time' ];
438
+ $sb_instagram_cache_time_unit = $options[ 'sb_instagram_cache_time_unit' ];
439
+
440
+ //Set the event schedule based on what the caching time is set to
441
+ $sb_instagram_cron_schedule = 'hourly';
442
+ if( $sb_instagram_cache_time_unit == 'hours' && $sb_instagram_cache_time > 5 ) $sb_instagram_cron_schedule = 'twicedaily';
443
+ if( $sb_instagram_cache_time_unit == 'days' ) $sb_instagram_cron_schedule = 'daily';
444
+
445
+ wp_schedule_event(time(), $sb_instagram_cron_schedule, 'sb_instagram_cron_job');
446
+
447
+ sb_instagram_clear_page_caches();
448
+ }
449
+
450
+ } //End customize tab post
451
+
452
+ //Save the settings to the settings array
453
+ update_option( 'sb_instagram_settings', $options );
454
+
455
+ ?>
456
+ <div class="updated"><p><strong><?php _e( 'Settings saved.', 'instagram-feed' ); ?></strong></p></div>
457
+ <?php } ?>
458
+
459
+ <?php } //End nonce check ?>
460
+
461
+
462
+ <div id="sbi_admin" class="wrap">
463
+ <?php
464
+ $lite_notice_dismissed = get_transient( 'instagram_feed_dismiss_lite' );
465
+
466
+ if ( ! $lite_notice_dismissed ) :
467
+ ?>
468
+ <div id="sbi-notice-bar" style="display:none">
469
+ <span class="sbi-notice-bar-message"><?php _e( 'You\'re using Instagram Feed Lite. To unlock more features consider <a href="https://smashballoon.com/instagram-feed/?utm_source=WordPress&utm_campaign=instagramliteplugin&utm_medium=notice-bar" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.', 'instagram-feed'); ?></span>
470
+ <button type="button" class="dismiss" title="<?php _e( 'Dismiss this message.', 'instagram-feed'); ?>" data-page="overview">
471
+ </button>
472
+ </div>
473
+ <?php endif; ?>
474
+ <div id="header">
475
+ <h1><?php _e( 'Instagram Feed', 'instagram-feed' ); ?></h1>
476
+ </div>
477
+ <?php
478
+ $sb_instagram_type = 'user';
479
+ $returned_data = sbi_get_connected_accounts_data( $sb_instagram_at );
480
+ $sb_instagram_at = $returned_data['access_token'];
481
+ $connected_accounts = $returned_data['connected_accounts'];
482
+ $user_feeds_returned = isset( $returned_data['user_ids'] ) ? $returned_data['user_ids'] : false;
483
+ if ( $user_feeds_returned ) {
484
+ $user_feed_ids = $user_feeds_returned;
485
+ } else {
486
+ $user_feed_ids = ! is_array( $sb_instagram_user_id ) ? explode( ',', $sb_instagram_user_id ) : $sb_instagram_user_id;
487
+ }
488
+
489
+ $new_user_name = false;
490
+
491
+
492
+
493
+
494
+ if( isset($_GET['access_token']) && isset($_GET['graph_api']) && empty($_POST) ) { ?>
495
+ <?php
496
+ $access_token = sbi_maybe_clean(urldecode($_GET['access_token']));
497
+ //
498
+ $url = 'https://graph.facebook.com/me/accounts?fields=instagram_business_account,access_token&limit=500&access_token='.$access_token;
499
+ $args = array(
500
+ 'timeout' => 60,
501
+ 'sslverify' => false
502
+ );
503
+ $result = wp_remote_get( $url, $args );
504
+ $pages_data = '{}';
505
+ if ( ! is_wp_error( $result ) ) {
506
+ $pages_data = $result['body'];
507
+ } else {
508
+ $page_error = $result;
509
+ }
510
+
511
+ $pages_data_arr = json_decode($pages_data);
512
+ $num_accounts = 0;
513
+ if(isset($pages_data_arr)){
514
+ $num_accounts = is_array( $pages_data_arr->data ) ? count( $pages_data_arr->data ) : 0;
515
+ }
516
+ ?>
517
+ <div id="sbi_config_info" class="sb_list_businesses sbi_num_businesses_<?php echo $num_accounts; ?>">
518
+ <div class="sbi_config_modal">
519
+ <div class="sbi-managed-pages">
520
+ <?php if ( isset( $page_error ) && isset( $page_error->errors ) ) {
521
+ foreach ($page_error->errors as $key => $item) {
522
+ echo '<div class="sbi_user_id_error" style="display:block;"><strong>Connection Error: </strong>' . $key . ': ' . $item[0] . '</div>';
523
+ }
524
+ }
525
+ ?>
526
+ <?php if( empty($pages_data_arr->data) ) : ?>
527
+ <span id="sbi-bus-account-error">
528
+ <p style="margin-top: 5px;"><b style="font-size: 16px">Couldn't find Business Profile</b><br />
529
+ Uh oh. It looks like this Facebook account is not currently connected to an Instagram Business profile. Please check that you are logged into the <a href="https://www.facebook.com/" target="_blank">Facebook account</a> in this browser which is associated with your Instagram Business Profile.</p>
530
+ <p><b style="font-size: 16px">Why do I need a Business Profile?</b><br />
531
+ A Business Profile is only required if you are displaying a Hashtag feed. If you want to display a regular User feed then you can do this by selecting to connect a Personal account instead. For directions on how to convert your Personal profile into a Business profile please <a href="https://smashballoon.com/instagram-business-profiles" target="_blank">see here</a>.</p>
532
+ </span>
533
+
534
+ <?php elseif ( $num_accounts === 0 ): ?>
535
+ <span id="sbi-bus-account-error">
536
+ <p style="margin-top: 5px;"><b style="font-size: 16px">Couldn't find Business Profile</b><br />
537
+ Uh oh. It looks like this Facebook account is not currently connected to an Instagram Business profile. Please check that you are logged into the <a href="https://www.facebook.com/" target="_blank">Facebook account</a> in this browser which is associated with your Instagram Business Profile.</p>
538
+ <p>If you are, in fact, logged-in to the correct account please make sure you have Instagram accounts connected with your Facebook account by following <a href="https://smashballoon.com/reconnecting-an-instagram-business-profile/" target="_blank">this FAQ</a></p>
539
+ </span>
540
+ <?php else: ?>
541
+ <p class="sbi-managed-page-intro"><b style="font-size: 16px;">Instagram Business profiles for this account</b><br /><i style="color: #666;">Note: In order to display a Hashtag feed you first need to select a Business profile below.</i></p>
542
+ <?php if ( $num_accounts > 1 ) : ?>
543
+ <div class="sbi-managed-page-select-all"><input type="checkbox" id="sbi-select-all" class="sbi-select-all"><label for="sbi-select-all">Select All</label></div>
544
+ <?php endif; ?>
545
+ <div class="sbi-scrollable-accounts">
546
+
547
+ <?php foreach ( $pages_data_arr->data as $page => $page_data ) : ?>
548
+
549
+ <?php if( isset( $page_data->instagram_business_account ) ) :
550
+
551
+ $instagram_business_id = $page_data->instagram_business_account->id;
552
+
553
+ $page_access_token = isset( $page_data->access_token ) ? $page_data->access_token : '';
554
+
555
+ //Make another request to get page info
556
+ $instagram_account_url = 'https://graph.facebook.com/'.$instagram_business_id.'?fields=name,username,profile_picture_url&access_token='.$access_token;
557
+
558
+ $args = array(
559
+ 'timeout' => 60,
560
+ 'sslverify' => false
561
+ );
562
+ $result = wp_remote_get( $instagram_account_url, $args );
563
+ $instagram_account_info = '{}';
564
+ if ( ! is_wp_error( $result ) ) {
565
+ $instagram_account_info = $result['body'];
566
+ } else {
567
+ $page_error = $result;
568
+ }
569
+
570
+ $instagram_account_data = json_decode($instagram_account_info);
571
+
572
+ $instagram_biz_img = isset( $instagram_account_data->profile_picture_url ) ? $instagram_account_data->profile_picture_url : false;
573
+ $selected_class = $instagram_business_id == $sb_instagram_user_id ? ' sbi-page-selected' : '';
574
+
575
+ ?>
576
+ <?php if ( isset( $page_error ) && isset( $page_error->errors ) ) :
577
+ foreach ($page_error->errors as $key => $item) {
578
+ echo '<div class="sbi_user_id_error" style="display:block;"><strong>Connection Error: </strong>' . $key . ': ' . $item[0] . '</div>';
579
+ }
580
+ else : ?>
581
+ <div class="sbi-managed-page<?php echo $selected_class; ?>" data-page-token="<?php echo esc_attr( $page_access_token ); ?>" data-token="<?php echo esc_attr( $access_token ); ?>" data-page-id="<?php echo esc_attr( $instagram_business_id ); ?>">
582
+ <div class="sbi-add-checkbox">
583
+ <input id="sbi-<?php echo esc_attr( $instagram_business_id ); ?>" type="checkbox" name="sbi_managed_pages[]" value="<?php echo esc_attr( $instagram_account_info ); ?>">
584
+ </div>
585
+ <div class="sbi-managed-page-details">
586
+ <label for="sbi-<?php echo esc_attr( $instagram_business_id ); ?>"><img class="sbi-page-avatar" border="0" height="50" width="50" src="<?php echo esc_url( $instagram_biz_img ); ?>"><b style="font-size: 16px;"><?php echo esc_html( $instagram_account_data->name ); ?></b>
587
+ <br />@<?php echo esc_html( $instagram_account_data->username); ?><span style="font-size: 11px; margin-left: 5px;">(<?php echo esc_html( $instagram_business_id ); ?>)</span></label>
588
+ </div>
589
+ </div>
590
+ <?php endif; ?>
591
+
592
+ <?php endif; ?>
593
+
594
+ <?php endforeach; ?>
595
+
596
+ </div> <!-- end scrollable -->
597
+ <a href="JavaScript:void(0);" id="sbi-connect-business-accounts" class="button button-primary" disabled="disabled" style="margin-top: 20px;">Connect Accounts</a>
598
+
599
+ <?php endif; ?>
600
+
601
+ <a href="JavaScript:void(0);" class="sbi_modal_close"><i class="fa fa-times"></i></a>
602
+ </div>
603
+ </div>
604
+ </div>
605
+ <?php } elseif ( isset( $_GET['access_token'] ) && isset( $_GET['account_type'] ) && empty( $_POST ) ) {
606
+ $access_token = sanitize_text_field( $_GET['access_token'] );
607
+ $account_type = sanitize_text_field( $_GET['account_type'] );
608
+ $user_id = sanitize_text_field( $_GET['id'] );
609
+ $user_name = sanitize_text_field( $_GET['username'] );
610
+ $expires_in = (int)$_GET['expires_in'];
611
+ $expires_timestamp = time() + $expires_in;
612
+
613
+ $new_account_details = array(
614
+ 'access_token' => $access_token,
615
+ 'account_type' => $account_type,
616
+ 'user_id' => $user_id,
617
+ 'username' => $user_name,
618
+ 'expires_timestamp' => $expires_timestamp,
619
+ 'type' => 'basic'
620
+ );
621
+
622
+
623
+ $matches_existing_personal = sbi_matches_existing_personal( $new_account_details );
624
+ $button_text = $matches_existing_personal ? __( 'Update This Account', 'instagram-feed' ) : __( 'Connect This Account', 'instagram-feed' );
625
+
626
+ $account_json = wp_json_encode( $new_account_details );
627
+
628
+ $already_connected_as_business_account = (isset( $connected_accounts[ $user_id ] ) && $connected_accounts[ $user_id ]['type'] === 'business');
629
+
630
+ ?>
631
+
632
+ <div id="sbi_config_info" class="sb_get_token">
633
+ <div class="sbi_config_modal">
634
+ <div class="sbi_ca_username"><strong><?php echo esc_html( $user_name ); ?></strong></div>
635
+ <form action="<?php echo admin_url( 'admin.php?page=sb-instagram-feed' ); ?>" method="post">
636
+ <p class="sbi_submit">
637
+ <?php if ( $already_connected_as_business_account ) :
638
+ _e( 'The Instagram account you are logged into is already connected as a "business" account. Remove the business account if you\'d like to connect as a basic account instead (not recommended).', 'instagram-feed' );
639
+ ?>
640
+ <?php else : ?>
641
+ <input type="submit" name="sbi_submit" id="sbi_connect_account" class="button button-primary" value="<?php echo esc_html( $button_text ); ?>">
642
+ <?php endif; ?>
643
+ <input type="hidden" name="sbi_account_json" value="<?php echo esc_attr( $account_json ) ; ?>">
644
+ <input type="hidden" name="sbi_connect_username" value="<?php echo esc_attr( $user_name ); ?>">
645
+ <a href="JavaScript:void(0);" class="button button-secondary" id="sbi_switch_accounts"><?php esc_html_e( 'Switch Accounts', 'instagram-feed' ); ?></a>
646
+ </p>
647
+ </form>
648
+ <a href="JavaScript:void(0);"><i class="sbi_modal_close fa fa-times"></i></a>
649
+ </div>
650
+ </div>
651
+ <?php
652
+ } elseif ( isset( $_POST['sbi_connect_username'] ) ) {
653
+
654
+ $new_user_name = sanitize_text_field( $_POST['sbi_connect_username'] );
655
+ $new_account_details = json_decode( stripslashes( $_POST['sbi_account_json'] ), true );
656
+ array_map( 'sanitize_text_field', $new_account_details );
657
+
658
+ $updated_options = sbi_connect_basic_account( $new_account_details );
659
+ $connected_accounts = $updated_options['connected_accounts'];
660
+ $user_feed_ids = $updated_options['sb_instagram_user_id'];
661
+ }?>
662
+
663
+ <?php //Display connected page
664
+ if (isset( $sbi_connected_page ) && strpos($sbi_connected_page, ':') !== false) {
665
+
666
+ $sbi_connected_page_pieces = explode(":", $sbi_connected_page);
667
+ $sbi_connected_page_id = $sbi_connected_page_pieces[0];
668
+ $sbi_connected_page_name = $sbi_connected_page_pieces[1];
669
+ $sbi_connected_page_image = $sbi_connected_page_pieces[2];
670
+
671
+ echo '&nbsp;';
672
+ echo '<p style="font-weight: bold; margin-bottom: 5px;">Connected Business Profile:</p>';
673
+ echo '<div class="sbi-managed-page sbi-no-select">';
674
+ echo '<p><img class="sbi-page-avatar" border="0" height="50" width="50" src="'.$sbi_connected_page_image.'"><b>'.$sbi_connected_page_name.'</b> &nbsp; ('.$sbi_connected_page_id.')</p>';
675
+ echo '</div>';
676
+ }
677
+
678
+ ?>
679
+
680
+ <form name="form1" method="post" action="">
681
+ <input type="hidden" name="<?php echo $sb_instagram_settings_hidden_field; ?>" value="Y">
682
+ <?php wp_nonce_field( 'sb_instagram_saving_settings', 'sb_instagram_settings_nonce' ); ?>
683
+
684
+ <?php $sbi_active_tab = isset( $_GET[ 'tab' ] ) ? sanitize_text_field( $_GET['tab'] ) : 'configure'; ?>
685
+ <h2 class="nav-tab-wrapper">
686
+ <a href="?page=sb-instagram-feed&amp;tab=configure" class="nav-tab <?php echo $sbi_active_tab == 'configure' ? 'nav-tab-active' : ''; ?>"><?php _e( '1. Configure', 'instagram-feed' ); ?></a>
687
+ <a href="?page=sb-instagram-feed&amp;tab=customize" class="nav-tab <?php echo $sbi_active_tab == 'customize' ? 'nav-tab-active' : ''; ?>"><?php _e( '2. Customize', 'instagram-feed' ); ?></a>
688
+ <a href="?page=sb-instagram-feed&amp;tab=display" class="nav-tab <?php echo $sbi_active_tab == 'display' ? 'nav-tab-active' : ''; ?>"><?php _e( '3. Display Your Feed', 'instagram-feed' ); ?></a>
689
+ <a href="?page=sb-instagram-feed&amp;tab=support" class="nav-tab <?php echo $sbi_active_tab == 'support' ? 'nav-tab-active' : ''; ?>"><?php _e( 'Support', 'instagram-feed' ); ?></a>
690
+ </h2>
691
+
692
+ <?php if( $sbi_active_tab == 'configure' ) { //Start Configure tab ?>
693
+ <input type="hidden" name="<?php echo $sb_instagram_configure_hidden_field; ?>" value="Y">
694
+
695
+ <table class="form-table">
696
+ <tbody>
697
+ <h3><?php _e( 'Configure', 'instagram-feed' ); ?></h3>
698
+
699
+ <div id="sbi_config">
700
+ <a data-personal-basic-api="https://api.instagram.com/oauth/authorize?app_id=423965861585747&redirect_uri=https://api.smashballoon.com/instagram-basic-display-redirect.php&response_type=code&scope=user_profile,user_media&state=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>"
701
+ data-new-api="https://www.facebook.com/dialog/oauth?client_id=254638078422287&redirect_uri=https://api.smashballoon.com/instagram-graph-api-redirect.php&scope=manage_pages,instagram_basic,instagram_manage_insights,instagram_manage_comments&state=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>"
702
+ data-old-api="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>&hl=en"
703
+ href="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>&hl=en" class="sbi_admin_btn"><i class="fa fa-user-plus" aria-hidden="true" style="font-size: 20px;"></i>&nbsp; <?php _e('Connect an Instagram Account', 'instagram-feed' ); ?></a>
704
+
705
+ <!--<a href="https://instagram.com/oauth/authorize/?client_id=3a81a9fa2a064751b8c31385b91cc25c&scope=basic&redirect_uri=https://smashballoon.com/instagram-feed/instagram-token-plugin/?return_uri=<?php echo admin_url('admin.php?page=sb-instagram-feed'); ?>&response_type=token&state=<?php echo admin_url('admin.php?page-sb-instagram-feed'); ?>" class="sbi_admin_btn"><i class="fa fa-user-plus" aria-hidden="true" style="font-size: 20px;"></i>&nbsp; <?php _e('Connect an Instagram Account', 'instagram-feed' ); ?></a>
706
+ -->
707
+ <a href="https://smashballoon.com/instagram-feed/token/" target="_blank" style="position: relative; top: 14px; left: 15px;"><?php _e('Button not working?', 'instagram-feed'); ?></a>
708
+ </div>
709
+
710
+ <!-- Old Access Token -->
711
+ <input name="sb_instagram_at" id="sb_instagram_at" type="hidden" value="<?php echo esc_attr( $sb_instagram_at ); ?>" size="80" maxlength="100" placeholder="Click button above to get your Access Token" />
712
+
713
+ <tr valign="top">
714
+ <th scope="row"><label><?php _e( 'Instagram Accounts', 'instagram-feed' ); ?></label><span style="font-weight:normal; font-style:italic; font-size: 12px; display: block;"><?php _e('Use the button above to connect an Instagram account', 'instagram-feed'); ?></span></th>
715
+ <td class="sbi_connected_accounts_wrap">
716
+ <?php if ( empty( $connected_accounts ) ) : ?>
717
+ <p class="sbi_no_accounts"><?php _e( 'No Instagram accounts connected. Click the button above to connect an account.', 'instagram-feed' ); ?></p><br />
718
+ <?php else:
719
+ if ( sbi_is_after_deprecation_deadline() ) {
720
+ $deprecated_connected_account_message = __( '<b>Action Needed:</b> Reconnect this account to allow feed to update.', 'instagram-feed' );
721
+ } else {
722
+ $deprecated_connected_account_message = __( '<b>Action Needed:</b> Reconnect this account before March 31, 2020 to avoid disruption with this feed.', 'instagram-feed' );
723
+ }
724
+
725
+ $accounts_that_need_updating = sbi_get_user_names_of_personal_accounts_not_also_already_updated();
726
+ ?>
727
+ <?php foreach ( $connected_accounts as $account ) :
728
+ $username = $account['username'] ? $account['username'] : $account['user_id'];
729
+ if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['sb_instagram_favor_local'] ) && $options['sb_instagram_favor_local' ] === 'on' ) {
730
+ $upload = wp_upload_dir();
731
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
732
+ $profile_picture = '<img class="sbi_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
733
+ } else {
734
+ $profile_picture = $account['profile_picture'] ? '<img class="sbi_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
735
+ }
736
+
737
+ $is_invalid_class = ! $account['is_valid'] ? ' sbi_account_invalid' : '';
738
+ $in_user_feed = in_array( $account['user_id'], $user_feed_ids, true );
739
+ $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
740
+ $use_tagged = isset( $account['use_tagged'] ) && $account['use_tagged'] == '1';
741
+
742
+ if ( empty( $profile_picture ) && $account_type === 'personal' ) {
743
+ $account_update = sbi_account_data_for_token( $account['access_token'] );
744
+ if ( isset( $account['is_valid'] ) ) {
745
+ $split = explode( '.', $account['access_token'] );
746
+ $connected_accounts[ $split[0] ] = array(
747
+ 'access_token' => $account['access_token'],
748
+ 'user_id' => $split[0],
749
+ 'username' => $account_update['username'],
750
+ 'is_valid' => true,
751
+ 'last_checked' => time(),
752
+ 'profile_picture' => $account_update['profile_picture']
753
+ );
754
+
755
+ $sbi_options = get_option( 'sb_instagram_settings', array() );
756
+ $sbi_options['connected_accounts'] = $connected_accounts;
757
+ update_option( 'sb_instagram_settings', $sbi_options );
758
+ }
759
+
760
+ }
761
+ $updated_or_new_account_class = $new_user_name === $username && $account_type !== 'business' ? ' sbi_ca_new_or_updated' : '';
762
+
763
+ ?>
764
+ <div class="sbi_connected_account<?php echo $is_invalid_class . $updated_or_new_account_class; ?><?php if ( $in_user_feed ) echo ' sbi_account_active' ?> sbi_account_type_<?php echo $account_type; ?>" id="sbi_connected_account_<?php esc_attr_e( $account['user_id'] ); ?>" data-accesstoken="<?php esc_attr_e( $account['access_token'] ); ?>" data-userid="<?php esc_attr_e( $account['user_id'] ); ?>" data-username="<?php esc_attr_e( $account['username'] ); ?>" data-type="<?php esc_attr_e( $account_type ); ?>" data-permissions="<?php if ( $use_tagged ) echo 'tagged'; ?>">
765
+ <?php if ( $account_type === 'personal' && in_array( $username, $accounts_that_need_updating, true ) ) : ?>
766
+ <div class="sbi_deprecated">
767
+ <span><i class="fa fa-exclamation-circle" aria-hidden="true"></i><?php echo $deprecated_connected_account_message; ?> <button class="sbi_reconnect button-primary">Reconnect</button></span>
768
+ </div>
769
+ <?php endif; ?>
770
+ <div class="sbi_ca_alert">
771
+ <span><?php _e( 'The Access Token for this account is expired or invalid. Click the button above to attempt to renew it.', 'instagram-feed' ) ?></span>
772
+ </div>
773
+ <div class="sbi_ca_info">
774
+
775
+ <div class="sbi_ca_delete">
776
+ <a href="JavaScript:void(0);" class="sbi_delete_account"><i class="fa fa-times"></i><span class="sbi_remove_text"><?php _e( 'Remove', 'instagram-feed' ); ?></span></a>
777
+ </div>
778
+
779
+ <div class="sbi_ca_username">
780
+ <?php echo $profile_picture; ?>
781
+ <strong><?php echo $username; ?><span><?php echo sbi_account_type_display( $account_type ); ?></span></strong>
782
+ </div>
783
+
784
+ <div class="sbi_ca_actions">
785
+ <?php if ( ! $in_user_feed ) : ?>
786
+ <a href="JavaScript:void(0);" class="sbi_use_in_user_feed button-primary"><i class="fa fa-plus-circle" aria-hidden="true"></i><?php _e( 'Add to Primary Feed', 'instagram-feed' ); ?></a>
787
+ <?php else : ?>
788
+ <a href="JavaScript:void(0);" class="sbi_remove_from_user_feed button-primary"><i class="fa fa-minus-circle" aria-hidden="true"></i><?php _e( 'Remove from Primary Feed', 'instagram-feed' ); ?></a>
789
+ <?php endif; ?>
790
+ <a class="sbi_ca_token_shortcode button-secondary" href="JavaScript:void(0);"><i class="fa fa-chevron-circle-right" aria-hidden="true"></i><?php _e( 'Add to another Feed', 'instagram-feed' ); ?></a>
791
+ <a class="sbi_ca_show_token button-secondary" href="JavaScript:void(0);" title="<?php _e('Show access token and account info', 'instagram-feed'); ?>"><i class="fa fa-cog"></i></a>
792
+
793
+ </div>
794
+
795
+ <div class="sbi_ca_shortcode">
796
+
797
+ <p><?php _e('Copy and paste this shortcode into your page or widget area', 'instagram-feed'); ?>:<br>
798
+ <?php if ( !empty( $account['username'] ) ) : ?>
799
+ <code>[instagram-feed user="<?php echo $account['username']; ?>"]</code>
800
+ <?php else : ?>
801
+ <code>[instagram-feed accesstoken="<?php echo $account['access_token']; ?>"]</code>
802
+ <?php endif; ?>
803
+ </p>
804
+
805
+ <p><?php _e('To add multiple users in the same feed, simply separate them using commas', 'instagram-feed'); ?>:<br>
806
+ <?php if ( !empty( $account['username'] ) ) : ?>
807
+ <code>[instagram-feed user="<?php echo $account['username']; ?>, a_second_user, a_third_user"]</code>
808
+ <?php else : ?>
809
+ <code>[instagram-feed accesstoken="<?php echo $account['access_token']; ?>, another_access_token"]</code>
810
+ <?php endif; ?>
811
+
812
+ <p><?php echo sprintf( __('Click on the %s tab to learn more about shortcodes', 'instagram-feed'), '<a href="?page=sb-instagram-feed&tab=display" target="_blank">'. __( 'Display Your Feed', 'instagram-feed' ) . '</a>' ); ?></p>
813
+ </div>
814
+
815
+ <div class="sbi_ca_accesstoken">
816
+ <span class="sbi_ca_token_label"><?php _e('Access Token', 'instagram-feed');?>:</span><input type="text" class="sbi_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).', 'instagram-feed');?>"><br>
817
+ <span class="sbi_ca_token_label"><?php _e('User ID', 'instagram-feed');?>:</span><input type="text" class="sbi_ca_user_id" value="<?php echo $account['user_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).', 'instagram-feed');?>"><br>
818
+ </div>
819
+
820
+ </div>
821
+
822
+ </div>
823
+
824
+ <?php endforeach; ?>
825
+ <?php endif; ?>
826
+ <a href="JavaScript:void(0);" class="sbi_manually_connect button-secondary"><?php _e( 'Manually Connect an Account', 'instagram-feed' ); ?></a>
827
+ <div class="sbi_manually_connect_wrap">
828
+ <input name="sb_manual_at" id="sb_manual_at" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="64" minlength="15" maxlength="200" placeholder="Enter a valid Instagram Access Token" /><span class='sbi_business_profile_tag'><?php _e('Business or Basic Display', 'instagram-feed');?></span>
829
+ <div class="sbi_manual_account_id_toggle">
830
+ <label><?php _e('Please enter the User ID for this Profile:', 'instagram-feed');?></label>
831
+ <input name="sb_manual_account_id" id="sb_manual_account_id" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="40" minlength="5" maxlength="100" placeholder="Eg: 15641403491391489" />
832
+ </div>
833
+ <p class="sbi_submit" style="display: inline-block;"><input type="sbi_submit" name="submit" id="sbi_manual_submit" class="button button-primary" style="text-align: center; padding: 0;" value="<?php _e('Connect This Account', 'instagram-feed' );?>"></p>
834
+ </div>
835
+ </td>
836
+ </tr>
837
+
838
+ <tr valign="top" class="sbi_feed_type">
839
+ <th scope="row"><label><?php _e('Show Photos From:', 'instagram-feed'); ?></label><code class="sbi_shortcode"> type
840
+ Eg: type=user id=12986477
841
+ </code></th>
842
+ <td>
843
+ <div class="sbi_row">
844
+ <div class="sbi_col sbi_one">
845
+ <input type="radio" name="sb_instagram_type" id="sb_instagram_type_user" value="user" <?php if($sb_instagram_type == "user") echo "checked"; ?> />
846
+ <label class="sbi_radio_label" for="sb_instagram_type_user"><?php _e( 'User Account:', 'instagram-feed' ); ?></label>
847
+ </div>
848
+ <div class="sbi_col sbi_two">
849
+ <div class="sbi_user_feed_ids_wrap">
850
+ <?php foreach ( $user_feed_ids as $feed_id ) : if ( $feed_id !== '' ) :?>
851
+ <?php if( count($connected_accounts) > 0 ) { ?><div id="sbi_user_feed_id_<?php echo $feed_id; ?>" class="sbi_user_feed_account_wrap"><?php } ?>
852
+
853
+ <?php if ( isset( $connected_accounts[ $feed_id ] ) && ! empty( $connected_accounts[ $feed_id ]['username'] ) ) : ?>
854
+ <strong><?php echo $connected_accounts[ $feed_id ]['username']; ?></strong> <span>(<?php echo $feed_id; ?>)</span>
855
+ <input name="sb_instagram_user_id[]" id="sb_instagram_user_id" type="hidden" value="<?php echo esc_attr( $feed_id ); ?>" />
856
+ <?php elseif ( isset( $connected_accounts[ $feed_id ] ) && ! empty( $connected_accounts[ $feed_id ]['access_token'] ) ) : ?>
857
+ <strong><?php echo $feed_id; ?></strong>
858
+ <input name="sb_instagram_user_id[]" id="sb_instagram_user_id" type="hidden" value="<?php echo esc_attr( $feed_id ); ?>" />
859
+ <?php endif; ?>
860
+
861
+ <?php if( count($connected_accounts) > 0 ) { ?></div><?php } ?>
862
+ <?php endif; endforeach; ?>
863
+ </div>
864
+
865
+ <?php if ( empty( $user_feed_ids ) ) : ?>
866
+ <p class="sbi_no_accounts" style="margin-top: -3px; margin-right: 10px;"><?php _e( 'Connect a user account above', 'instagram-feed' ); ?></p>
867
+ <?php endif; ?>
868
+
869
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);" style="margin: 5px 0 10px 0; display: inline-block; height: 19px;"><?php _e("How to display User feeds", 'instagram-feed' ); ?></a>
870
+ <div class="sbi_tooltip"><?php _e("<p><b>Displaying Posts from Your User Account</b><br />Simply connect an account using the button above.</p><p style='padding-top:8px;'><b>Displaying Posts from Other Instagram Accounts</b><br />Due to recent changes in the Instagram API it is no longer possible to display photos from other Instagram accounts which you do not have access to. You can only display the user feed of an account which you connect above. You can connect as many account as you like by logging in using the button above, or manually copy/pasting an Access Token by selecting the 'Manually Connect an Account' option.</p><p style='padding-top:10px;'><b>Multiple Acounts</b><br />It is only possible to display feeds from Instagram accounts which you own. In order to display feeds from multiple accounts, first connect them above and then use the buttons to add the account either to your primary feed or to another feed on your site.</p>", 'instagram-feed'); ?></div><br />
871
+ </div>
872
+
873
+ </div>
874
+
875
+ <div class="sbi_pro sbi_row">
876
+ <div class="sbi_col sbi_one">
877
+ <input disabled type="radio" name="sb_instagram_type" id="sb_instagram_type_hashtag" value="hashtag" <?php if($sb_instagram_type == "hashtag") echo "checked"; ?> />
878
+ <label class="sbi_radio_label" for="sb_instagram_type_hashtag"><?php _e( 'Hashtag:', 'instagram-feed' ); ?></label>
879
+ </div>
880
+ <div class="sbi_col sbi_two">
881
+
882
+ <p class="sbi_pro_tooltip"><?php _e( 'Upgrade to the Pro version to display Hashtag and Tagged feeds', 'instagram-feed' ); ?><i class="fa fa-caret-down" aria-hidden="true"></i></p>
883
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi_lock"><i class="fa fa-rocket"></i><?php _e('Pro', 'instagram-feed'); ?></a>
884
+
885
+ <input readonly type="text" size="25" style="height: 32px; top: -2px; position: relative; box-shadow: none;" disabled />
886
+ &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed' ); ?></a>
887
+
888
+ <p class="sbi_tooltip"><?php _e( 'Display posts from a specific hashtag instead of from a user', 'instagram-feed' ); ?></p>
889
+ </div>
890
+ </div>
891
+
892
+ <div class="sbi_pro sbi_row">
893
+ <div class="sbi_col sbi_one">
894
+ <input disabled type="radio" name="sb_instagram_type" id="sb_instagram_type_tagged" value="tagged" <?php if($sb_instagram_type == "tagged") echo "checked"; ?> />
895
+ <label class="sbi_radio_label" for="sb_instagram_type_tagged"><?php _e( 'Tagged:', 'instagram-feed' ); ?></label>
896
+ </div>
897
+ <div class="sbi_col sbi_two">
898
+ <input readonly type="text" size="25" style="height: 32px; top: -2px; position: relative; box-shadow: none;" disabled />
899
+ &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed' ); ?></a>
900
+
901
+ <p class="sbi_tooltip"><?php _e( 'Display posts that your account has been tagged in.', 'instagram-feed' ); ?></p>
902
+ </div>
903
+ </div>
904
+
905
+ <div class="sbi_row sbi_pro">
906
+ <br>
907
+ <a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);" style="margin-left: 0;"><i class="fa fa-question-circle" aria-hidden="true" style="margin-right: 6px;"></i><?php _e('Combine multiple feed types into a single feed', 'instagram-feed'); ?></a>
908
+ <p class="sbi_tooltip">
909
+ <b><?php _e( 'Please note: this is only available in the <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Pro version</a>', 'instagram-feed' ); ?>.</b><br />
910
+ <?php echo sprintf( __('To display multiple feed types in a single feed, use %s in your shortcode and then add each user name or hashtag of each feed into the shortcode, like so: %s. This will combine a user feed and a hashtag feed into the same feed.', 'instagram-feed'), 'type="mixed"', '<code>[instagram-feed type="mixed" user="smashballoon" hashtag="#awesomeplugins"]</code>' ); ?>
911
+ </p>
912
+ </div>
913
+
914
+ </td>
915
+ </tr>
916
+
917
+ <tr>
918
+ <th class="bump-left"><label for="sb_instagram_preserve_settings" class="bump-left"><?php _e("Preserve settings when plugin is removed", 'instagram-feed'); ?></label></th>
919
+ <td>
920
+ <input name="sb_instagram_preserve_settings" type="checkbox" id="sb_instagram_preserve_settings" <?php if($sb_instagram_preserve_settings == true) echo "checked"; ?> />
921
+ <label for="sb_instagram_preserve_settings"><?php _e('Yes', 'instagram-feed'); ?></label>
922
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
923
+ <p class="sbi_tooltip"><?php _e('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.', 'instagram-feed'); ?></p>
924
+ </td>
925
+ </tr>
926
+
927
+
928
+ <tr valign="top" class="sbi_cron_cache_opts">
929
+ <th scope="row"><?php _e( 'Check for new posts', 'instagram-feed' ); ?></th>
930
+ <td>
931
+
932
+ <div class="sbi_row">
933
+ <input type="radio" name="sbi_caching_type" id="sbi_caching_type_page" value="page" <?php if ( $sbi_caching_type === 'page' ) echo 'checked'; ?>>
934
+ <label for="sbi_caching_type_page"><?php _e( 'When the page loads', 'instagram-feed' ); ?></label>
935
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><i class="fa fa-question-circle" aria-hidden="true"></i></a>
936
+ <p class="sbi_tooltip sbi-more-info"><?php _e( 'Your Instagram post 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', 'instagram-feed' ); ?>:<br><br>
937
+ <?php _e( '<b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check Facebook for new posts the next time that the feed is loaded. You can choose how long this data should be cached for. 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.', 'instagram-feed' ); ?>
938
+ <br><br>
939
+ <?php _e( '<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.</p>', 'instagram-feed' ); ?>
940
+ </div>
941
+ <div class="sbi_row sbi-caching-page-options" style="display: none;">
942
+ <?php _e( 'Every', 'instagram-feed' ); ?>:
943
+ <input name="sb_instagram_cache_time" type="text" value="<?php echo esc_attr( $sb_instagram_cache_time ); ?>" size="4" />
944
+ <select name="sb_instagram_cache_time_unit">
945
+ <option value="minutes" <?php if($sb_instagram_cache_time_unit == "minutes") echo 'selected="selected"' ?> ><?php _e('Minutes', 'instagram-feed'); ?></option>
946
+ <option value="hours" <?php if($sb_instagram_cache_time_unit == "hours") echo 'selected="selected"' ?> ><?php _e('Hours', 'instagram-feed'); ?></option>
947
+ <option value="days" <?php if($sb_instagram_cache_time_unit == "days") echo 'selected="selected"' ?> ><?php _e('Days', 'instagram-feed'); ?></option>
948
+ </select>
949
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
950
+ <p class="sbi_tooltip"><?php _e('Your Instagram 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 Instagram for posts again.', 'instagram-feed'); ?></p>
951
+ </div>
952
+
953
+ <div class="sbi_row">
954
+ <input type="radio" name="sbi_caching_type" id="sbi_caching_type_cron" value="background" <?php if ( $sbi_caching_type === 'background' ) echo 'checked'; ?>>
955
+ <label for="sbi_caching_type_cron"><?php _e( 'In the background', 'instagram-feed' ); ?></label>
956
+ </div>
957
+ <div class="sbi_row sbi-caching-cron-options" style="display: block;">
958
+
959
+ <select name="sbi_cache_cron_interval" id="sbi_cache_cron_interval">
960
+ <option value="30mins" <?php if ( $sbi_cache_cron_interval === '30mins' ) echo 'selected'; ?>><?php _e( 'Every 30 minutes', 'instagram-feed' ); ?></option>
961
+ <option value="1hour" <?php if ( $sbi_cache_cron_interval === '1hour' ) echo 'selected'; ?>><?php _e( 'Every hour', 'instagram-feed' ); ?></option>
962
+ <option value="12hours" <?php if ( $sbi_cache_cron_interval === '12hours' ) echo 'selected'; ?>><?php _e( 'Every 12 hours', 'instagram-feed' ); ?></option>
963
+ <option value="24hours" <?php if ( $sbi_cache_cron_interval === '24hours' ) echo 'selected'; ?>><?php _e( 'Every 24 hours', 'instagram-feed' ); ?></option>
964
+ </select>
965
+
966
+ <div id="sbi-caching-time-settings" style="display: none;">
967
+ <?php _e('at' ); ?>
968
+
969
+ <select name="sbi_cache_cron_time" style="width: 80px">
970
+ <option value="1" <?php if ( $sbi_cache_cron_time === '1' ) echo 'selected'; ?>>1:00</option>
971
+ <option value="2" <?php if ( $sbi_cache_cron_time === '2' ) echo 'selected'; ?>>2:00</option>
972
+ <option value="3" <?php if ( $sbi_cache_cron_time === '3' ) echo 'selected'; ?>>3:00</option>
973
+ <option value="4" <?php if ( $sbi_cache_cron_time === '4' ) echo 'selected'; ?>>4:00</option>
974
+ <option value="5" <?php if ( $sbi_cache_cron_time === '5' ) echo 'selected'; ?>>5:00</option>
975
+ <option value="6" <?php if ( $sbi_cache_cron_time === '6' ) echo 'selected'; ?>>6:00</option>
976
+ <option value="7" <?php if ( $sbi_cache_cron_time === '7' ) echo 'selected'; ?>>7:00</option>
977
+ <option value="8" <?php if ( $sbi_cache_cron_time === '8' ) echo 'selected'; ?>>8:00</option>
978
+ <option value="9" <?php if ( $sbi_cache_cron_time === '9' ) echo 'selected'; ?>>9:00</option>
979
+ <option value="10" <?php if ( $sbi_cache_cron_time === '10' ) echo 'selected'; ?>>10:00</option>
980
+ <option value="11" <?php if ( $sbi_cache_cron_time === '11' ) echo 'selected'; ?>>11:00</option>
981
+ <option value="0" <?php if ( $sbi_cache_cron_time === '0' ) echo 'selected'; ?>>12:00</option>
982
+ </select>
983
+
984
+ <select name="sbi_cache_cron_am_pm" style="width: 50px">
985
+ <option value="am" <?php if ( $sbi_cache_cron_am_pm === 'am' ) echo 'selected'; ?>>AM</option>
986
+ <option value="pm" <?php if ( $sbi_cache_cron_am_pm === 'pm' ) echo 'selected'; ?>>PM</option>
987
+ </select>
988
+ </div>
989
+
990
+ <?php
991
+ if ( wp_next_scheduled( 'sbi_feed_update' ) ) {
992
+ $time_format = get_option( 'time_format' );
993
+ if ( ! $time_format ) {
994
+ $time_format = 'g:i a';
995
+ }
996
+ //
997
+ $schedule = wp_get_schedule( 'sbi_feed_update' );
998
+ if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', 'instagram-feed' );
999
+ if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', 'instagram-feed' );
1000
+ $sbi_next_cron_event = wp_next_scheduled( 'sbi_feed_update' );
1001
+ echo '<p class="sbi-caching-sched-notice"><span><b>' . __( 'Next check', 'instagram-feed' ) . ': ' . date( $time_format, $sbi_next_cron_event + sbi_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', 'instagram-feed' ) . '</span></p>';
1002
+ } else {
1003
+ echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', 'instagram-feed' ) . '</p>';
1004
+ }
1005
+ ?>
1006
+
1007
+ </div>
1008
+
1009
+ </td>
1010
+ </tr>
1011
+
1012
+ </tbody>
1013
+ </table>
1014
+
1015
+ <?php submit_button(); ?>
1016
+ </form>
1017
+
1018
+ <p><i class="fa fa-chevron-circle-right" aria-hidden="true"></i>&nbsp; <?php _e('Next Step: <a href="?page=sb-instagram-feed&tab=customize">Customize your Feed</a>', 'instagram-feed'); ?></p>
1019
+
1020
+ <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
1021
+
1022
+
1023
+ <?php } // End Configure tab ?>
1024
+
1025
+
1026
+
1027
+ <?php if( $sbi_active_tab == 'customize' ) { //Start Configure tab ?>
1028
+
1029
+ <p class="sb_instagram_contents_links" id="general">
1030
+ <span><?php _e( 'Quick links:', 'instagram-feed' ); ?> </span>
1031
+ <a href="#general"><?php _e( 'General', 'instagram-feed' ); ?></a>
1032
+ <a href="#layout"><?php _e( 'Layout', 'instagram-feed' ); ?></a>
1033
+ <a href="#photos"><?php _e( 'Photos', 'instagram-feed' ); ?></a>
1034
+ <a href="#headeroptions"><?php _e( 'Header', 'instagram-feed' ); ?></a>
1035
+ <a href="#loadmore"><?php _e( "'Load More' Button", 'instagram-feed' ); ?></a>
1036
+ <a href="#follow"><?php _e( "'Follow' Button", 'instagram-feed' ); ?></a>
1037
+ <a href="#customcss"><?php _e( 'Custom CSS', 'instagram-feed' ); ?></a>
1038
+ <a href="#customjs"><?php _e( 'Custom JavaScript', 'instagram-feed' ); ?></a>
1039
+ </p>
1040
+
1041
+ <input type="hidden" name="<?php echo $sb_instagram_customize_hidden_field; ?>" value="Y">
1042
+
1043
+ <h3><?php _e( 'General', 'instagram-feed' ); ?></h3>
1044
+
1045
+ <table class="form-table">
1046
+ <tbody>
1047
+ <tr valign="top">
1048
+ <th scope="row"><label><?php _e('Width of Feed', 'instagram-feed'); ?></label><code class="sbi_shortcode"> width widthunit
1049
+ Eg: width=50 widthunit=%</code></th>
1050
+ <td>
1051
+ <input name="sb_instagram_width" type="text" value="<?php echo esc_attr( $sb_instagram_width ); ?>" id="sb_instagram_width" size="4" maxlength="4" />
1052
+ <select name="sb_instagram_width_unit" id="sb_instagram_width_unit">
1053
+ <option value="px" <?php if($sb_instagram_width_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1054
+ <option value="%" <?php if($sb_instagram_width_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1055
+ </select>
1056
+ <div id="sb_instagram_width_options">
1057
+ <input name="sb_instagram_feed_width_resp" type="checkbox" id="sb_instagram_feed_width_resp" <?php if($sb_instagram_feed_width_resp == true) echo "checked"; ?> /><label for="sb_instagram_feed_width_resp"><?php _e('Set to be 100% width on mobile?', 'instagram-feed'); ?></label>
1058
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does this mean?', 'instagram-feed' ); ?></a>
1059
+ <p class="sbi_tooltip"><?php _e("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.", 'instagram-feed'); ?></p>
1060
+ </div>
1061
+ </td>
1062
+ </tr>
1063
+ <tr valign="top">
1064
+ <th scope="row"><label><?php _e('Height of Feed', 'instagram-feed'); ?></label><code class="sbi_shortcode"> height heightunit
1065
+ Eg: height=500 heightunit=px</code></th>
1066
+ <td>
1067
+ <input name="sb_instagram_height" type="text" value="<?php echo esc_attr( $sb_instagram_height ); ?>" size="4" maxlength="4" />
1068
+ <select name="sb_instagram_height_unit">
1069
+ <option value="px" <?php if($sb_instagram_height_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1070
+ <option value="%" <?php if($sb_instagram_height_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1071
+ </select>
1072
+ </td>
1073
+ </tr>
1074
+ <tr valign="top">
1075
+ <th scope="row"><label><?php _e('Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> background
1076
+ Eg: background=d89531</code></th>
1077
+ <td>
1078
+ <input name="sb_instagram_background" type="text" value="<?php echo esc_attr( $sb_instagram_background ); ?>" class="sbi_colorpick" />
1079
+ </td>
1080
+ </tr>
1081
+ </tbody>
1082
+ </table>
1083
+
1084
+ <hr id="layout" />
1085
+ <h3><?php _e('Layout', 'instagram-feed'); ?></h3>
1086
+
1087
+ <table class="form-table">
1088
+ <tbody>
1089
+ <?php
1090
+ $selected_type = isset( $sb_instagram_layout_type ) ? $sb_instagram_layout_type : 'grid';
1091
+ $layout_types = array(
1092
+ 'grid' => __( 'Grid', 'instagram-feed' ),
1093
+ 'carousel' => __( 'Carousel', 'instagram-feed' ),
1094
+ 'masonry' => __( 'Masonry', 'instagram-feed' ),
1095
+ 'highlight' => __( 'Highlight', 'instagram-feed' )
1096
+ );
1097
+ $layout_images = array(
1098
+ 'grid' => SBI_PLUGIN_URL . 'img/grid.png',
1099
+ 'carousel' => SBI_PLUGIN_URL . 'img/carousel.png',
1100
+ 'masonry' => SBI_PLUGIN_URL . 'img/masonry.png',
1101
+ 'highlight' => SBI_PLUGIN_URL . 'img/highlight.png'
1102
+ );
1103
+ ?>
1104
+ <tr valign="top">
1105
+ <th scope="row" class="sbi_pro"><label title="<?php _e('Click for shortcode option', 'instagram-feed'); ?>"><?php _e('Layout Type', 'instagram-feed'); ?></label><br /><span class="sbi_note" style="margin: 5px 0 0 0; font-weight: normal;"><?php _e('Select a layout to see associated<br />options', 'instagram-feed'); ?></span></th>
1106
+ <td>
1107
+ <div class="sbi_layouts">
1108
+ <?php foreach( $layout_types as $layout_type => $label ) : ?>
1109
+ <div class="sbi_layout_cell sbi_pro">
1110
+ <input class="sb_layout_type" id="sb_layout_type_<?php echo esc_attr( $layout_type ); ?>" name="sb_instagram_layout_type" type="radio" value="<?php echo esc_attr( $layout_type ); ?>" <?php if ( $selected_type === $layout_type ) echo 'checked'; ?>/><label for="sb_layout_type_<?php echo esc_attr( $layout_type ); ?>"><span class="sbi_label"><?php echo esc_html( $label ); ?></span><img src="<?php echo esc_url( $layout_images[ $layout_type ] ); ?>" /></label>
1111
+ </div>
1112
+ <?php endforeach; ?>
1113
+
1114
+ <p class="sbi_pro_tooltip"><?php _e('Upgrade to the Pro version to unlock these layouts', 'instagram-feed'); ?><i class="fa fa-caret-down" aria-hidden="true"></i></p>
1115
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi_lock"><i class="fa fa-rocket"></i><?php _e('Pro', 'instagram-feed'); ?></a>
1116
+
1117
+ </div>
1118
+ <div class="sb_layout_options_wrap sbi_pro">
1119
+ <a href="JavaScript:void(0);" class="sbi_close_options"><i class="fa fa-close"></i></a>
1120
+ <div class="sb_instagram_layout_settings sbi_layout_type_grid">
1121
+ <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('A uniform grid of square-cropped images.', 'instagram-feed'); ?></span>
1122
+ </div>
1123
+ <div class="sb_instagram_layout_settings sbi_layout_type_masonry">
1124
+ <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Images in their original aspect ratios with no vertical space between posts.', 'instagram-feed'); ?></span>
1125
+ </div>
1126
+ <div class="sb_instagram_layout_settings sbi_layout_type_carousel">
1127
+ <div class="sb_instagram_layout_setting">
1128
+ <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Posts are displayed in a slideshow carousel.', 'instagram-feed'); ?></span>
1129
+ </div>
1130
+ <div class="sb_instagram_layout_setting">
1131
+
1132
+ <label><?php _e('Number of Rows', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselrows
1133
+ Eg: carouselrows=2</code>
1134
+ <br>
1135
+ <span class="sbi_note" style="margin: -5px 0 -10px 0; display: block;"><?php _e('Use the "Number of Columns" setting below this section to set how many posts are visible in the carousel at a given time.', 'instagram-feed'); ?></span>
1136
+ <br>
1137
+ <select name="sb_instagram_carousel_rows" id="sb_instagram_carousel_rows">
1138
+ <option value="1">1</option>
1139
+ <option value="2" selected="selected">2</option>
1140
+ </select>
1141
+ </div>
1142
+ <div class="sb_instagram_layout_setting">
1143
+ <label><?php _e('Loop Type', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselloop
1144
+ Eg: carouselloop=rewind
1145
+ carouselloop=infinity</code>
1146
+ <br>
1147
+ <select name="sb_instagram_carousel_loop" id="sb_instagram_carousel_loop">
1148
+ <option value="rewind"><?php _e('Rewind', 'instagram-feed'); ?></option>
1149
+ <option value="infinity" selected="selected"><?php _e('Infinity', 'instagram-feed'); ?></option>
1150
+ </select>
1151
+ </div>
1152
+ <div class="sb_instagram_layout_setting">
1153
+ <input type="checkbox" name="sb_instagram_carousel_arrows" id="sb_instagram_carousel_arrows" checked="checked">
1154
+ <label><?php _e('Show Navigation Arrows', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselarrows
1155
+ Eg: carouselarrows=true</code>
1156
+ </div>
1157
+ <div class="sb_instagram_layout_setting">
1158
+ <input type="checkbox" name="sb_instagram_carousel_pag" id="sb_instagram_carousel_pag">
1159
+ <label><?php _e('Show Pagination', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselpag
1160
+ Eg: carouselpag=true</code>
1161
+ </div>
1162
+ <div class="sb_instagram_layout_setting">
1163
+ <input type="checkbox" name="sb_instagram_carousel_autoplay" id="sb_instagram_carousel_autoplay">
1164
+ <label><?php _e('Enable Autoplay', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouselautoplay
1165
+ Eg: carouselautoplay=true</code>
1166
+ </div>
1167
+ <div class="sb_instagram_layout_setting">
1168
+ <label><?php _e('Interval Time', 'instagram-feed'); ?></label><code class="sbi_shortcode"> carouseltime
1169
+ Eg: carouseltime=8000</code>
1170
+ <br>
1171
+ <input name="sb_instagram_carousel_interval" type="text" value="5000" size="6"><?php _e("miliseconds", 'instagram-feed'); ?>
1172
+ </div>
1173
+ </div>
1174
+
1175
+ <div class="sb_instagram_layout_settings sbi_layout_type_highlight">
1176
+ <div class="sb_instagram_layout_setting">
1177
+ <i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 8px;"></i><span class="sbi_note" style="margin-left: 0;"><?php _e('Masonry style, square-cropped, image only (no captions or likes/comments below image). "Highlighted" posts are twice as large.', 'instagram-feed'); ?></span>
1178
+ </div>
1179
+ <div class="sb_instagram_layout_setting">
1180
+ <label title="Click for shortcode option"><?php _e('Highlighting Type', 'instagram-feed'); ?></label><code class="sbi_shortcode"> highlighttype
1181
+ Eg: highlighttype=pattern</code>
1182
+ <br>
1183
+ <select name="sb_instagram_highlight_type" id="sb_instagram_highlight_type">
1184
+ <option value="pattern" selected="selected"><?php _e('Pattern', 'instagram-feed'); ?></option>
1185
+ <option value="id"><?php _e('Post ID', 'instagram-feed'); ?></option>
1186
+ <option value="hashtag"><?php _e('Hashtag', 'instagram-feed'); ?></option>
1187
+ </select>
1188
+ </div>
1189
+ <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_pattern sb_instagram_layout_setting" style="display: block;">
1190
+ <label></label><code class="sbi_shortcode"> highlightoffset
1191
+ Eg: highlightoffset=2</code>
1192
+ <br>
1193
+ <input name="sb_instagram_highlight_offset" type="number" min="0" value="0" style="width: 50px;">
1194
+ </div>
1195
+ <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_pattern sb_instagram_layout_setting" style="display: block;">
1196
+ <label><?php _e('Pattern', 'instagram-feed'); ?></label><code class="sbi_shortcode"> highlightpattern
1197
+ Eg: highlightpattern=3</code>
1198
+ <br>
1199
+ <span><?php _e('Highlight every', 'instagram-feed'); ?></span><input name="sb_instagram_highlight_factor" type="number" min="2" value="6" style="width: 50px;"><span><?php _e('posts', 'instagram-feed'); ?></span>
1200
+ </div>
1201
+ <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_hashtag sb_instagram_layout_setting" style="display: none;">
1202
+ <label><?php _e('Highlight Posts with these Hashtags', 'instagram-feed'); ?></label>
1203
+ <input name="sb_instagram_highlight_hashtag" id="sb_instagram_highlight_hashtag" type="text" size="40" value="#fishing">&nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What is this?', 'instagram-feed'); ?></a>
1204
+ <br>
1205
+ <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate multiple hashtags using commas', 'instagram-feed'); ?></span>
1206
+
1207
+
1208
+ <p class="sbi_tooltip"><?php _e('You can use this setting to highlight posts by a hashtag. Use a specified hashtag in your posts and they will be automatically highlighted in your feed.', 'instagram-feed'); ?></p>
1209
+ </div>
1210
+ <div class="sb_instagram_highlight_sub_options sb_instagram_highlight_ids sb_instagram_layout_setting" style="display: none;">
1211
+ <label><?php _e('Highlight Posts by ID', 'instagram-feed'); ?></label>
1212
+ <textarea name="sb_instagram_highlight_ids" id="sb_instagram_highlight_ids" style="width: 100%;" rows="3">sbi_1852317219231323590_3269008872</textarea>
1213
+ <br>
1214
+ <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate IDs using commas', 'instagram-feed'); ?></span>
1215
+
1216
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What is this?', 'instagram-feed'); ?></a>
1217
+ <p class="sbi_tooltip"><?php _e('You can use this setting to highlight posts by their ID. Enable and use "moderation mode", check the box to show post IDs underneath posts, then copy and paste IDs into this text box.', 'instagram-feed'); ?></p>
1218
+ </div>
1219
+ </div>
1220
+
1221
+ </div>
1222
+ </td>
1223
+ </tr>
1224
+ <tr valign="top">
1225
+ <th scope="row"><label><?php _e('Number of Photos', 'instagram-feed'); ?></label><code class="sbi_shortcode"> num
1226
+ Eg: num=6</code></th>
1227
+ <td>
1228
+ <input name="sb_instagram_num" type="text" value="<?php echo esc_attr( $sb_instagram_num ); ?>" size="4" maxlength="4" />
1229
+ <span class="sbi_note"><?php _e('Number of photos to show initially.', 'instagram-feed'); ?></span>
1230
+ </td>
1231
+ </tr>
1232
+ <tr valign="top">
1233
+ <th scope="row"><label><?php _e('Number of Columns', 'instagram-feed'); ?></label><code class="sbi_shortcode"> cols
1234
+ Eg: cols=3</code></th>
1235
+ <td>
1236
+ <select name="sb_instagram_cols">
1237
+ <option value="1" <?php if($sb_instagram_cols == "1") echo 'selected="selected"' ?> ><?php _e('1', 'instagram-feed'); ?></option>
1238
+ <option value="2" <?php if($sb_instagram_cols == "2") echo 'selected="selected"' ?> ><?php _e('2', 'instagram-feed'); ?></option>
1239
+ <option value="3" <?php if($sb_instagram_cols == "3") echo 'selected="selected"' ?> ><?php _e('3', 'instagram-feed'); ?></option>
1240
+ <option value="4" <?php if($sb_instagram_cols == "4") echo 'selected="selected"' ?> ><?php _e('4', 'instagram-feed'); ?></option>
1241
+ <option value="5" <?php if($sb_instagram_cols == "5") echo 'selected="selected"' ?> ><?php _e('5', 'instagram-feed'); ?></option>
1242
+ <option value="6" <?php if($sb_instagram_cols == "6") echo 'selected="selected"' ?> ><?php _e('6', 'instagram-feed'); ?></option>
1243
+ <option value="7" <?php if($sb_instagram_cols == "7") echo 'selected="selected"' ?> ><?php _e('7', 'instagram-feed'); ?></option>
1244
+ <option value="8" <?php if($sb_instagram_cols == "8") echo 'selected="selected"' ?> ><?php _e('8', 'instagram-feed'); ?></option>
1245
+ <option value="9" <?php if($sb_instagram_cols == "9") echo 'selected="selected"' ?> ><?php _e('9', 'instagram-feed'); ?></option>
1246
+ <option value="10" <?php if($sb_instagram_cols == "10") echo 'selected="selected"' ?> ><?php _e('10', 'instagram-feed'); ?></option>
1247
+ </select>
1248
+ </td>
1249
+ </tr>
1250
+ <tr valign="top">
1251
+ <th scope="row"><label><?php _e('Padding around Images', 'instagram-feed'); ?></label><code class="sbi_shortcode"> imagepadding imagepaddingunit</code></th>
1252
+ <td>
1253
+ <input name="sb_instagram_image_padding" type="text" value="<?php echo esc_attr( $sb_instagram_image_padding ); ?>" size="4" maxlength="4" />
1254
+ <select name="sb_instagram_image_padding_unit">
1255
+ <option value="px" <?php if($sb_instagram_image_padding_unit == "px") echo 'selected="selected"' ?> ><?php _e('px', 'instagram-feed'); ?></option>
1256
+ <option value="%" <?php if($sb_instagram_image_padding_unit == "%") echo 'selected="selected"' ?> ><?php _e('%', 'instagram-feed'); ?></option>
1257
+ </select>
1258
+ </td>
1259
+ </tr>
1260
+ <tr valign="top">
1261
+ <th scope="row"><label><?php _e("Disable mobile layout", 'instagram-feed'); ?></label><code class="sbi_shortcode"> disablemobile
1262
+ Eg: disablemobile=true</code></th>
1263
+ <td>
1264
+ <input type="checkbox" name="sb_instagram_disable_mobile" id="sb_instagram_disable_mobile" <?php if($sb_instagram_disable_mobile == true) echo 'checked="checked"' ?> />
1265
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does this mean?', 'instagram-feed' ); ?></a>
1266
+ <p class="sbi_tooltip"><?php _e("By default on mobile devices the layout automatically changes to use fewer columns. Checking this setting disables the mobile layout.", 'instagram-feed'); ?></p>
1267
+ </td>
1268
+ </tr>
1269
+ </tbody>
1270
+ </table>
1271
+
1272
+ <?php submit_button(); ?>
1273
+
1274
+ <hr id="photos" />
1275
+ <h3><?php _e('Photos', 'instagram-feed'); ?></h3>
1276
+
1277
+ <table class="form-table">
1278
+ <tbody>
1279
+ <tr valign="top">
1280
+ <th scope="row"><label><?php _e('Sort Photos By', 'instagram-feed'); ?></label><code class="sbi_shortcode"> sortby
1281
+ Eg: sortby=random</code></th>
1282
+ <td>
1283
+ <select name="sb_instagram_sort">
1284
+ <option value="none" <?php if($sb_instagram_sort == "none") echo 'selected="selected"' ?> ><?php _e('Newest to oldest', 'instagram-feed'); ?></option>
1285
+ <option value="random" <?php if($sb_instagram_sort == "random") echo 'selected="selected"' ?> ><?php _e('Random', 'instagram-feed'); ?></option>
1286
+ </select>
1287
+ </td>
1288
+ </tr>
1289
+ <tr valign="top">
1290
+ <th scope="row"><label><?php _e('Image Resolution', 'instagram-feed'); ?></label><code class="sbi_shortcode"> imageres
1291
+ Eg: imageres=thumb</code></th>
1292
+ <td>
1293
+
1294
+ <select name="sb_instagram_image_res">
1295
+ <option value="auto" <?php if($sb_instagram_image_res == "auto") echo 'selected="selected"' ?> ><?php _e('Auto-detect (recommended)', 'instagram-feed'); ?></option>
1296
+ <option value="thumb" <?php if($sb_instagram_image_res == "thumb") echo 'selected="selected"' ?> ><?php _e('Thumbnail (150x150)', 'instagram-feed'); ?></option>
1297
+ <option value="medium" <?php if($sb_instagram_image_res == "medium") echo 'selected="selected"' ?> ><?php _e('Medium (320x320)', 'instagram-feed'); ?></option>
1298
+ <option value="full" <?php if($sb_instagram_image_res == "full") echo 'selected="selected"' ?> ><?php _e('Full size (640x640)', 'instagram-feed'); ?></option>
1299
+ </select>
1300
+
1301
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e( 'What does Auto-detect mean?', 'instagram-feed'); ?></a>
1302
+ <p class="sbi_tooltip"><?php _e("Auto-detect means that the plugin automatically sets the image resolution based on the size of your feed.", 'instagram-feed'); ?></p>
1303
+
1304
+ </td>
1305
+ </tr>
1306
+ </tbody>
1307
+ </table>
1308
+
1309
+ <span><a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a></span>
1310
+
1311
+ <div class="sbi-pro-options">
1312
+ <p class="sbi-upgrade-link">
1313
+ <i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable these settings', 'instagram-feed'); ?></a>
1314
+ </p>
1315
+ <table class="form-table">
1316
+ <tbody>
1317
+ <tr valign="top" class="sbi_pro">
1318
+ <th scope="row"><label><?php _e('Media Type to Display','instagram-feed'); ?></label></th>
1319
+ <td>
1320
+ <select name="sb_instagram_media_type" disabled>
1321
+ <option value="all"><?php _e('All','instagram-feed'); ?></option>
1322
+ <option value="photos"><?php _e('Photos only','instagram-feed'); ?></option>
1323
+ <option value="videos"><?php _e('Videos only','instagram-feed'); ?></option>
1324
+ </select>
1325
+ </td>
1326
+ </tr>
1327
+
1328
+ <tr valign="top" class="sbi_pro">
1329
+ <th scope="row"><label><?php _e("Enable Pop-up Lightbox", 'instagram-feed'); ?></label></th>
1330
+ <td>
1331
+ <input type="checkbox" name="sb_instagram_captionlinks" id="sb_instagram_captionlinks" disabled />
1332
+ </td>
1333
+ </tr>
1334
+
1335
+ <tr valign="top" class="sbi_pro">
1336
+ <th scope="row"><label><?php _e("Link Posts to URL in Caption (Shoppable feed)",'instagram-feed'); ?></label></th>
1337
+ <td>
1338
+ <input type="checkbox" name="sb_instagram_captionlinks" id="sb_instagram_captionlinks" disabled />
1339
+ &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e("What will this do?",'instagram-feed'); ?></a>
1340
+ <p class="sbi_tooltip"><?php _e("Checking this box will change the link for each post to any url included in the caption for that Instagram post. The lightbox will be disabled. Visit <a href='https://smashballoon.com/make-a-shoppable-feed?utm_source=plugin-free&utm_campaign=sbi'>this link</a> to learn how this works.",'instagram-feed'); ?></p>
1341
+ </td>
1342
+ </tr>
1343
+ </tbody>
1344
+ </table>
1345
+ </div>
1346
+
1347
+
1348
+ <hr />
1349
+ <h3><?php _e('Photo Hover Style','instagram-feed'); ?></h3>
1350
+
1351
+ <p style="padding-bottom: 18px;">
1352
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Photo Hover styles','instagram-feed'); ?></a><br />
1353
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options','instagram-feed'); ?></a>
1354
+ </p>
1355
+
1356
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1357
+ <table class="form-table">
1358
+ <tbody>
1359
+ <tr valign="top" class="sbi_pro">
1360
+ <th scope="row"><label><?php _e('Hover Background Color', 'instagram-feed'); ?></label></th>
1361
+ <td>
1362
+ <input name="sb_hover_background" type="text" disabled class="sbi_colorpick" />
1363
+ </td>
1364
+ </tr>
1365
+ <tr valign="top" class="sbi_pro">
1366
+ <th scope="row"><label><?php _e('Hover Text Color', 'instagram-feed'); ?></label></th>
1367
+ <td>
1368
+ <input name="sb_hover_text" type="text" disabled class="sbi_colorpick" />
1369
+ </td>
1370
+ </tr>
1371
+ <tr valign="top" class="sbi_pro">
1372
+ <th scope="row"><label><?php _e('Information to display', 'instagram-feed'); ?></label></th>
1373
+ <td>
1374
+ <div>
1375
+ <input name="sbi_hover_inc_username" type="checkbox" disabled />
1376
+ <label for="sbi_hover_inc_username"><?php _e('Username', 'instagram-feed'); ?></label>
1377
+ </div>
1378
+ <div>
1379
+ <input name="sbi_hover_inc_icon" type="checkbox" disabled />
1380
+ <label for="sbi_hover_inc_icon"><?php _e('Expand Icon', 'instagram-feed'); ?></label>
1381
+ </div>
1382
+ <div>
1383
+ <input name="sbi_hover_inc_date" type="checkbox" disabled />
1384
+ <label for="sbi_hover_inc_date"><?php _e('Date', 'instagram-feed'); ?></label>
1385
+ </div>
1386
+ <div>
1387
+ <input name="sbi_hover_inc_instagram" type="checkbox" disabled />
1388
+ <label for="sbi_hover_inc_instagram"><?php _e('Instagram Icon/Link', 'instagram-feed'); ?></label>
1389
+ </div>
1390
+ <div>
1391
+ <input name="sbi_hover_inc_location" type="checkbox" disabled />
1392
+ <label for="sbi_hover_inc_location"><?php _e('Location', 'instagram-feed'); ?></label>
1393
+ </div>
1394
+ <div>
1395
+ <input name="sbi_hover_inc_caption" type="checkbox" disabled />
1396
+ <label for="sbi_hover_inc_caption"><?php _e('Caption', 'instagram-feed'); ?></label>
1397
+ </div>
1398
+ <div>
1399
+ <input name="sbi_hover_inc_likes" type="checkbox" disabled />
1400
+ <label for="sbi_hover_inc_likes"><?php _e('Like/Comment Icons', 'instagram-feed'); ?></label>
1401
+ </div>
1402
+ </td>
1403
+ </tr>
1404
+
1405
+ </tbody>
1406
+ </table>
1407
+ </div>
1408
+
1409
+
1410
+ <hr />
1411
+ <h3><?php _e( 'Carousel', 'instagram-feed' ); ?></h3>
1412
+ <p style="padding-bottom: 18px;">
1413
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Carousels', 'instagram-feed'); ?></a><br />
1414
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1415
+ </p>
1416
+
1417
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1418
+ <table class="form-table">
1419
+ <tbody>
1420
+ <tr valign="top" class="sbi_pro">
1421
+ <th scope="row"><label><?php _e("Enable Carousel", 'instagram-feed'); ?></label></th>
1422
+ <td>
1423
+ <input type="checkbox" disabled />
1424
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1425
+ <p class="sbi_tooltip"><?php _e("Enable this setting to create a carousel slider out of your photos.", 'instagram-feed'); ?></p>
1426
+ </td>
1427
+ </tr>
1428
+ <tr valign="top" class="sbi_pro">
1429
+ <th scope="row"><label><?php _e("Show Navigation Arrows", 'instagram-feed'); ?></label></th>
1430
+ <td>
1431
+ <input type="checkbox" disabled />
1432
+ </td>
1433
+ </tr>
1434
+ <tr valign="top" class="sbi_pro">
1435
+ <th scope="row"><label><?php _e("Show Pagination", 'instagram-feed'); ?></label></th>
1436
+ <td>
1437
+ <input type="checkbox" disabled />
1438
+ </td>
1439
+ </tr>
1440
+ <tr valign="top" class="sbi_pro">
1441
+ <th scope="row"><label><?php _e("Enable Autoplay", 'instagram-feed'); ?></label></th>
1442
+ <td>
1443
+ <input type="checkbox" disabled />
1444
+ </td>
1445
+ </tr>
1446
+ <tr valign="top" class="sbi_pro">
1447
+ <th scope="row"><label><?php _e("Interval Time", 'instagram-feed'); ?></label></th>
1448
+ <td>
1449
+ <input name="sb_instagram_carousel_interval" type="text" disabled size="6" /><?php _e("milliseconds", 'instagram-feed'); ?>
1450
+ </td>
1451
+ </tr>
1452
+ </tbody>
1453
+ </table>
1454
+ </div>
1455
+
1456
+
1457
+
1458
+ <hr id="headeroptions" />
1459
+ <h3><?php _e("Header", 'instagram-feed'); ?></h3>
1460
+ <table class="form-table">
1461
+ <tbody>
1462
+ <tr valign="top">
1463
+ <th scope="row"><label><?php _e("Show Feed Header", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showheader
1464
+ Eg: showheader=false</code></th>
1465
+ <td>
1466
+ <input type="checkbox" name="sb_instagram_show_header" id="sb_instagram_show_header" <?php if($sb_instagram_show_header == true) echo 'checked="checked"' ?> />
1467
+ </td>
1468
+ </tr>
1469
+ <tr valign="top">
1470
+ <th scope="row"><label><?php _e('Header Size', 'instagram-feed'); ?></label><code class="sbi_shortcode"> headersize
1471
+ Eg: headersize=medium</code></th>
1472
+ <td>
1473
+ <select name="sb_instagram_header_size" id="sb_instagram_header_size" style="float: left;">
1474
+ <option value="small" <?php if($sb_instagram_header_size == "small") echo 'selected="selected"' ?> ><?php _e('Small', 'instagram-feed'); ?></option>
1475
+ <option value="medium" <?php if($sb_instagram_header_size == "medium") echo 'selected="selected"' ?> ><?php _e('Medium', 'instagram-feed'); ?></option>
1476
+ <option value="large" <?php if($sb_instagram_header_size == "large") echo 'selected="selected"' ?> ><?php _e('Large', 'instagram-feed'); ?></option>
1477
+ </select>
1478
+ </td>
1479
+ </tr>
1480
+ <tr valign="top">
1481
+ <th scope="row"><label><?php _e("Show Bio Text", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showbio
1482
+ Eg: showbio=false</code></th>
1483
+ <td>
1484
+ <?php $sb_instagram_show_bio = isset( $sb_instagram_show_bio ) ? $sb_instagram_show_bio : true; ?>
1485
+ <input type="checkbox" name="sb_instagram_show_bio" id="sb_instagram_show_bio" <?php if($sb_instagram_show_bio == true) echo 'checked="checked"' ?> />
1486
+ <span class="sbi_note"><?php _e("Only applies for Instagram accounts with bios", 'instagram-feed'); ?></span>
1487
+ <div class="sb_instagram_box" style="display: block;">
1488
+ <div class="sb_instagram_box_setting" style="display: block;">
1489
+ <label style="padding-bottom: 0;"><?php _e("Add Custom Bio Text", 'instagram-feed'); ?></label><code class="sbi_shortcode" style="margin-top: 5px;"> custombio
1490
+ Eg: custombio="My custom bio."</code>
1491
+ <br>
1492
+ <span class="sbi_aside" style="padding-bottom: 5px; display: block;"><?php _e("Use your own custom bio text in the feed header. Bio text is automatically retrieved from Instagram for Business accounts.", 'instagram-feed'); ?></span>
1493
+
1494
+ <textarea type="text" name="sb_instagram_custom_bio" id="sb_instagram_custom_bio" ><?php echo esc_textarea( stripslashes( $sb_instagram_custom_bio ) ); ?></textarea>
1495
+ &nbsp;<a class="sbi_tooltip_link sbi_tooltip_under" href="JavaScript:void(0);"><?php _e("Why is my bio not displaying automatically?", 'instagram-feed'); ?></a>
1496
+ <p class="sbi_tooltip" style="padding: 10px 0 0 0; width: 99%;"><?php echo sprintf( __("Instagram is deprecating their old API for Personal accounts on March 31, 2020. The plugin supports their new API, however, their new API does not yet include the bio text for Personal accounts. If you require this feature then it is available if you convert your Instagram account from a Personal to a Business account by following %s. Note: If you previously had a Personal account connected then the plugin has saved the avatar for that feed and will continue to use it automatically.", 'instagram-feed'), '<a href="https://smashballoon.com/instagram-business-profiles/" target="_blank">these directions</a>' ); ?></p>
1497
+ </div>
1498
+ </div>
1499
+
1500
+ </td>
1501
+ </tr>
1502
+
1503
+ <tr valign="top">
1504
+ <th scope="row"><label><?php _e("Use Custom Avatar", 'instagram-feed'); ?></label><code class="sbi_shortcode"> customavatar
1505
+ Eg: customavatar="https://my-website.com/avatar.jpg"</code></th>
1506
+ <td>
1507
+ <input type="text" name="sb_instagram_custom_avatar" class="large-text" id="sb_instagram_custom_avatar" value="<?php echo esc_attr( stripslashes( $sb_instagram_custom_avatar ) ); ?>" placeholder="https://example.com/avatar.jpg" />
1508
+ <span class="sbi_aside"><?php _e("Avatar is automatically retrieved from Instagram for Business accounts", 'instagram-feed'); ?></span>
1509
+ <br>
1510
+ <a class="sbi_tooltip_link sbi_tooltip_under" href="JavaScript:void(0);"><?php _e("Why is my avatar not displaying automatically?", 'instagram-feed'); ?></a>
1511
+
1512
+ <p class="sbi_tooltip sbi_tooltip_under_text" style="padding: 10px 0 0 0;"><?php echo sprintf( __("Instagram is deprecating their old API for Personal accounts on March 31, 2020. The plugin supports their new API, however, their new API does not yet include the avatar image for Personal accounts. If you require this feature then it is available if you convert your Instagram account from a Personal to a Business account by following %s. Note: If you previously had a Personal account connected then the plugin has saved the bio text for that feed and will continue to use it automatically.", 'instagram-feed'), '<a href="https://smashballoon.com/instagram-business-profiles/" target="_blank">these directions</a>' ); ?></p>
1513
+
1514
+ </td>
1515
+ </tr>
1516
+ <tr valign="top">
1517
+ <th scope="row"><label><?php _e('Header Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> headercolor
1518
+ Eg: headercolor=fff</code></th>
1519
+ <td>
1520
+ <input name="sb_instagram_header_color" type="text" value="<?php echo esc_attr( $sb_instagram_header_color ); ?>" class="sbi_colorpick" />
1521
+ </td>
1522
+ </tr>
1523
+ </tbody>
1524
+ </table>
1525
+
1526
+ <span><a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a></span>
1527
+
1528
+ <div class="sbi-pro-options">
1529
+ <p class="sbi-upgrade-link">
1530
+ <i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable these settings', 'instagram-feed'); ?></a>
1531
+ </p>
1532
+ <table class="form-table">
1533
+ <tbody>
1534
+ <tr valign="top" class="sbi_pro">
1535
+ <th scope="row"><label><?php _e('Header Style','instagram-feed'); ?></label></th>
1536
+ <td>
1537
+ <select name="sb_instagram_header_style" style="float: left;">
1538
+ <option value="circle"><?php _e('Standard','instagram-feed'); ?></option>
1539
+ <option value="boxed"><?php _e('Boxed','instagram-feed'); ?></option>
1540
+ <option value="centered"><?php _e('Centered','instagram-feed'); ?></option>
1541
+ </select>
1542
+ </td>
1543
+ </tr>
1544
+ <tr valign="top" class="sbi_pro">
1545
+ <th scope="row"><label><?php _e("Show Number of Followers",'instagram-feed'); ?></label></th>
1546
+ <td>
1547
+ <input type="checkbox" disabled />
1548
+ <span class="sbi_note"><?php _e("This only applies when displaying photos from a User ID",'instagram-feed'); ?></span>
1549
+ </td>
1550
+ </tr>
1551
+ </tbody>
1552
+ </table>
1553
+ </div>
1554
+
1555
+ <?php submit_button(); ?>
1556
+
1557
+
1558
+ <hr />
1559
+ <h3><?php _e("Caption", 'instagram-feed'); ?></h3>
1560
+ <p style="padding-bottom: 18px;">
1561
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e("Upgrade to Pro to enable Photo Captions", 'instagram-feed'); ?></a><br />
1562
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e("Show Pro Options", 'instagram-feed'); ?></a>
1563
+ </p>
1564
+
1565
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1566
+ <table class="form-table">
1567
+ <tbody>
1568
+ <tr valign="top" class="sbi_pro">
1569
+ <th scope="row"><label><?php _e("Show Caption", 'instagram-feed'); ?></label></th>
1570
+ <td>
1571
+ <input type="checkbox" disabled />
1572
+ </td>
1573
+ </tr>
1574
+ <tr valign="top" class="sbi_pro">
1575
+ <th scope="row"><label><?php _e("Maximum Text Length", 'instagram-feed'); ?></label></th>
1576
+ <td>
1577
+ <input disabled size="4" />Characters
1578
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1579
+ <p class="sbi_tooltip"><?php _e("The number of characters of text to display in the caption. An elipsis link will be added to allow the user to reveal more text if desired.", 'instagram-feed'); ?></p>
1580
+ </td>
1581
+ </tr>
1582
+ <tr valign="top" class="sbi_pro">
1583
+ <th scope="row"><label><?php _e('Text Color', 'instagram-feed'); ?></label></th>
1584
+ <td>
1585
+ <input type="text" disabled class="sbi_colorpick" />
1586
+ </td>
1587
+ </tr>
1588
+ <tr valign="top" class="sbi_pro">
1589
+ <th scope="row"><label><?php _e('Text Size', 'instagram-feed'); ?></label></th>
1590
+ <td>
1591
+ <select name="sb_instagram_caption_size" style="width: 180px;" disabled>
1592
+ <option value="inherit" ><?php _e('Inherit from theme', 'instagram-feed'); ?></option>
1593
+ <option value="10" >10px</option>
1594
+ <option value="11" >11px</option>
1595
+ <option value="12" >12px</option>
1596
+ <option value="13" >13px</option>
1597
+ <option value="14" >14px</option>
1598
+ <option value="16" >16px</option>
1599
+ <option value="18" >18px</option>
1600
+ <option value="20" >20px</option>
1601
+ <option value="24" >24px</option>
1602
+ <option value="28" >28px</option>
1603
+ <option value="32" >32px</option>
1604
+ <option value="36" >36px</option>
1605
+ <option value="40" >40px</option>
1606
+ </select>
1607
+ </td>
1608
+ </tr>
1609
+ </tbody>
1610
+ </table>
1611
+ </div>
1612
+
1613
+
1614
+ <hr />
1615
+ <h3><?php _e("Likes &amp; Comments", 'instagram-feed'); ?></h3>
1616
+ <p style="padding-bottom: 18px;">
1617
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e("Upgrade to Pro to enable Likes &amp; Comments", 'instagram-feed'); ?></a><br />
1618
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e("Show Pro Options", 'instagram-feed'); ?></a>
1619
+ </p>
1620
+
1621
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1622
+ <table class="form-table">
1623
+ <tbody>
1624
+ <tr valign="top" class="sbi_pro">
1625
+ <th scope="row"><label><?php _e("Show Icons", 'instagram-feed'); ?></label></th>
1626
+ <td>
1627
+ <input type="checkbox" disabled />
1628
+ </td>
1629
+ </tr>
1630
+ <tr valign="top" class="sbi_pro">
1631
+ <th scope="row"><label><?php _e('Icon Color', 'instagram-feed'); ?></label></th>
1632
+ <td>
1633
+ <input type="text" disabled class="sbi_colorpick" />
1634
+ </td>
1635
+ </tr>
1636
+ <tr valign="top" class="sbi_pro">
1637
+ <th scope="row"><label><?php _e('Icon Size', 'instagram-feed'); ?></label></th>
1638
+ <td>
1639
+ <select disabled name="sb_instagram_meta_size" style="width: 180px;">
1640
+ <option value="inherit"><?php _e('Inherit from theme', 'instagram-feed'); ?></option>
1641
+ <option value="10" >10px</option>
1642
+ <option value="11" >11px</option>
1643
+ <option value="12" >12px</option>
1644
+ <option value="13" >13px</option>
1645
+ <option value="14" >14px</option>
1646
+ <option value="16" >16px</option>
1647
+ <option value="18" >18px</option>
1648
+ <option value="20" >20px</option>
1649
+ <option value="24" >24px</option>
1650
+ <option value="28" >28px</option>
1651
+ <option value="32" >32px</option>
1652
+ <option value="36" >36px</option>
1653
+ <option value="40" >40px</option>
1654
+ </select>
1655
+ </td>
1656
+ </tr>
1657
+ </tbody>
1658
+ </table>
1659
+ </div>
1660
+
1661
+
1662
+ <hr />
1663
+ <h3><?php _e('Lightbox Comments', 'instagram-feed'); ?></h3>
1664
+
1665
+ <p style="padding-bottom: 18px;">
1666
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Comments', 'instagram-feed'); ?></a><br />
1667
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1668
+ </p>
1669
+
1670
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1671
+ <table class="form-table">
1672
+ <tbody>
1673
+
1674
+ <tr valign="top" class="sbi_pro">
1675
+ <th scope="row"><label><?php _e('Show Comments in Lightbox', 'instagram-feed'); ?></label></th>
1676
+ <td style="padding: 5px 10px 0 10px;">
1677
+ <input type="checkbox" disabled style="margin-right: 15px;" />
1678
+ <input class="button-secondary" style="margin-top: -5px;" disabled value="<?php echo esc_attr( 'Clear Comment Cache', 'instagram-feed' ); ?>" />
1679
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1680
+ <p class="sbi_tooltip"><?php _e("This will remove the cached comments saved in the database", 'instagram-feed'); ?></p>
1681
+ </td>
1682
+ </tr>
1683
+ <tr valign="top" class="sbi_pro">
1684
+ <th scope="row"><label><?php _e('Number of Comments', 'instagram-feed'); ?></label></th>
1685
+ <td>
1686
+ <input name="sb_instagram_num_comments" type="text" disabled size="4" />
1687
+ <span class="sbi_note"><?php _e('Max number of latest comments.', 'instagram-feed'); ?></span>
1688
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1689
+ <p class="sbi_tooltip"><?php _e("This is the maximum number of comments that will be shown in the lightbox. If there are more comments available than the number set, only the latest comments will be shown", 'instagram-feed'); ?></p>
1690
+ </td>
1691
+ </tr>
1692
+
1693
+ </tbody>
1694
+ </table>
1695
+ </div>
1696
+
1697
+
1698
+ <hr id="loadmore" />
1699
+ <h3><?php _e("'Load More' Button", 'instagram-feed'); ?></h3>
1700
+ <table class="form-table">
1701
+ <tbody>
1702
+ <tr valign="top">
1703
+ <th scope="row"><label><?php _e("Show the 'Load More' button", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showbutton
1704
+ Eg: showbutton=false</code></th>
1705
+ <td>
1706
+ <input type="checkbox" name="sb_instagram_show_btn" id="sb_instagram_show_btn" <?php if($sb_instagram_show_btn == true) echo 'checked="checked"' ?> />
1707
+ </td>
1708
+ </tr>
1709
+ <tr valign="top">
1710
+ <th scope="row"><label><?php _e('Button Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttoncolor
1711
+ Eg: buttoncolor=8224e3</code></th>
1712
+ <td>
1713
+ <input name="sb_instagram_btn_background" type="text" value="<?php echo esc_attr( $sb_instagram_btn_background ); ?>" class="sbi_colorpick" />
1714
+ </td>
1715
+ </tr>
1716
+ <tr valign="top">
1717
+ <th scope="row"><label><?php _e('Button Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttontextcolor
1718
+ Eg: buttontextcolor=eeee22</code></th>
1719
+ <td>
1720
+ <input name="sb_instagram_btn_text_color" type="text" value="<?php echo esc_attr( $sb_instagram_btn_text_color ); ?>" class="sbi_colorpick" />
1721
+ </td>
1722
+ </tr>
1723
+ <tr valign="top">
1724
+ <th scope="row"><label><?php _e('Button Text', 'instagram-feed'); ?></label><code class="sbi_shortcode"> buttontext
1725
+ Eg: buttontext="Show more.."</code></th>
1726
+ <td>
1727
+ <input name="sb_instagram_btn_text" type="text" value="<?php echo esc_attr( stripslashes( $sb_instagram_btn_text ) ); ?>" size="20" />
1728
+ </td>
1729
+ </tr>
1730
+ </tbody>
1731
+ </table>
1732
+
1733
+ <?php submit_button(); ?>
1734
+
1735
+ <hr id="follow" />
1736
+ <h3><?php _e("'Follow' Button", 'instagram-feed'); ?></h3>
1737
+ <table class="form-table">
1738
+ <tbody>
1739
+ <tr valign="top">
1740
+ <th scope="row"><label><?php _e("Show the Follow button", 'instagram-feed'); ?></label><code class="sbi_shortcode"> showfollow
1741
+ Eg: showfollow=true</code></th>
1742
+ <td>
1743
+ <input type="checkbox" name="sb_instagram_show_follow_btn" id="sb_instagram_show_follow_btn" <?php if($sb_instagram_show_follow_btn == true) echo 'checked="checked"' ?> />
1744
+ </td>
1745
+ </tr>
1746
+
1747
+ <tr valign="top">
1748
+ <th scope="row"><label><?php _e('Button Background Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followcolor
1749
+ Eg: followcolor=28a1bf</code></th>
1750
+ <td>
1751
+ <input name="sb_instagram_folow_btn_background" type="text" value="<?php echo esc_attr( $sb_instagram_folow_btn_background ); ?>" class="sbi_colorpick" />
1752
+ </td>
1753
+ </tr>
1754
+ <tr valign="top">
1755
+ <th scope="row"><label><?php _e('Button Text Color', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followtextcolor
1756
+ Eg: followtextcolor=000</code></th>
1757
+ <td>
1758
+ <input name="sb_instagram_follow_btn_text_color" type="text" value="<?php echo esc_attr( $sb_instagram_follow_btn_text_color ); ?>" class="sbi_colorpick" />
1759
+ </td>
1760
+ </tr>
1761
+ <tr valign="top">
1762
+ <th scope="row"><label><?php _e('Button Text', 'instagram-feed'); ?></label><code class="sbi_shortcode"> followtext
1763
+ Eg: followtext="Follow me"</code></th>
1764
+ <td>
1765
+ <input name="sb_instagram_follow_btn_text" type="text" value="<?php echo esc_attr( stripslashes( $sb_instagram_follow_btn_text ) ); ?>" size="30" />
1766
+ </td>
1767
+ </tr>
1768
+ </tbody>
1769
+ </table>
1770
+
1771
+ <hr id="filtering" />
1772
+ <h3><?php _e('Post Filtering', 'instagram-feed'); ?></h3>
1773
+
1774
+ <p style="padding-bottom: 18px;">
1775
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Post Filtering options', 'instagram-feed'); ?></a><br />
1776
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1777
+ </p>
1778
+
1779
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1780
+
1781
+ <table class="form-table">
1782
+ <tbody>
1783
+ <tr valign="top" class="sbi_pro">
1784
+ <th scope="row"><label><?php _e('Remove photos containing these words or hashtags', 'instagram-feed'); ?></label></th>
1785
+ <td>
1786
+ <div class="sb_instagram_apply_labels">
1787
+ <p><?php _e('Apply to:', 'instagram-feed'); ?></p>
1788
+ <input class="sb_instagram_incex_one_all" type="radio" value="all" disabled /><label><?php _e('All feeds', 'instagram-feed'); ?></label>
1789
+ <input class="sb_instagram_incex_one_all" type="radio" value="one" disabled /><label><?php _e('One feed', 'instagram-feed'); ?></label>
1790
+ </div>
1791
+
1792
+ <input disabled name="sb_instagram_exclude_words" id="sb_instagram_exclude_words" type="text" style="width: 70%;" value="" />
1793
+ <br />
1794
+ <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate words/hashtags using commas', 'instagram-feed'); ?></span>
1795
+ &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed'); ?></a>
1796
+ <p class="sbi_tooltip"><?php _e("You can use this setting to remove photos which contain certain words or hashtags in the caption. Separate multiple words or hashtags using commas.", 'instagram-feed'); ?></p>
1797
+ </td>
1798
+ </tr>
1799
+
1800
+ <tr valign="top" class="sbi_pro">
1801
+ <th scope="row"><label><?php _e('Show photos containing these words or hashtags', 'instagram-feed'); ?></label></th>
1802
+ <td>
1803
+ <div class="sb_instagram_apply_labels">
1804
+ <p><?php _e('Apply to:', 'instagram-feed'); ?></p>
1805
+ <input class="sb_instagram_incex_one_all" type="radio" value="all" disabled /><label><?php _e('All feeds', 'instagram-feed'); ?></label>
1806
+ <input class="sb_instagram_incex_one_all" type="radio" value="one" disabled /><label><?php _e('One feed', 'instagram-feed'); ?></label>
1807
+ </div>
1808
+
1809
+ <input disabled name="sb_instagram_include_words" id="sb_instagram_include_words" type="text" style="width: 70%;" value="" />
1810
+ <br />
1811
+ <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate words/hashtags using commas', 'instagram-feed'); ?></span>
1812
+ &nbsp;<a class="sbi_tooltip_link sbi_pro" href="JavaScript:void(0);"><?php _e( 'What is this?', 'instagram-feed'); ?></a>
1813
+ <p class="sbi_tooltip"><?php _e("You can use this setting to only show photos which contain certain words or hashtags in the caption. For example, adding <code>sheep, cow, dog</code> will show any photos which contain either the word sheep, cow, or dog. Separate multiple words or hashtags using commas.", 'instagram-feed'); ?></p>
1814
+ </td>
1815
+ </tr>
1816
+ </tbody>
1817
+ </table>
1818
+ </div>
1819
+
1820
+
1821
+ <hr id="moderation" />
1822
+ <h3><?php _e('Moderation', 'instagram-feed'); ?></h3>
1823
+
1824
+ <p style="padding-bottom: 18px;">
1825
+ <a href="https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e('Upgrade to Pro to enable Moderation options', 'instagram-feed'); ?></a><br />
1826
+ <a href="javascript:void(0);" class="button button-secondary sbi-show-pro"><b>+</b> <?php _e('Show Pro Options', 'instagram-feed'); ?></a>
1827
+ </p>
1828
+
1829
+ <div class="sbi-pro-options" style="margin-top: -15px;">
1830
+ <table class="form-table">
1831
+ <tbody>
1832
+ <tr valign="top" class="sbi_pro">
1833
+ <th scope="row"><label><?php _e('Moderation Type', 'instagram-feed'); ?></label></th>
1834
+ <td>
1835
+ <input class="sb_instagram_moderation_mode" checked="checked" disabled type="radio" value="visual" style="margin-top: 0;" /><label><?php _e('Visual', 'instagram-feed'); ?></label>
1836
+ <input class="sb_instagram_moderation_mode" disabled type="radio" value="manual" style="margin-top: 0; margin-left: 10px;"/><label><?php _e('Manual', 'instagram-feed'); ?></label>
1837
+
1838
+ <p class="sbi_tooltip" style="display: block;"><?php _e("<b>Visual Moderation Mode</b><br />This adds a button to each feed that will allow you to hide posts, block users, and create white lists from the front end using a visual interface. Visit <a href='https://smashballoon.com/guide-to-moderation-mode/?utm_source=plugin-free&utm_campaign=sbi' target='_blank'>this page</a> for details", 'instagram-feed'); ?></p>
1839
+
1840
+ </td>
1841
+ </tr>
1842
+
1843
+ <tr valign="top" class="sbi_pro">
1844
+ <th scope="row"><label><?php _e('Only show posts by these users', 'instagram-feed'); ?></label></th>
1845
+ <td>
1846
+ <input type="text" style="width: 70%;" disabled /><br />
1847
+ <span class="sbi_note" style="margin-left: 0;"><?php _e('Separate usernames using commas', 'instagram-feed'); ?></span>
1848
+
1849
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e("What is this?", 'instagram-feed'); ?></a>
1850
+ <p class="sbi_tooltip"><?php _e("You can use this setting to show photos only from certain users in your feed. Just enter the usernames here which you want to show. Separate multiple usernames using commas.", 'instagram-feed'); ?></p>
1851
+ </td>
1852
+ </tr>
1853
+ <tr valign="top" class="sbi_pro">
1854
+ <th scope="row"><label><?php _e('White lists', 'instagram-feed'); ?></label></th>
1855
+ <td>
1856
+ <div class="sbi_white_list_names_wrapper">
1857
+ <?php _e("No white lists currently created", 'instagram-feed'); ?>
1858
+ </div>
1859
+
1860
+ <input disabled class="button-secondary" type="submit" value="<?php esc_attr_e( 'Clear White Lists', 'instagram-feed' ); ?>" />
1861
+ &nbsp;<a class="sbi_tooltip_link" href="JavaScript:void(0);" style="display: inline-block; margin-top: 5px;"><?php _e("What is this?", 'instagram-feed'); ?></a>
1862
+ <p class="sbi_tooltip"><?php _e("This will remove all of the white lists from the database", 'instagram-feed'); ?></p>
1863
+ </td>
1864
+ </tr>
1865
+
1866
+ </tbody>
1867
+ </table>
1868
+ </div>
1869
+
1870
+
1871
+
1872
+ <hr id="customcss" />
1873
+ <h3><?php _e('Misc', 'instagram-feed'); ?></h3>
1874
+
1875
+ <table class="form-table">
1876
+ <tbody>
1877
+ <tr valign="top">
1878
+ <td style="padding-bottom: 0;">
1879
+ <?php _e('<strong style="font-size: 15px;">Custom CSS</strong><br />Enter your own custom CSS in the box below', 'instagram-feed'); ?>
1880
+ </td>
1881
+ </tr>
1882
+ <tr valign="top">
1883
+ <td>
1884
+ <textarea name="sb_instagram_custom_css" id="sb_instagram_custom_css" style="width: 70%;" rows="7"><?php echo esc_textarea( stripslashes($sb_instagram_custom_css), 'instagram-feed' ); ?></textarea>
1885
+ </td>
1886
+ </tr>
1887
+ <tr valign="top" id="customjs">
1888
+ <td style="padding-bottom: 0;">
1889
+ <?php _e('<strong style="font-size: 15px;">Custom JavaScript</strong><br />Enter your own custom JavaScript/jQuery in the box below', 'instagram-feed'); ?>
1890
+ </td>
1891
+ </tr>
1892
+ <tr valign="top">
1893
+ <td>
1894
+ <textarea name="sb_instagram_custom_js" id="sb_instagram_custom_js" style="width: 70%;" rows="7"><?php echo esc_textarea( stripslashes($sb_instagram_custom_js), 'instagram-feed' ); ?></textarea>
1895
+ </td>
1896
+ </tr>
1897
+ </tbody>
1898
+ </table>
1899
+ <table class="form-table">
1900
+ <tbody>
1901
+
1902
+ <tr valign="top">
1903
+ <th scope="row"><label for="sb_instagram_ajax_theme" class="bump-left"><?php _e("Are you using an Ajax powered theme?", 'instagram-feed'); ?></label></th>
1904
+ <td>
1905
+ <input name="sb_instagram_ajax_theme" type="checkbox" id="sb_instagram_ajax_theme" <?php if($sb_instagram_ajax_theme == true) echo "checked"; ?> />
1906
+ <label for="sb_instagram_ajax_theme"><?php _e('Yes', 'instagram-feed'); ?></label>
1907
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1908
+ <p class="sbi_tooltip"><?php _e("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 please check with the theme author.", 'instagram-feed'); ?></p>
1909
+ </td>
1910
+ </tr>
1911
+
1912
+ <tr>
1913
+ <th class="bump-left"><label class="bump-left"><?php _e("Image Resizing", 'instagram-feed'); ?></label></th>
1914
+ <td>
1915
+ <input name="sb_instagram_disable_resize" type="checkbox" id="sb_instagram_disable_resize" <?php if($sb_instagram_disable_resize == true) echo "checked"; ?> />
1916
+ <label for="sb_instagram_disable_resize"><?php _e('Disable Local Image Storing and Resizing', 'instagram-feed'); ?></label><br><br>
1917
+ <input name="sb_instagram_favor_local" type="checkbox" id="sb_instagram_favor_local" <?php if($sb_instagram_favor_local == true) echo "checked"; ?> />
1918
+ <label for="sb_instagram_favor_local"><?php _e('Favor Local Images', 'instagram-feed'); ?></label><br><br>
1919
+
1920
+ <input id="sbi_reset_resized" class="button-secondary" type="submit" value="<?php esc_attr_e( 'Reset Resized Images' ); ?>" style="vertical-align: middle;"/>
1921
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1922
+ <p class="sbi_tooltip"><?php _e("The plugin creates and stores resized versions of images in order to serve a more optimized resolution size in the feed. Click this button to clear all data related to resized images. Enable the setting to favor local images to always use a local, resized image if one is available.", 'instagram-feed'); ?></p>
1923
+ </td>
1924
+ </tr>
1925
+
1926
+ <tr valign="top">
1927
+ <th scope="row"><label><?php _e('API request size', 'instagram-feed'); ?></label><code class="sbi_shortcode"> minnum
1928
+ Eg: minnum=25</code></th>
1929
+ <td>
1930
+ <input name="sb_instagram_minnum" type="number" min="0" max="100" value="<?php echo esc_attr( $sb_instagram_minnum ); ?>" />
1931
+ <span class="sbi_note"><?php _e('Leave at "0" for default', 'instagram-feed'); ?></span>
1932
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1933
+ <p class="sbi_tooltip"><?php _e("If your feed contains a lot of IG TV posts or your feed is not displaying any posts despite there being posts available on Instagram.com, try increasing this number to 25 or more.", 'instagram-feed'); ?></p>
1934
+ </td>
1935
+ </tr>
1936
+
1937
+ <tr valign="top">
1938
+ <th scope="row"><label><?php _e('Enqueue JS file in head', 'instagram-feed'); ?></label></th>
1939
+ <td>
1940
+ <input type="checkbox" name="enqueue_js_in_head" id="sb_instagram_enqueue_js_in_head" <?php if($enqueue_js_in_head == true) echo 'checked="checked"' ?> />
1941
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1942
+ <p class="sbi_tooltip"><?php _e("Check this box if you'd like to enqueue the JavaScript file for the plugin in the head instead of the footer.", 'instagram-feed'); ?></p>
1943
+ </td>
1944
+ </tr>
1945
+
1946
+ <tr valign="top">
1947
+ <th scope="row"><label><?php _e('Enqueue CSS file with shortcode', 'instagram-feed'); ?></label></th>
1948
+ <td>
1949
+ <input type="checkbox" name="enqueue_css_in_shortcode" id="sb_instagram_enqueue_css_in_shortcode" <?php if($enqueue_css_in_shortcode == true) echo 'checked="checked"' ?> />
1950
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1951
+ <p class="sbi_tooltip"><?php _e("Check this box if you'd like to only include the CSS file for the plugin when the feed is on the page.", 'instagram-feed'); ?></p>
1952
+ </td>
1953
+ </tr>
1954
+
1955
+ <tr valign="top">
1956
+ <th scope="row"><label><?php _e('Disable JS Image Loading', 'instagram-feed'); ?></label></th>
1957
+ <td>
1958
+ <input type="checkbox" name="disable_js_image_loading" id="sb_instagram_disable_js_image_loading" <?php if($disable_js_image_loading == true) echo 'checked="checked"' ?> />
1959
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1960
+ <p class="sbi_tooltip"><?php _e("Check this box to have images loaded server side instead of with JS.", 'instagram-feed'); ?></p>
1961
+ </td>
1962
+ </tr>
1963
+
1964
+ <tr valign="top">
1965
+ <th><label><?php _e("Enable Backup Caching", 'instagram-feed'); ?></label></th>
1966
+ <td class="sbi-customize-tab-opt">
1967
+ <input name="sb_instagram_backup" type="checkbox" id="sb_instagram_backup" <?php if($sb_instagram_backup == true) echo "checked"; ?> />
1968
+ <input id="sbi_clear_backups" class="button-secondary" type="submit" style="position: relative; top: -4px;" value="<?php esc_attr_e( 'Clear Backup Cache', 'instagram-feed' ); ?>" />
1969
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1970
+ <p class="sbi_tooltip"><?php _e('Every feed will save a duplicate version of itself in the database to be used if the normal cache is not available.', 'instagram-feed'); ?></p>
1971
+ </td>
1972
+ </tr>
1973
+
1974
+ <tr>
1975
+ <th class="bump-left">
1976
+ <label class="bump-left"><?php _e("Load initial posts with AJAX", 'instagram-feed'); ?></label>
1977
+ </th>
1978
+ <td>
1979
+ <input name="sb_ajax_initial" type="checkbox" id="sb_ajax_initial" <?php if($sb_ajax_initial == true) echo "checked"; ?> />
1980
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1981
+ <p class="sbi_tooltip"><?php _e("Initial posts will be loaded using AJAX instead of added to the page directly. If you use page caching, this will allow the feed to update according to the \"Check for new posts every\" setting on the \"Configure\" tab.", 'instagram-feed'); ?></p>
1982
+ </td>
1983
+ </tr>
1984
+
1985
+ <tr>
1986
+ <th class="bump-left">
1987
+ <label for="sb_instagram_cron" class="bump-left"><?php _e("Force cache to clear on interval", 'instagram-feed'); ?></label>
1988
+ </th>
1989
+ <td>
1990
+ <select name="sb_instagram_cron">
1991
+ <option value="unset" <?php if($sb_instagram_cron == "unset") echo 'selected="selected"' ?> > - </option>
1992
+ <option value="yes" <?php if($sb_instagram_cron == "yes") echo 'selected="selected"' ?> ><?php _e('Yes', 'instagram-feed'); ?></option>
1993
+ <option value="no" <?php if($sb_instagram_cron == "no") echo 'selected="selected"' ?> ><?php _e('No', 'instagram-feed'); ?></option>
1994
+ </select>
1995
+
1996
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
1997
+ <p class="sbi_tooltip"><?php _e("If you're experiencing an issue with the plugin not auto-updating then you can set this to 'Yes' to run a scheduled event behind the scenes which forces the plugin cache to clear on a regular basis and retrieve new data from Instagram.", 'instagram-feed'); ?></p>
1998
+ </td>
1999
+ </tr>
2000
+ </tbody>
2001
+ </table>
2002
+ <table class="form-table">
2003
+ <tbody>
2004
+ <tr valign="top">
2005
+ <th scope="row"><label><?php _e("Disable Icon Font", 'instagram-feed'); ?></label></th>
2006
+ <td>
2007
+ <input type="checkbox" name="sb_instagram_disable_awesome" id="sb_instagram_disable_awesome" <?php if($sb_instagram_disable_awesome == true) echo 'checked="checked"' ?> /> <?php _e( 'Yes', 'instagram-feed' ); ?>
2008
+ </td>
2009
+ </tr>
2010
+ <tr>
2011
+ <th scope="row"><label for="sbi_font_method"><?php _e("Icon Method", 'instagram-feed'); ?></label></th>
2012
+ <td>
2013
+ <select name="sbi_font_method" id="sbi_font_method" class="default-text">
2014
+ <option value="svg" id="sbi-font_method" class="default-text" <?php if($sbi_font_method == 'svg') echo 'selected="selected"' ?>>SVG</option>
2015
+ <option value="fontfile" id="sbi-font_method" class="default-text" <?php if($sbi_font_method == 'fontfile') echo 'selected="selected"' ?>><?php _e("Font File", 'instagram-feed'); ?></option>
2016
+ </select>
2017
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
2018
+ <p class="sbi_tooltip"><?php _e("This plugin uses SVGs for all icons in the feed. Use this setting to switch to font icons.", 'instagram-feed'); ?></p>
2019
+ </td>
2020
+ </tr>
2021
+ <tr>
2022
+ <th class="bump-left"><label class="bump-left"><?php _e("Enable Custom Templates", 'instagram-feed'); ?></label></th>
2023
+ <td>
2024
+ <input name="sb_instagram_custom_template" type="checkbox" id="sb_instagram_custom_template" <?php if($sb_instagram_custom_template == true) echo "checked"; ?> />
2025
+ <label for="sb_instagram_custom_template"><?php _e('Yes', 'instagram-feed'); ?></label>
2026
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
2027
+ <p class="sbi_tooltip"><?php _e("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/guide-to-creating-custom-templates/\" target=\"_blank\">this guide</a>", 'instagram-feed'); ?></p>
2028
+ </td>
2029
+ </tr>
2030
+ <tr>
2031
+ <th class="bump-left"><label class="bump-left"><?php _e("Disable Admin Error Notice", 'instagram-feed'); ?></label></th>
2032
+ <td>
2033
+ <input name="sb_instagram_disable_admin_notice" type="checkbox" id="sb_instagram_disable_admin_notice" <?php if($sb_instagram_disable_admin_notice == true) echo "checked"; ?> />
2034
+ <label for="sb_instagram_disable_admin_notice"><?php _e('Yes', 'instagram-feed'); ?></label>
2035
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
2036
+ <p class="sbi_tooltip"><?php _e("This will permanently disable the feed error notice that displays in the bottom right corner for admins on the front end of your site.", 'instagram-feed'); ?></p>
2037
+ </td>
2038
+ </tr>
2039
+ <tr>
2040
+ <th class="bump-left"><label class="bump-left"><?php _e("Feed Issue Email Report", 'instagram-feed'); ?></label></th>
2041
+ <td>
2042
+ <input name="sb_instagram_enable_email_report" type="checkbox" id="sb_instagram_enable_email_report" <?php if($sb_instagram_enable_email_report == 'on') echo "checked"; ?> />
2043
+ <label for="sb_instagram_enable_email_report"><?php _e('Yes', 'instagram-feed'); ?></label>
2044
+ <a class="sbi_tooltip_link" href="JavaScript:void(0);"><?php _e('What does this mean?', 'instagram-feed'); ?></a>
2045
+ <p class="sbi_tooltip"><?php _e("Instagram Feed will send a weekly notification email using your site's wp_mail() function if one or more of your feeds is not updating or is not displaying. If you're not receiving the emails in your inbox, you may need to configure an SMTP service using another plugin like WP Mail SMTP.", 'instagram-feed'); ?></p>
2046
+
2047
+ <div class="sb_instagram_box" style="display: block;">
2048
+ <div class="sb_instagram_box_setting">
2049
+ <label><?php _e('Schedule Weekly on', 'instagram-feed'); ?></label><br>
2050
+ <?php
2051
+ $schedule_options = array(
2052
+ array(
2053
+ 'val' => 'monday',
2054
+ 'label' => __( 'Monday', 'instagram-feed' )
2055
+ ),
2056
+ array(
2057
+ 'val' => 'tuesday',
2058
+ 'label' => __( 'Tuesday', 'instagram-feed' )
2059
+ ),
2060
+ array(
2061
+ 'val' => 'wednesday',
2062
+ 'label' => __( 'Wednesday', 'instagram-feed' )
2063
+ ),
2064
+ array(
2065
+ 'val' => 'thursday',
2066
+ 'label' => __( 'Thursday', 'instagram-feed' )
2067
+ ),
2068
+ array(
2069
+ 'val' => 'friday',
2070
+ 'label' => __( 'Friday', 'instagram-feed' )
2071
+ ),
2072
+ array(
2073
+ 'val' => 'saturday',
2074
+ 'label' => __( 'Saturday', 'instagram-feed' )
2075
+ ),
2076
+ array(
2077
+ 'val' => 'sunday',
2078
+ 'label' => __( 'Sunday', 'instagram-feed' )
2079
+ ),
2080
+ );
2081
+
2082
+ if ( isset( $_GET['flag'] ) ){
2083
+ echo '<span id="sbi-goto"></span>';
2084
+ }
2085
+ ?>
2086
+ <select name="sb_instagram_email_notification" id="sb_instagram_email_notification">
2087
+ <?php foreach ( $schedule_options as $schedule_option ) : ?>
2088
+ <option value="<?php echo esc_attr( $schedule_option['val'] ) ; ?>" <?php if ( $schedule_option['val'] === $sb_instagram_email_notification ) { echo 'selected';} ?>><?php echo esc_html( $schedule_option['label'] ) ; ?></option>
2089
+ <?php endforeach; ?>
2090
+ </select>
2091
+ </div>
2092
+ <div class="sb_instagram_box_setting">
2093
+ <label><?php _e('Email Recipients', 'instagram-feed'); ?></label><br><input class="regular-text" type="text" name="sb_instagram_email_notification_addresses" value="<?php echo esc_attr( $sb_instagram_email_notification_addresses ); ?>"><span class="sbi_note"><?php _e('separate multiple emails with commas', 'instagram-feed'); ?></span>
2094
+ <br><br><?php _e( 'Emails not working?', 'instagram-feed' ) ?> <a href="https://smashballoon.com/email-report-is-not-in-my-inbox/" target="_blank"><?php _e( 'See our related FAQ', 'instagram-feed' ) ?></a>
2095
+ </div>
2096
+ </div>
2097
+
2098
+ </td>
2099
+ </tr>
2100
+ </tbody>
2101
+ </table>
2102
+
2103
+ <?php submit_button(); ?>
2104
+
2105
+ </form>
2106
+
2107
+ <p><i class="fa fa-chevron-circle-right" aria-hidden="true"></i>&nbsp; <?php _e('Next Step: <a href="?page=sb-instagram-feed&tab=display">Display your Feed</a>', 'instagram-feed'); ?></p>
2108
+
2109
+ <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
2110
+
2111
+
2112
+ <?php } //End Customize tab ?>
2113
+
2114
+
2115
+
2116
+ <?php if( $sbi_active_tab == 'display' ) { //Start Display tab ?>
2117
+
2118
+ <h3><?php _e('Display your Feed', 'instagram-feed'); ?></h3>
2119
+ <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:", 'instagram-feed'); ?></p>
2120
+ <input type="text" value="[instagram-feed]" size="16" 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).', 'instagram-feed'); ?>" />
2121
+
2122
+ <h3 style="padding-top: 10px;"><?php _e( 'Multiple Feeds', 'instagram-feed' ); ?></h3>
2123
+ <p><?php _e("If you'd like to display multiple feeds then you can set different settings directly in the shortcode like so:", 'instagram-feed'); ?>
2124
+ <code>[instagram-feed num=9 cols=3]</code></p>
2125
+ <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:', 'instagram-feed' ); ?><br />
2126
+ <code>[instagram-feed]</code><br />
2127
+ <code>[instagram-feed num=4 cols=4 showfollow=false]</code><br />
2128
+ <code>[instagram-feed accesstoken="ANOTHER_ACCESS_TOKEN"]</code>
2129
+ </p>
2130
+ <p><?php _e("See the table below for a full list of available shortcode options:", 'instagram-feed'); ?></p>
2131
+
2132
+ <p><span class="sbi_table_key"></span><?php _e('Pro version only', 'instagram-feed'); ?></p>
2133
+
2134
+ <table class="sbi_shortcode_table">
2135
+ <tbody>
2136
+ <tr valign="top">
2137
+ <th scope="row"><?php _e('Shortcode option', 'instagram-feed'); ?></th>
2138
+ <th scope="row"><?php _e('Description', 'instagram-feed'); ?></th>
2139
+ <th scope="row"><?php _e('Example', 'instagram-feed'); ?></th>
2140
+ </tr>
2141
+
2142
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Configure Options", 'instagram-feed'); ?></td></tr>
2143
+ <tr class="sbi_pro">
2144
+ <td>type</td>
2145
+ <td><?php _e("Display photos from a User ID (user)<br />Display posts from a Hashtag (hashtag)", 'instagram-feed'); ?><br /><?php _e("Display photos that the account was tagged in (tagged)", 'instagram-feed'); ?></td>
2146
+ <td><code>[instagram-feed type=user]</code><br /><code>[instagram-feed type=hashtag]</code><br /><code>[instagram-feed type=tagged]</code></td>
2147
+ </tr>
2148
+ <tr>
2149
+ <td>user</td>
2150
+ <td><?php _e('Your Instagram User Name. This must be from a connected account on the "Configure" tab.', 'instagram-feed'); ?></td>
2151
+ <td><code>[instagram-feed user="smashballoon"]</code></td>
2152
+ </tr>
2153
+ <tr class="sbi_pro">
2154
+ <td>hashtag</td>
2155
+ <td><?php _e('Any hashtag. Separate multiple hashtags by commas.', 'instagram-feed'); ?></td>
2156
+ <td><code>[instagram-feed hashtag="#awesome"]</code></td>
2157
+ </tr>
2158
+ <tr class="sbi_pro">
2159
+ <td>tagged</td>
2160
+ <td><?php _e('Your Instagram User Name. Separate multiple users by commas.', 'instagram-feed'); ?></td>
2161
+ <td><code>[instagram-feed tagged="smashballoon"]</code></td>
2162
+ </tr>
2163
+
2164
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Customize Options", 'instagram-feed'); ?></td></tr>
2165
+ <tr>
2166
+ <td>width</td>
2167
+ <td><?php _e("The width of your feed. Any number.", 'instagram-feed'); ?></td>
2168
+ <td><code>[instagram-feed width=50]</code></td>
2169
+ </tr>
2170
+ <tr>
2171
+ <td>widthunit</td>
2172
+ <td><?php _e("The unit of the width. 'px' or '%'", 'instagram-feed'); ?></td>
2173
+ <td><code>[instagram-feed widthunit=%]</code></td>
2174
+ </tr>
2175
+ <tr>
2176
+ <td>height</td>
2177
+ <td><?php _e("The height of your feed. Any number.", 'instagram-feed'); ?></td>
2178
+ <td><code>[instagram-feed height=250]</code></td>
2179
+ </tr>
2180
+ <tr>
2181
+ <td>heightunit</td>
2182
+ <td><?php _e("The unit of the height. 'px' or '%'", 'instagram-feed'); ?></td>
2183
+ <td><code>[instagram-feed heightunit=px]</code></td>
2184
+ </tr>
2185
+ <tr>
2186
+ <td>background</td>
2187
+ <td><?php _e("The background color of the feed. Any hex color code.", 'instagram-feed'); ?></td>
2188
+ <td><code>[instagram-feed background=#ffff00]</code></td>
2189
+ </tr>
2190
+ <tr>
2191
+ <td>class</td>
2192
+ <td><?php _e("Add a CSS class to the feed container", 'instagram-feed'); ?></td>
2193
+ <td><code>[instagram-feed class=feedOne]</code></td>
2194
+ </tr>
2195
+
2196
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Layout Options", 'instagram-feed'); ?></td></tr>
2197
+ <tr class="sbi_pro">
2198
+ <td>layout</td>
2199
+ <td><?php _e("How posts are arranged visually in the feed. There are four layouts: Grid, Carousel Slider, Masonry Grid, or Highlight Grid. Options:", 'instagram-feed' ); ?> 'grid', 'carousel', 'masonry', or 'highlight'</td>
2200
+ <td><code>[instagram-feed layout=grid]</code></td>
2201
+ </tr>
2202
+ <tr>
2203
+ <td>num</td>
2204
+ <td><?php _e("The number of photos to display initially. Maximum is 33.", 'instagram-feed'); ?></td>
2205
+ <td><code>[instagram-feed num=10]</code></td>
2206
+ </tr>
2207
+ <tr class="sbi_pro">
2208
+ <td>nummobile</td>
2209
+ <td><?php _e("The number of photos to display initially for mobile screens (smaller than 480 pixels).", 'instagram-feed'); ?></td>
2210
+ <td><code>[instagram-feed nummobile=6]</code></td>
2211
+ </tr>
2212
+ <tr>
2213
+ <td>cols</td>
2214
+ <td><?php _e("The number of columns in your feed. 1 - 10.", 'instagram-feed'); ?></td>
2215
+ <td><code>[instagram-feed cols=5]</code></td>
2216
+ </tr>
2217
+ <tr class="sbi_pro">
2218
+ <td>colsmobile</td>
2219
+ <td><?php _e("The number of columns in your feed for mobile screens (smaller than 480 pixels).", 'instagram-feed'); ?></td>
2220
+ <td><code>[instagram-feed colsmobile=2]</code></td>
2221
+ </tr>
2222
+ <tr>
2223
+ <td>imagepadding</td>
2224
+ <td><?php _e("The spacing around your photos", 'instagram-feed'); ?></td>
2225
+ <td><code>[instagram-feed imagepadding=10]</code></td>
2226
+ </tr>
2227
+ <tr>
2228
+ <td>imagepaddingunit</td>
2229
+ <td><?php _e("The unit of the padding. 'px' or '%'", 'instagram-feed'); ?></td>
2230
+ <td><code>[instagram-feed imagepaddingunit=px]</code></td>
2231
+ </tr>
2232
+
2233
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Carousel Options", 'instagram-feed'); ?></td></tr>
2234
+ <tr class="sbi_pro">
2235
+ <td>carouselrows</td>
2236
+ <td><?php _e("Choose 1 or 2 rows of posts in the carousel", 'instagram-feed'); ?></td>
2237
+ <td><code>[instagram-feed carouselrows=1]</code></td>
2238
+ </tr>
2239
+ <tr class="sbi_pro">
2240
+ <td>carouselloop</td>
2241
+ <td><?php _e("Infinitely loop through posts or rewind", 'instagram-feed'); ?></td>
2242
+ <td><code>[instagram-feed carouselloop=rewind]</code></td>
2243
+ </tr>
2244
+ <tr class="sbi_pro">
2245
+ <td>carouselarrows</td>
2246
+ <td><?php _e("Display directional arrows on the carousel", 'instagram-feed'); ?></td>
2247
+ <td><code>[instagram-feed carouselarrows=true]</code></td>
2248
+ </tr>
2249
+ <tr class="sbi_pro">
2250
+ <td>carouselpag</td>
2251
+ <td><?php _e("Display pagination links below the carousel", 'instagram-feed'); ?></td>
2252
+ <td><code>[instagram-feed carouselpag=true]</code></td>
2253
+ </tr>
2254
+ <tr class="sbi_pro">
2255
+ <td>carouselautoplay</td>
2256
+ <td><?php _e("Make the carousel autoplay", 'instagram-feed'); ?></td>
2257
+ <td><code>[instagram-feed carouselautoplay=true]</code></td>
2258
+ </tr>
2259
+ <tr class="sbi_pro">
2260
+ <td>carouseltime</td>
2261
+ <td><?php _e("The interval time between slides for autoplay. Time in miliseconds.", 'instagram-feed'); ?></td>
2262
+ <td><code>[instagram-feed carouseltime=8000]</code></td>
2263
+ </tr>
2264
+
2265
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Highlight Options", 'instagram-feed'); ?></td></tr>
2266
+ <tr class="sbi_pro">
2267
+ <td>highlighttype</td>
2268
+ <td><?php _e("Choose from 3 different ways of highlighting posts including by pattern, hashtag, post id or. Options:", 'instagram-feed'); ?> 'pattern', 'hashtag', 'id'.</td>
2269
+ <td><code>[instagram-feed highlighttype=hashtag]</code></td>
2270
+ </tr>
2271
+ <tr class="sbi_pro">
2272
+ <td>highlightpattern</td>
2273
+ <td><?php _e("How often a post is highlighted.", 'instagram-feed'); ?></td>
2274
+ <td><code>[instagram-feed highlightpattern=7]</code></td>
2275
+ </tr>
2276
+ <tr class="sbi_pro">
2277
+ <td>highlightoffset</td>
2278
+ <td><?php _e("When to start the highlight pattern.", 'instagram-feed'); ?></td>
2279
+ <td><code>[instagram-feed highlightoffset=3]</code></td>
2280
+ </tr>
2281
+ <tr class="sbi_pro">
2282
+ <td>highlighthashtag</td>
2283
+ <td><?php _e("Highlight posts with these hashtags.", 'instagram-feed'); ?></td>
2284
+ <td><code>[instagram-feed highlighthashtag=best]</code></td>
2285
+ </tr>
2286
+
2287
+
2288
+
2289
+
2290
+
2291
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Photos Options", 'instagram-feed'); ?></td></tr>
2292
+ <tr>
2293
+ <td>sortby</td>
2294
+ <td><?php _e("Sort the posts by Newest to Oldest (none) or Random (random)", 'instagram-feed'); ?></td>
2295
+ <td><code>[instagram-feed sortby=random]</code></td>
2296
+ </tr>
2297
+ <tr>
2298
+ <td>imageres</td>
2299
+ <td><?php _e("The resolution/size of the photos including full, medium, thumbnail, and auto (based on size of image on page). Options:", 'instagram-feed'); ?> 'auto', full', 'medium' or 'thumb'.</td>
2300
+ <td><code>[instagram-feed imageres=full]</code></td>
2301
+ </tr>
2302
+ <tr class="sbi_pro">
2303
+ <td>media</td>
2304
+ <td><?php _e("Display all media, only photos, or only videos", 'instagram-feed'); ?></td>
2305
+ <td><code>[instagram-feed media=photos]</code></td>
2306
+ </tr>
2307
+ <tr class="sbi_pro">
2308
+ <td>disablelightbox</td>
2309
+ <td><?php _e("Whether to disable the photo Lightbox. It is enabled by default.", 'instagram-feed'); ?></td>
2310
+ <td><code>[instagram-feed disablelightbox=true]</code></td>
2311
+ </tr>
2312
+ <tr>
2313
+ <td>disablemobile</td>
2314
+ <td><?php _e("Disable the mobile layout. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2315
+ <td><code>[instagram-feed disablemobile=true]</code></td>
2316
+ </tr>
2317
+ <tr class="sbi_pro">
2318
+ <td>captionlinks</td>
2319
+ <td><?php _e("Whether to use urls in captions for the photo's link instead of linking to instagram.com.", 'instagram-feed'); ?></td>
2320
+ <td><code>[instagram-feed captionlinks=true]</code></td>
2321
+ </tr>
2322
+
2323
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Lightbox Comments Options", 'instagram-feed'); ?></td></tr>
2324
+ <tr class="sbi_pro">
2325
+ <td>lightboxcomments</td>
2326
+ <td><?php _e("Whether to show comments in the lightbox for this feed.", 'instagram-feed'); ?></td>
2327
+ <td><code>[instagram-feed lightboxcomments=true]</code></td>
2328
+ </tr>
2329
+ <tr class="sbi_pro">
2330
+ <td>numcomments</td>
2331
+ <td><?php _e("Number of comments to show starting from the most recent.", 'instagram-feed'); ?></td>
2332
+ <td><code>[instagram-feed numcomments=10]</code></td>
2333
+ </tr>
2334
+
2335
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Photos Hover Style Options", 'instagram-feed'); ?></td></tr>
2336
+ <tr class="sbi_pro">
2337
+ <td>hovercolor</td>
2338
+ <td><?php _e("The background color when hovering over a photo. Any hex color code.", 'instagram-feed'); ?></td>
2339
+ <td><code>[instagram-feed hovercolor=#ff0000]</code></td>
2340
+ </tr>
2341
+ <tr class="sbi_pro">
2342
+ <td>hovertextcolor</td>
2343
+ <td><?php _e("The text/icon color when hovering over a photo. Any hex color code.", 'instagram-feed'); ?></td>
2344
+ <td><code>[instagram-feed hovertextcolor=#fff]</code></td>
2345
+ </tr>
2346
+ <tr class="sbi_pro">
2347
+ <td>hoverdisplay</td>
2348
+ <td><?php _e("The info to display when hovering over the photo such as the user name, post date, Instagram icon, location, caption, and like counts. Options:", 'instagram-feed'); ?><br />username, date, instagram, location, caption, likes</td>
2349
+ <td><code>[instagram-feed hoverdisplay="date, location, likes"]</code></td>
2350
+ </tr>
2351
+
2352
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Header Options", 'instagram-feed'); ?></td></tr>
2353
+ <tr>
2354
+ <td>showheader</td>
2355
+ <td><?php _e("Whether to show the feed Header. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2356
+ <td><code>[instagram-feed showheader=false]</code></td>
2357
+ </tr>
2358
+ <tr>
2359
+ <td>showbio</td>
2360
+ <td><?php _e("Display the bio in the header. Options:", 'instagram-feed'); ?> 'true' or 'false'</td>
2361
+ <td><code>[instagram-feed showbio=true]</code></td>
2362
+ </tr>
2363
+ <tr>
2364
+ <td>custombio</td>
2365
+ <td><?php _e("Display a custom bio in the header", 'instagram-feed'); ?></td>
2366
+ <td><code>[instagram-feed custombio="My custom bio."]</code></td>
2367
+ </tr>
2368
+ <tr>
2369
+ <td>customavatar</td>
2370
+ <td><?php _e("Display a custom avatar in the header. Enter the full URL of an image file.", 'instagram-feed'); ?></td>
2371
+ <td><code>[instagram-feed customavatar="https://example.com/avatar.jpg"]</code></td>
2372
+ </tr>
2373
+ <tr>
2374
+ <td>headersize</td>
2375
+ <td><?php _e("Size of the header including small, medium and large. Options:", 'instagram-feed'); ?> small, medium, or large.</td>
2376
+ <td><code>[instagram-feed headersize=medium]</code></td>
2377
+ </tr>
2378
+ <tr>
2379
+ <td>headercolor</td>
2380
+ <td><?php _e("The color of the Header text. Any hex color code.", 'instagram-feed'); ?></td>
2381
+ <td><code>[instagram-feed headercolor=#333]</code></td>
2382
+ </tr>
2383
+
2384
+ <tr class="sbi_table_header"><td colspan=3><?php _e("'Load More' Button Options", 'instagram-feed'); ?></td></tr>
2385
+ <tr>
2386
+ <td>showbutton</td>
2387
+ <td><?php _e("Whether to show the 'Load More' button. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2388
+ <td><code>[instagram-feed showbutton=false]</code></td>
2389
+ </tr>
2390
+ <tr>
2391
+ <td>buttoncolor</td>
2392
+ <td><?php _e("The background color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2393
+ <td><code>[instagram-feed buttoncolor=#000]</code></td>
2394
+ </tr>
2395
+ <tr>
2396
+ <td>buttontextcolor</td>
2397
+ <td><?php _e("The text color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2398
+ <td><code>[instagram-feed buttontextcolor=#fff]</code></td>
2399
+ </tr>
2400
+ <tr>
2401
+ <td>buttontext</td>
2402
+ <td><?php _e("The text used for the button.", 'instagram-feed'); ?></td>
2403
+ <td><code>[instagram-feed buttontext="Load More Photos"]</code></td>
2404
+ </tr>
2405
+
2406
+ <tr class="sbi_table_header"><td colspan=3><?php _e("'Follow on Instagram' Button Options", 'instagram-feed'); ?></td></tr>
2407
+ <tr>
2408
+ <td>showfollow</td>
2409
+ <td><?php _e("Whether to show the 'Follow on Instagram' button. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2410
+ <td><code>[instagram-feed showfollow=false]</code></td>
2411
+ </tr>
2412
+ <tr>
2413
+ <td>followcolor</td>
2414
+ <td><?php _e("The background color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2415
+ <td><code>[instagram-feed followcolor=#ff0000]</code></td>
2416
+ </tr>
2417
+ <tr>
2418
+ <td>followtextcolor</td>
2419
+ <td><?php _e("The text color of the button. Any hex color code.", 'instagram-feed'); ?></td>
2420
+ <td><code>[instagram-feed followtextcolor=#fff]</code></td>
2421
+ </tr>
2422
+ <tr>
2423
+ <td>followtext</td>
2424
+ <td><?php _e("The text used for the button.", 'instagram-feed'); ?></td>
2425
+ <td><code>[instagram-feed followtext="Follow me"]</code></td>
2426
+ </tr>
2427
+
2428
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Caption Options", 'instagram-feed'); ?></td></tr>
2429
+ <tr class="sbi_pro">
2430
+ <td>showcaption</td>
2431
+ <td><?php _e("Whether to show the photo caption. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2432
+ <td><code>[instagram-feed showcaption=false]</code></td>
2433
+ </tr>
2434
+ <tr class="sbi_pro">
2435
+ <td>captionlength</td>
2436
+ <td><?php _e("The number of characters of the caption to display", 'instagram-feed'); ?></td>
2437
+ <td><code>[instagram-feed captionlength=50]</code></td>
2438
+ </tr>
2439
+ <tr class="sbi_pro">
2440
+ <td>captioncolor</td>
2441
+ <td><?php _e("The text color of the caption. Any hex color code.", 'instagram-feed'); ?></td>
2442
+ <td><code>[instagram-feed captioncolor=#000]</code></td>
2443
+ </tr>
2444
+ <tr class="sbi_pro">
2445
+ <td>captionsize</td>
2446
+ <td><?php _e("The size of the caption text. Any number.", 'instagram-feed'); ?></td>
2447
+ <td><code>[instagram-feed captionsize=24]</code></td>
2448
+ </tr>
2449
+
2450
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Likes &amp; Comments Options", 'instagram-feed'); ?></td></tr>
2451
+ <tr class="sbi_pro">
2452
+ <td>showlikes</td>
2453
+ <td><?php _e("Whether to show the Likes &amp; Comments. Options:", 'instagram-feed'); ?> 'true' or 'false'.</td>
2454
+ <td><code>[instagram-feed showlikes=false]</code></td>
2455
+ </tr>
2456
+ <tr class="sbi_pro">
2457
+ <td>likescolor</td>
2458
+ <td><?php _e("The color of the Likes &amp; Comments. Any hex color code.", 'instagram-feed'); ?></td>
2459
+ <td><code>[instagram-feed likescolor=#FF0000]</code></td>
2460
+ </tr>
2461
+ <tr class="sbi_pro">
2462
+ <td>likessize</td>
2463
+ <td><?php _e("The size of the Likes &amp; Comments. Any number.", 'instagram-feed'); ?></td>
2464
+ <td><code>[instagram-feed likessize=14]</code></td>
2465
+ </tr>
2466
+
2467
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Post Filtering Options", 'instagram-feed'); ?></td></tr>
2468
+ <tr class="sbi_pro">
2469
+ <td>excludewords</td>
2470
+ <td><?php _e("Remove posts which contain certain words or hashtags in the caption.", 'instagram-feed'); ?></td>
2471
+ <td><code>[instagram-feed excludewords="bad, words"]</code></td>
2472
+ </tr>
2473
+ <tr class="sbi_pro">
2474
+ <td>includewords</td>
2475
+ <td><?php _e("Only display posts which contain certain words or hashtags in the caption.", 'instagram-feed'); ?></td>
2476
+ <td><code>[instagram-feed includewords="sunshine"]</code></td>
2477
+ </tr>
2478
+
2479
+ <tr class="sbi_table_header"><td colspan=3><?php _e("Auto Load More on Scroll", 'instagram-feed'); ?></td></tr>
2480
+ <tr class="sbi_pro">
2481
+ <td>autoscroll</td>
2482
+ <td><?php _e("Load more posts automatically as the user scrolls down the page.", 'instagram-feed'); ?></td>
2483
+ <td><code>[instagram-feed autoscroll=true]</code></td>
2484
+ </tr>
2485
+ <tr class="sbi_pro">
2486
+ <td>autoscrolldistance</td>
2487
+ <td><?php _e("Distance before the end of feed or page that triggers the loading of more posts.", 'instagram-feed'); ?></td>
2488
+ <td><code>[instagram-feed autoscrolldistance=200]</code></td>
2489
+ </tr>
2490
+
2491
+ </tbody>
2492
+ </table>
2493
+
2494
+ <p><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">setup directions</a>', 'instagram-feed'); ?></p>
2495
+
2496
+ <?php } //End Display tab ?>
2497
+
2498
+
2499
+ <?php if( $sbi_active_tab == 'support' ) { //Start Support tab ?>
2500
+
2501
+ <div class="sbi_support">
2502
+
2503
+ <br/>
2504
+ <h3 style="padding-bottom: 10px;"><?php _e("Need help?", 'instagram-feed'); ?></h3>
2505
+
2506
+ <p>
2507
+ <span class="sbi-support-title"><i class="fa fa-life-ring" aria-hidden="true"></i>&nbsp; <a
2508
+ href="https://smashballoon.com/instagram-feed/free/?utm_source=plugin-free&utm_campaign=sbi"
2509
+ target="_blank"><?php _e( 'Setup Directions', 'instagram-feed' ); ?></a></span>
2510
+ <?php _e( 'A step-by-step guide on how to setup and use the plugin.', 'instagram-feed' ); ?>
2511
+ </p>
2512
+
2513
+ <p>
2514
+ <span class="sbi-support-title"><i class="fa fa-youtube-play" aria-hidden="true"></i>&nbsp; <a
2515
+ href="https://www.youtube.com/embed/q6ZXVU4g970" target="_blank"
2516
+ id="sbi-play-support-video"><?php _e( 'Watch a Video', 'instagram-feed' ); ?></a></span>
2517
+ <?php _e( "Watch a short video demonstrating how to set up, customize and use the plugin.<br /><b>Please note</b> that the video shows the set up and use of the <b><a href='https://smashballoon.com/instagram-feed/?utm_source=plugin-free&utm_campaign=sbi' target='_blank'>Pro version</a></b> of the plugin, but the process is the same for this free version. The only difference is some of the features available.", 'instagram-feed' ); ?>
2518
+
2519
+ <iframe id="sbi-support-video"
2520
+ src="//www.youtube.com/embed/q6ZXVU4g970?theme=light&amp;showinfo=0&amp;controls=2" width="960"
2521
+ height="540" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
2522
+ </p>
2523
+
2524
+ <p>
2525
+ <span class="sbi-support-title"><i class="fa fa-question-circle" aria-hidden="true"></i>&nbsp; <a
2526
+ href="https://smashballoon.com/instagram-feed/support/faq/?utm_source=plugin-free&utm_campaign=sbi"
2527
+ target="_blank"><?php _e( 'FAQs and Docs', 'instagram-feed' ); ?></a></span>
2528
+ <?php _e( 'View our expansive library of FAQs and documentation to help solve your problem as quickly as possible.', 'instagram-feed' ); ?>
2529
+ </p>
2530
+
2531
+ <div class="sbi-support-faqs">
2532
+
2533
+ <ul>
2534
+ <li><b><?php _e( 'FAQs', 'instagram-feed' ); ?></b></li>
2535
+ <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/my-photos-wont-load/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">My Instagram Feed Won\'t Load</a>', 'instagram-feed' ); ?></li>
2536
+ <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/my-instagram-access-token-keep-expiring/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">My Access Token Keeps Expiring</a>', 'instagram-feed' ); ?></li>
2537
+ <li style="margin-top: 8px; font-size: 12px;"><a href="https://smashballoon.com/instagram-feed/support/faq/?utm_source=plugin-free&utm_campaign=sbi" target="_blank"><?php _e( 'See All', 'instagram-feed' ); ?><i class="fa fa-chevron-right" aria-hidden="true"></i></a></li>
2538
+ </ul>
2539
+
2540
+ <ul>
2541
+ <li><b><?php _e("Documentation", 'instagram-feed'); ?></b></li>
2542
+ <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/instagram-feed/free?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Installation and Configuration</a>', 'instagram-feed' ); ?></li>
2543
+ <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/display-multiple-instagram-feeds/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Displaying multiple feeds</a>', 'instagram-feed' ); ?></li>
2544
+ <li>&bull;&nbsp; <?php _e( '<a href="https://smashballoon.com/instagram-feed-faq/customization/?utm_source=plugin-free&utm_campaign=sbi" target="_blank">Customizing your Feed</a>', 'instagram-feed' ); ?></li>
2545
+ </ul>
2546
+ </div>
2547
+
2548
+ <p>
2549
+ <span class="sbi-support-title"><i class="fa fa-envelope" aria-hidden="true"></i>&nbsp; <a
2550
+ href="https://smashballoon.com/instagram-feed/support/?utm_source=plugin-free&utm_campaign=sbi"
2551
+ target="_blank"><?php _e( 'Request Support', 'instagram-feed' ); ?></a></span>
2552
+ <?php _e( 'Still need help? Submit a ticket and one of our support experts will get back to you as soon as possible.<br /><b>Important:</b> Please include your <b>System Info</b> below with all support requests.', 'instagram-feed' ); ?>
2553
+ </p>
2554
+ </div>
2555
+
2556
+ <hr />
2557
+
2558
+ <h3><?php _e('System Info &nbsp; <i style="color: #666; font-size: 11px; font-weight: normal;">Click the text below to select all</i>', 'instagram-feed'); ?></h3>
2559
+
2560
+
2561
+
2562
+
2563
+ <?php $sbi_options = get_option('sb_instagram_settings'); ?>
2564
+ <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: 100%; max-width: 960px; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
2565
+ ## SITE/SERVER INFO: ##
2566
+ Site URL: <?php echo site_url() . "\n"; ?>
2567
+ Home URL: <?php echo home_url() . "\n"; ?>
2568
+ WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
2569
+ PHP Version: <?php echo PHP_VERSION . "\n"; ?>
2570
+ Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
2571
+
2572
+ ## ACTIVE PLUGINS: ##
2573
+ <?php
2574
+ $plugins = get_plugins();
2575
+ $active_plugins = get_option( 'active_plugins', array() );
2576
+
2577
+ foreach ( $plugins as $plugin_path => $plugin ) {
2578
+ // If the plugin isn't active, don't show it.
2579
+ if ( ! in_array( $plugin_path, $active_plugins ) )
2580
+ continue;
2581
+
2582
+ echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
2583
+ }
2584
+ ?>
2585
+
2586
+ ## PLUGIN SETTINGS: ##
2587
+ sb_instagram_plugin_type => Instagram Feed Free
2588
+ <?php
2589
+ global $wpdb;
2590
+ foreach( $sbi_options as $key => $val ) {
2591
+ if ( $key !== 'connected_accounts' ) {
2592
+ if ( is_array( $val ) ) {
2593
+ foreach ( $val as $item ) {
2594
+ if ( is_array( $item ) ) {
2595
+ foreach ( $item as $key2 => $val2 ) {
2596
+ echo "$key2 => $val2\n";
2597
+ }
2598
+ } else {
2599
+ echo "$key => $item\n";
2600
+ }
2601
+ }
2602
+ } else {
2603
+ echo "$key => $val\n";
2604
+ }
2605
+ }
2606
+
2607
+ }
2608
+ ?>
2609
+
2610
+ ## CONNECTED ACCOUNTS: ##<?php echo "\n";
2611
+ $con_accounts = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
2612
+ $business_accounts = array();
2613
+ $basic_accounts = array();
2614
+ if ( ! empty( $con_accounts ) ) {
2615
+ foreach ( $con_accounts as $account ) {
2616
+ $type = isset( $account['type'] ) ? $account['type'] : 'personal';
2617
+
2618
+ if ( $type === 'business' ) {
2619
+ $business_accounts[] = $account;
2620
+ } elseif ( $type === 'basic' ) {
2621
+ $basic_accounts[] = $account;
2622
+ }
2623
+ echo '*' . $account['user_id'] . '*' . "\n";
2624
+ var_export( $account );
2625
+ echo "\n";
2626
+ }
2627
+ }
2628
+ ?>
2629
+
2630
+ ## API RESPONSE: ##
2631
+ <?php
2632
+ $first_con_basic_account = isset( $basic_accounts[0] ) ? $basic_accounts[0] : array();
2633
+ $first_con_business_account = isset( $business_accounts[0] ) ? $business_accounts[0] : array();
2634
+
2635
+ if ( ! empty( $first_con_basic_account ) ) {
2636
+ echo '*BASIC ACCOUNT*';
2637
+ echo "\n";
2638
+ $connection = new SB_Instagram_API_Connect( $first_con_basic_account, 'header' );
2639
+ $connection->connect();
2640
+ if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
2641
+ foreach ( $connection->get_data() as $key => $item ) {
2642
+ if ( is_array ( $item ) ) {
2643
+ foreach ( $item as $key2 => $item2 ) {
2644
+ echo $key2 . ' => ' . esc_html( $item2 ) . "\n";
2645
+ }
2646
+ } else {
2647
+ echo $key . ' => ' . esc_html( $item ) . "\n";
2648
+ }
2649
+ }
2650
+ } else {
2651
+ if ( $connection->is_wp_error() ) {
2652
+ $response = $connection->get_wp_error();
2653
+ if ( isset( $response ) && isset( $response->errors ) ) {
2654
+ foreach ( $response->errors as $key => $item ) {
2655
+ echo $key . ' => ' . $item[0] . "\n";
2656
+ }
2657
+ }
2658
+ } else {
2659
+ $error = $connection->get_data();
2660
+ var_export( $error );
2661
+ }
2662
+ }
2663
+ echo "\n";
2664
+ } else {
2665
+ echo 'no connected basic accounts';
2666
+ echo "\n";
2667
+ }
2668
+ if ( ! empty( $first_con_business_account ) ) {
2669
+ echo '*BUSINESS ACCOUNT*';
2670
+ echo "\n";
2671
+ $connection = new SB_Instagram_API_Connect( $first_con_business_account, 'header' );
2672
+ $connection->connect();
2673
+ if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
2674
+ foreach ( $connection->get_data() as $key => $item ) {
2675
+ if ( is_array ( $item ) ) {
2676
+ foreach ( $item as $key2 => $item2 ) {
2677
+ echo $key2 . ' => ' . esc_html( $item2 ) . "\n";
2678
+ }
2679
+ } else {
2680
+ echo $key . ' => ' . esc_html( $item ) . "\n";
2681
+ }
2682
+ }
2683
+ } else {
2684
+ if ( $connection->is_wp_error() ) {
2685
+ $response = $connection->get_wp_error();
2686
+ if ( isset( $response ) && isset( $response->errors ) ) {
2687
+ foreach ( $response->errors as $key => $item ) {
2688
+ echo $key . ' => ' . $item[0] . "\n";
2689
+ }
2690
+ }
2691
+ } else {
2692
+ $error = $connection->get_data();
2693
+ var_export( $error );
2694
+ }
2695
+ }
2696
+ } else {
2697
+ echo 'no connected business accounts';
2698
+ } ?>
2699
+
2700
+ ## Cron Events: ##
2701
+ <?php
2702
+ $cron = _get_cron_array();
2703
+ foreach ( $cron as $key => $data ) {
2704
+ $is_target = false;
2705
+ foreach ( $data as $key2 => $val ) {
2706
+ if ( strpos( $key2, 'sbi' ) !== false || strpos( $key2, 'sb_instagram' ) !== false ) {
2707
+ $is_target = true;
2708
+ echo $key2;
2709
+ echo "\n";
2710
+ }
2711
+ }
2712
+ if ( $is_target) {
2713
+ echo date( "Y-m-d H:i:s", $key );
2714
+ echo "\n";
2715
+ echo 'Next Scheduled: ' . ((int)$key - time())/60 . ' minutes';
2716
+ echo "\n\n";
2717
+ }
2718
+ }
2719
+ ?>
2720
+ ## Cron Cache Report: ##
2721
+ <?php $cron_report = get_option( 'sbi_cron_report', array() );
2722
+ if ( ! empty( $cron_report ) ) {
2723
+ var_export( $cron_report );
2724
+ }
2725
+ echo "\n";
2726
+ ?>
2727
+
2728
+ ## Access Token Refresh: ##
2729
+ <?php $cron_report = get_option( 'sbi_refresh_report', array() );
2730
+ if ( ! empty( $cron_report ) ) {
2731
+ var_export( $cron_report );
2732
+ }
2733
+ echo "\n";
2734
+ ?>
2735
+
2736
+ ## Resizing: ##
2737
+ <?php $upload = wp_upload_dir();
2738
+ $upload_dir = $upload['basedir'];
2739
+ $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
2740
+ if ( file_exists( $upload_dir ) ) {
2741
+ echo 'upload directory exists';
2742
+ } else {
2743
+ $created = wp_mkdir_p( $upload_dir );
2744
+
2745
+ if ( ! $created ) {
2746
+ echo 'cannot create upload directory';
2747
+ }
2748
+ }
2749
+ echo "\n";
2750
+ echo "\n";
2751
+
2752
+ $table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE );
2753
+ $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
2754
+
2755
+ if ( $wpdb->get_var( "show tables like '$feeds_posts_table_name'" ) != $feeds_posts_table_name ) {
2756
+ echo 'no feeds posts table';
2757
+ echo "\n";
2758
+
2759
+ } else {
2760
+ $last_result = $wpdb->get_results( "SELECT * FROM $feeds_posts_table_name ORDER BY id DESC LIMIT 1;" );
2761
+ if ( is_array( $last_result ) && isset( $last_result[0] ) ) {
2762
+ echo '*FEEDS POSTS TABLE*';
2763
+ echo "\n";
2764
+
2765
+ foreach ( $last_result as $column ) {
2766
+
2767
+ foreach ( $column as $key => $value ) {
2768
+ echo $key . ': ' . esc_html( $value ) . "\n";;
2769
+ }
2770
+ }
2771
+
2772
+ } else {
2773
+ echo 'feeds posts has no rows';
2774
+ echo "\n";
2775
+ }
2776
+ }
2777
+ echo "\n";
2778
+
2779
+ if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) {
2780
+ echo 'no posts table';
2781
+ echo "\n";
2782
+
2783
+ } else {
2784
+
2785
+
2786
+ $last_result = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY id DESC LIMIT 1;" );
2787
+ if ( is_array( $last_result ) && isset( $last_result[0] ) ) {
2788
+ echo '*POSTS TABLE*';
2789
+ echo "\n";
2790
+ foreach ( $last_result as $column ) {
2791
+
2792
+ foreach ( $column as $key => $value ) {
2793
+ echo $key . ': ' . esc_html( $value ) . "\n";;
2794
+ }
2795
+ }
2796
+
2797
+ } else {
2798
+ echo 'feeds posts has no rows';
2799
+ echo "\n";
2800
+ }
2801
+ }
2802
+
2803
+ ?>
2804
+
2805
+ ## Error Log: ##
2806
+ <?php
2807
+ global $sb_instagram_posts_manager;
2808
+ $errors = $sb_instagram_posts_manager->get_errors();
2809
+ if ( ! empty( $errors ) ) :
2810
+ foreach ( $errors as $type => $error ) :
2811
+ echo $type . ': ' . $error[1] . "\n";
2812
+ endforeach;
2813
+ endif;
2814
+ $ajax_statuses = $sb_instagram_posts_manager->get_ajax_status();
2815
+ if ( ! $ajax_statuses['successful'] ) {
2816
+ ## AJAX Status ##
2817
+ echo 'test not successful';
2818
+ }
2819
+ ?>
2820
+ </textarea>
2821
+ <div><input id="sbi_reset_log" class="button-secondary" type="submit" value="<?php esc_attr_e( 'Reset Error Log' ); ?>" style="vertical-align: middle;"/></div>
2822
+
2823
+ <?php
2824
+ } //End Support tab
2825
+ ?>
2826
+
2827
+
2828
+ <div class="sbi_quickstart">
2829
+ <h3><i class="fa fa-rocket" aria-hidden="true"></i>&nbsp; <?php _e('Display your feed', 'instagram-feed'); ?></h3>
2830
+ <p><?php _e('Copy and paste this shortcode directly into the page, post or widget where you\'d like to display the feed:', 'instagram-feed'); ?> <input type="text" value="[instagram-feed]" size="15" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)."></p>
2831
+ <p><?php _e('Find out how to display <a href="?page=sb-instagram-feed&amp;tab=display">multiple feeds</a>.', 'instagram-feed'); ?></p>
2832
+ </div>
2833
+
2834
+ <a href="https://smashballoon.com/instagram-feed/demo/?utm_source=plugin-free&utm_campaign=sbi" target="_blank" class="sbi-pro-notice">
2835
+ <img src="<?php echo SBI_PLUGIN_URL . 'img/instagram-pro-promo.png?2019'; ?>" alt="<?php esc_attr_e( 'Instagram Feed Pro', 'instagram-feed' ); ?>">
2836
+ </a>
2837
+
2838
+ <p class="sbi_plugins_promo dashicons-before dashicons-admin-plugins"> <?php _e('Check out our other free plugins: <a href="https://wordpress.org/plugins/custom-facebook-feed/" target="_blank">Facebook</a>, <a href="https://wordpress.org/plugins/custom-twitter-feeds/" target="_blank">Twitter</a>, and <a href="https://wordpress.org/plugins/feeds-for-youtube/" target="_blank">YouTube</a>.', 'instagram-feed' ); ?></p>
2839
+
2840
+ <div class="sbi_share_plugin">
2841
+ <h3><?php _e('Like the plugin? Help spread the word!', 'instagram-feed'); ?></h3>
2842
+
2843
+ <button id="sbi_admin_show_share_links" class="button secondary" style="margin-bottom: 1px;"><i class="fa fa-share-alt" aria-hidden="true"></i>&nbsp;&nbsp;Share the plugin</button> <div id="sbi_admin_share_links"></div>
2844
+ </div>
2845
+
2846
+ </div> <!-- end #sbi_admin -->
2847
+
2848
  <?php } //End Settings page
inc/class-sb-instagram-api-connect.php CHANGED
@@ -1,380 +1,422 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_API_Connect
4
- *
5
- * Connect to the Instagram API and return the results. It's possible
6
- * to build the url from a connected account (includes access token,
7
- * account id, account type), endpoint and parameters (hashtag, etc..)
8
- * as well as a full url such as from the pagination data from some Instagram API requests.
9
- *
10
- * Errors from either the Instagram API or from the HTTP request are detected
11
- * and can be handled.
12
- *
13
- * Primarily used in the SB_Instagram_Feed class to collect posts and data for
14
- * the header. Can also be used for comments in the Pro version
15
- *
16
- * @since 2.0/5.0
17
- */
18
-
19
- if ( ! defined( 'ABSPATH' ) ) {
20
- die( '-1' );
21
- }
22
-
23
- class SB_Instagram_API_Connect
24
- {
25
- /**
26
- * @var string
27
- */
28
- private $url;
29
-
30
- /**
31
- * @var object
32
- */
33
- private $response;
34
-
35
- /**
36
- * SB_Instagram_API_Connect constructor.
37
- *
38
- * @param mixed|array|string $connected_account_or_url either the connected account
39
- * data for this request or the complete url for the request
40
- * @param string $endpoint (optional) is optional only if the complete url is provided
41
- * otherwise is they key for the endpoint needed for the request (ex. "header")
42
- * @param array $params (optional) used with the connected account and endpoint to add
43
- * additional query parameters to the url if needed
44
- *
45
- * @since 2.0/5.0
46
- */
47
- public function __construct( $connected_account_or_url, $endpoint = '', $params = array() ) {
48
- if ( is_array( $connected_account_or_url ) && isset( $connected_account_or_url['access_token'] ) ) {
49
- $this->set_url( $connected_account_or_url, $endpoint, $params );
50
- } elseif ( strpos( $connected_account_or_url, 'https' ) !== false ) {
51
- $this->url = $connected_account_or_url;
52
- } else {
53
- $this->url = '';
54
- }
55
- }
56
-
57
- /**
58
- * Returns the response from Instagram
59
- *
60
- * @return object
61
- *
62
- * @since 2.0/5.0
63
- */
64
- public function get_data() {
65
- if (!empty($this->response['data'])) {
66
- return $this->response['data'];
67
- } else {
68
- return $this->response;
69
- }
70
- }
71
-
72
- /**
73
- * Returns the error response and the url that was trying to be connected to
74
- * or false if no error
75
- *
76
- * @return array|bool
77
- *
78
- * @since 2.0/5.0
79
- */
80
- public function get_wp_error() {
81
- if ( $this->is_wp_error() ) {
82
- return array( 'response' => $this->response, 'url' => $this->url );
83
- } else {
84
- return false;
85
- }
86
- }
87
-
88
- /**
89
- * Returns the full url for the next page of the API request
90
- *
91
- * @return string
92
- *
93
- * @since 2.0/5.0
94
- */
95
- public function get_next_page() {
96
- if ( ! empty( $this->response['pagination']['next_url'] ) ) {
97
- return $this->response['pagination']['next_url'];
98
- } elseif ( ! empty( $this->response['paging']['next'] ) ) {
99
- return $this->response['paging']['next'];
100
- } else {
101
- return '';
102
- }
103
- }
104
-
105
- /**
106
- * If url needs to be generated from the connected account, endpoint,
107
- * and params, this function is used to do so.
108
- *
109
- * @param $url
110
- */
111
- public function set_url_from_args( $url ) {
112
- $this->url = $url;
113
- }
114
-
115
- /**
116
- * @return string
117
- *
118
- * @since 2.0/5.0
119
- */
120
- public function get_url() {
121
- return $this->url;
122
- }
123
-
124
- /**
125
- * If the server is unable to connect to the url, returns true
126
- *
127
- * @return bool
128
- *
129
- * @since 2.0/5.0
130
- */
131
- public function is_wp_error() {
132
- return is_wp_error( $this->response );
133
- }
134
-
135
- /**
136
- * If the server can connect but Instagram returns an error, returns true
137
- *
138
- * @return bool
139
- *
140
- * @since 2.0/5.0
141
- */
142
- public function is_instagram_error() {
143
- return (isset( $this->response['meta']['error_type'] ) || isset( $this->response['error']['message'] ));
144
- }
145
-
146
- /**
147
- * Connect to the Instagram API and record the response
148
- *
149
- * @since 2.0/5.0
150
- */
151
- public function connect() {
152
- $args = array(
153
- 'timeout' => 60,
154
- 'sslverify' => false
155
- );
156
- $response = wp_remote_get( $this->url, $args );
157
-
158
- if ( ! is_wp_error( $response ) ) {
159
- // certain ways of representing the html for double quotes causes errors so replaced here.
160
- $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
161
- }
162
-
163
- $this->response = $response;
164
- }
165
-
166
- /**
167
- * Determines how and where to record an error from Instagram's API response
168
- *
169
- * @param array $response response from the API request
170
- * @param array $error_connected_account the connected account that is associated
171
- * with the error
172
- * @param string $request_type key used to determine the endpoint (ex. "header")
173
- *
174
- * @since 2.0/5.0
175
- */
176
- public static function handle_instagram_error( $response, $error_connected_account, $request_type ) {
177
- global $sb_instagram_posts_manager;
178
-
179
- $error_time = 300;
180
- if ( isset( $response['meta']['error_type'] ) ) {
181
- $sb_instagram_posts_manager->add_error( 'api', array( 'Error connecting', sprintf( __( 'API error %s:', 'instagram-feed'), $response['meta']['code'] ) . ' ' . $response['meta']['error_message'] ) );
182
-
183
- if ( $response['meta']['error_type'] === 'OAuthAccessTokenException' ) {
184
- $options = get_option( 'sb_instagram_settings', array() );
185
-
186
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
187
- $user_name = '';
188
- foreach ( $connected_accounts as $connected_account ) {
189
- if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
190
- $connected_accounts[ $connected_account['user_id'] ]['is_valid'] = false;
191
- $connected_accounts[ $connected_account['user_id'] ]['last_checked'] = time();
192
- if ( isset( $connected_account['username'] ) ) {
193
- $user_name = $connected_account['username'];
194
- } else {
195
- $user_name = $connected_account['user_id'];
196
- }
197
- }
198
- }
199
-
200
- $options['connected_accounts'] = $connected_accounts;
201
-
202
- update_option( 'sb_instagram_settings', $options );
203
-
204
- $error = '<p><b>' . sprintf( __( 'Error: Access Token for %s is not valid or has expired.', 'instagram-feed' ), $user_name ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b></p>';
205
-
206
- $error .= '<p>' . __( 'There\'s an issue with the Instagram Access Token that you are using. Please obtain a new Access Token on the plugin\'s Settings page.<br />', 'instagram-feed' );
207
- $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
208
- $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
209
- if ( current_user_can( $cap ) ) {
210
- $error .= __( 'If you continue to have an issue with your Access Token then please see <a href="https://smashballoon.com/my-instagram-access-token-keep-expiring/" target="_blank" rel="noopener">this FAQ</a> for more information.', 'instagram-feed' );
211
- }
212
- $error .= '</p>';
213
- $sb_instagram_posts_manager->add_frontend_error( 'at_' . $user_name, $error );
214
-
215
- $error_time = 3600;
216
- $account_id = $error_connected_account['user_id'];
217
- } else {
218
- $error = $response['meta']['error_message'];
219
-
220
- $sb_instagram_posts_manager->add_frontend_error( $response['meta']['error_type'], $error );
221
- }
222
- } elseif ( isset( $response['error']['message'] ) ) {
223
- $sb_instagram_posts_manager->add_error( 'api', array( 'Error connecting', sprintf( __( 'API error %s:', 'instagram-feed'), $response['error']['code'] ) . ' ' . $response['error']['message'] ) );
224
-
225
- if ( (int)$response['error']['code'] === 18 ) {
226
- $options = get_option( 'sb_instagram_settings', array() );
227
-
228
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
229
- $user_name = '';
230
- $hashtag_refresh_time = time() + (7*24*60*60);
231
- foreach ( $connected_accounts as $connected_account ) {
232
- if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
233
- if ( ! isset( $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'] ) ) {
234
- $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'] = time();
235
- } else {
236
- $hashtag_refresh_time = $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'];
237
- }
238
- if ( isset( $connected_account['username'] ) ) {
239
- $user_name = $connected_account['username'];
240
- } else {
241
- $user_name = $connected_account['user_id'];
242
- }
243
- }
244
- }
245
-
246
- $options['connected_accounts'] = $connected_accounts;
247
-
248
- update_option( 'sb_instagram_settings', $options );
249
-
250
- global $sb_instagram_posts_manager;
251
- $sb_instagram_posts_manager->add_error( 'error_18', array( 'Too many hashtags', $response['error']['error_user_msg'] ) );
252
-
253
- } elseif ( (int)$response['error']['code'] === 10 ) {
254
- $user_name = $error_connected_account['username'];
255
-
256
- $error = '<p><b>' . sprintf( __( 'Error: Connected account for the user %s does not have permission to use this feed type.', 'instagram-feed' ), $user_name ) .'</b>';
257
- $error .= '<p>' . __( 'Try using the big blue button on the "Configure" tab to reconnect the account and update its permissions.', 'instagram-feed' );
258
-
259
- $sb_instagram_posts_manager->add_frontend_error( 'hashtag_limit_reached', $error );
260
-
261
- } else if ( $response['error']['type'] === 'OAuthException' ) {
262
- if ( $response['error']['code'] === 24 ) {
263
- $error = '<p><b>' . __( 'Error: Cannot retrieve posts for this hashtag.', 'instagram-feed' ) .'</b>';
264
- $error .= '<p>' . $response['error']['error_user_msg'];
265
-
266
- $sb_instagram_posts_manager->add_frontend_error( 'hashtag_error', $error );
267
- } else {
268
- $options = get_option( 'sb_instagram_settings', array() );
269
-
270
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
271
- $user_name = '';
272
- foreach ( $connected_accounts as $connected_account ) {
273
- if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
274
- $connected_accounts[ $connected_account['user_id'] ]['is_valid'] = false;
275
- $connected_accounts[ $connected_account['user_id'] ]['last_checked'] = time();
276
- if ( isset( $connected_account['username'] ) ) {
277
- $user_name = $connected_account['username'];
278
- } else {
279
- $user_name = $connected_account['user_id'];
280
- }
281
- }
282
- }
283
-
284
- $options['connected_accounts'] = $connected_accounts;
285
-
286
- update_option( 'sb_instagram_settings', $options );
287
-
288
- $error = '<p><b>' . sprintf( __( 'Error: Access Token for %s is not valid or has expired.', 'instagram-feed' ), $user_name ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b>';
289
- $error .= '<p>' . __( 'There\'s an issue with the Instagram Access Token that you are using. Please obtain a new Access Token on the plugin\'s Settings page.', 'instagram-feed' );
290
-
291
- $sb_instagram_posts_manager->add_frontend_error( 'at_' . $user_name, $error );
292
-
293
- $error_time = 3600;
294
- $account_id = $error_connected_account['user_id'];
295
- }
296
-
297
- } else {
298
- $error = $response['error']['message'];
299
-
300
- $sb_instagram_posts_manager->add_frontend_error( $response['error']['type'], $error );
301
- }
302
-
303
- }
304
-
305
- if ( ! empty( $account_id ) ) {
306
- $sb_instagram_posts_manager->add_api_request_delay( $error_time, $account_id );
307
- } else {
308
- $sb_instagram_posts_manager->add_api_request_delay( $error_time );
309
- }
310
-
311
- }
312
-
313
- /**
314
- * Determines how and where to record an error connecting to a specified url
315
- *
316
- * @param $response
317
- *
318
- * @since 2.0/5.0
319
- */
320
- public static function handle_wp_remote_get_error( $response ) {
321
- global $sb_instagram_posts_manager;
322
-
323
- $message = sprintf( __( 'Error connecting to %s.', 'instagram-feed' ), $response['url'] ). ' ';
324
- if ( isset( $response['response'] ) && isset( $response['response']->errors ) ) {
325
- foreach ( $response['response']->errors as $key => $item ) {
326
- $message .= ' '.$key . ' - ' . $item[0] . ' |';
327
- }
328
- }
329
-
330
- $sb_instagram_posts_manager->add_api_request_delay( 300 );
331
-
332
- $sb_instagram_posts_manager->add_error( 'connection', array( 'Error connecting', $message ) );
333
- }
334
-
335
- /**
336
- * Sets the url for the API request based on the account information,
337
- * type of data needed, and additional parameters.
338
- *
339
- * Overwritten in the Pro version.
340
- *
341
- * @param array $connected_account connected account to be used in the request
342
- * @param string $endpoint_slug header or user
343
- * @param array $params additional params related to the request
344
- *
345
- * @since 2.0/5.0
346
- * @since 2.2/5.3 added endpoints for the basic display API
347
- */
348
- protected function set_url( $connected_account, $endpoint_slug, $params ) {
349
- $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
350
- $num = ! empty( $params['num'] ) ? (int)$params['num'] : 33;
351
-
352
- if ( $account_type === 'basic' ) {
353
- if ( $endpoint_slug === 'access_token' ) {
354
- $url = 'https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
355
- } elseif ( $endpoint_slug === 'header' ) {
356
- $url = 'https://graph.instagram.com/me?fields=id,username,media_count,account_type&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
357
- } else {
358
- $num = min( $num, 200 );
359
- $url = 'https://graph.instagram.com/' . $connected_account['user_id'] . '/media?fields=media_url,thumbnail_url,caption,id,media_type,timestamp,username,comments_count,like_count,permalink,children{media_url,id,media_type,timestamp,permalink,thumbnail_url}&limit='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
360
- }
361
- } elseif ( $account_type === 'personal' ) {
362
- if ( $endpoint_slug === 'header' ) {
363
- $url = 'https://api.instagram.com/v1/users/' . $connected_account['user_id'] . '?access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
364
- } else {
365
- $num = $num > 20 ? min( $num, 33 ) : 20; // minimum set at 20 due to IG TV bug
366
- $url = 'https://api.instagram.com/v1/users/' . $connected_account['user_id'] . '/media/recent?count='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
367
- }
368
- } else {
369
- if ( $endpoint_slug === 'header' ) {
370
- $url = 'https://graph.facebook.com/' . $connected_account['user_id'] . '?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
371
- } else {
372
- $num = min( $num, 200 );
373
- $url = 'https://graph.facebook.com/' . $connected_account['user_id'] . '/media?fields=media_url,thumbnail_url,caption,id,media_type,timestamp,username,comments_count,like_count,permalink,children{media_url,id,media_type,timestamp,permalink,thumbnail_url}&limit='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
374
- }
375
- }
376
-
377
- $this->set_url_from_args( $url );
378
- }
379
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_API_Connect
4
+ *
5
+ * Connect to the Instagram API and return the results. It's possible
6
+ * to build the url from a connected account (includes access token,
7
+ * account id, account type), endpoint and parameters (hashtag, etc..)
8
+ * as well as a full url such as from the pagination data from some Instagram API requests.
9
+ *
10
+ * Errors from either the Instagram API or from the HTTP request are detected
11
+ * and can be handled.
12
+ *
13
+ * Primarily used in the SB_Instagram_Feed class to collect posts and data for
14
+ * the header. Can also be used for comments in the Pro version
15
+ *
16
+ * @since 2.0/5.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ die( '-1' );
21
+ }
22
+
23
+ class SB_Instagram_API_Connect
24
+ {
25
+ /**
26
+ * @var string
27
+ */
28
+ private $url;
29
+
30
+ /**
31
+ * @var object
32
+ */
33
+ protected $response;
34
+
35
+ /**
36
+ * SB_Instagram_API_Connect constructor.
37
+ *
38
+ * @param mixed|array|string $connected_account_or_url either the connected account
39
+ * data for this request or the complete url for the request
40
+ * @param string $endpoint (optional) is optional only if the complete url is provided
41
+ * otherwise is they key for the endpoint needed for the request (ex. "header")
42
+ * @param array $params (optional) used with the connected account and endpoint to add
43
+ * additional query parameters to the url if needed
44
+ *
45
+ * @since 2.0/5.0
46
+ */
47
+ public function __construct( $connected_account_or_url, $endpoint = '', $params = array() ) {
48
+ if ( is_array( $connected_account_or_url ) && isset( $connected_account_or_url['access_token'] ) ) {
49
+ $this->set_url( $connected_account_or_url, $endpoint, $params );
50
+ } elseif ( strpos( $connected_account_or_url, 'https' ) !== false ) {
51
+ $this->url = $connected_account_or_url;
52
+ } else {
53
+ $this->url = '';
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Returns the response from Instagram
59
+ *
60
+ * @return object
61
+ *
62
+ * @since 2.0/5.0
63
+ */
64
+ public function get_data() {
65
+ if (!empty($this->response['data'])) {
66
+ return $this->response['data'];
67
+ } else {
68
+ return $this->response;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Returns the error response and the url that was trying to be connected to
74
+ * or false if no error
75
+ *
76
+ * @return array|bool
77
+ *
78
+ * @since 2.0/5.0
79
+ */
80
+ public function get_wp_error() {
81
+ if ( $this->is_wp_error() ) {
82
+ return array( 'response' => $this->response, 'url' => $this->url );
83
+ } else {
84
+ return false;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Certain endpoints don't include the "next" URL so
90
+ * this method allows using the "cursors->after" data instead
91
+ *
92
+ * @param $type
93
+ *
94
+ * @return bool
95
+ *
96
+ * @since 2.2.2/5.3.3
97
+ */
98
+ public function type_allows_after_paging( $type ) {
99
+ return false;
100
+ }
101
+
102
+ /**
103
+ * Returns the full url for the next page of the API request
104
+ *
105
+ * @param $type
106
+ *
107
+ * @return string
108
+ *
109
+ * @since 2.0/5.0
110
+ */
111
+ public function get_next_page( $type = '' ) {
112
+ if ( ! empty( $this->response['pagination']['next_url'] ) ) {
113
+ return $this->response['pagination']['next_url'];
114
+ } elseif ( ! empty( $this->response['paging']['next'] ) ) {
115
+ return $this->response['paging']['next'];
116
+ } else {
117
+ if ( $this->type_allows_after_paging( $type ) ) {
118
+ if ( isset( $this->response['paging']['cursors']['after'] ) ) {
119
+ return $this->response['paging']['cursors']['after'];
120
+ }
121
+ }
122
+ return '';
123
+ }
124
+ }
125
+
126
+ /**
127
+ * If url needs to be generated from the connected account, endpoint,
128
+ * and params, this function is used to do so.
129
+ *
130
+ * @param $url
131
+ */
132
+ public function set_url_from_args( $url ) {
133
+ $this->url = $url;
134
+ }
135
+
136
+ /**
137
+ * @return string
138
+ *
139
+ * @since 2.0/5.0
140
+ */
141
+ public function get_url() {
142
+ return $this->url;
143
+ }
144
+
145
+ /**
146
+ * If the server is unable to connect to the url, returns true
147
+ *
148
+ * @return bool
149
+ *
150
+ * @since 2.0/5.0
151
+ */
152
+ public function is_wp_error() {
153
+ return is_wp_error( $this->response );
154
+ }
155
+
156
+ /**
157
+ * If the server can connect but Instagram returns an error, returns true
158
+ *
159
+ * @return bool
160
+ *
161
+ * @since 2.0/5.0
162
+ */
163
+ public function is_instagram_error() {
164
+ return (isset( $this->response['meta']['error_type'] ) || isset( $this->response['error']['message'] ));
165
+ }
166
+
167
+ /**
168
+ * Connect to the Instagram API and record the response
169
+ *
170
+ * @since 2.0/5.0
171
+ */
172
+ public function connect() {
173
+ $args = array(
174
+ 'timeout' => 60,
175
+ 'sslverify' => false
176
+ );
177
+ // $response = wp_remote_get( $this->url, $args );
178
+ $response = wp_remote_get( $this->url, $args );
179
+
180
+ if ( ! is_wp_error( $response ) ) {
181
+ // certain ways of representing the html for double quotes causes errors so replaced here.
182
+ $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
183
+ }
184
+
185
+ $this->response = $response;
186
+ }
187
+
188
+ /**
189
+ * Determines how and where to record an error from Instagram's API response
190
+ *
191
+ * @param array $response response from the API request
192
+ * @param array $error_connected_account the connected account that is associated
193
+ * with the error
194
+ * @param string $request_type key used to determine the endpoint (ex. "header")
195
+ *
196
+ * @since 2.0/5.0
197
+ */
198
+ public static function handle_instagram_error( $response, $error_connected_account, $request_type ) {
199
+ global $sb_instagram_posts_manager;
200
+ delete_option( 'sbi_dismiss_critical_notice' );
201
+
202
+ $sb_instagram_posts_manager->update_error_page( get_the_ID() );
203
+
204
+ $error_time = 300;
205
+ if ( isset( $response['meta']['error_type'] ) ) {
206
+ if ( $response['meta']['error_type'] === 'OAuthAccessTokenException' ) {
207
+ $options = get_option( 'sb_instagram_settings', array() );
208
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
209
+ $user_name = '';
210
+ foreach ( $connected_accounts as $connected_account ) {
211
+ if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
212
+ $connected_accounts[ $connected_account['user_id'] ]['is_valid'] = false;
213
+ $connected_accounts[ $connected_account['user_id'] ]['last_checked'] = time();
214
+ if ( isset( $connected_account['username'] ) ) {
215
+ $user_name = $connected_account['username'];
216
+ } else {
217
+ $user_name = $connected_account['user_id'];
218
+ }
219
+ }
220
+ }
221
+
222
+ $options['connected_accounts'] = $connected_accounts;
223
+
224
+ update_option( 'sb_instagram_settings', $options );
225
+
226
+ $error = '<p><b>' . sprintf( __( 'Error: Access Token for %s is not valid or has expired.', 'instagram-feed' ), $user_name ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b></p>';
227
+ $error .= '<p>' . __( 'There\'s an issue with the Instagram Access Token that you are using. Please obtain a new Access Token on the plugin\'s Settings page.', 'instagram-feed' ) . '</p>';
228
+
229
+ $sb_instagram_posts_manager->add_frontend_error( 'at_' . $user_name, $error );
230
+
231
+ $error_time = 3600;
232
+ $account_id = $error_connected_account['user_id'];
233
+ } else {
234
+ $error = $response['meta']['error_message'];
235
+ $sb_instagram_posts_manager->add_error( 'api', array( 'Error connecting', sprintf( __( 'API error %s:', 'instagram-feed'), $response['meta']['code'] ) . ' ' . $response['meta']['error_message'], $response['meta']['code'] ) );
236
+ $sb_instagram_posts_manager->add_frontend_error( $response['meta']['error_type'], $error );
237
+ }
238
+ } elseif ( isset( $response['error']['message'] ) ) {
239
+ if ( (int)$response['error']['code'] === 18 ) {
240
+ $options = get_option( 'sb_instagram_settings', array() );
241
+
242
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
243
+ $user_name = '';
244
+ $hashtag_refresh_time = time() + (7*24*60*60);
245
+ foreach ( $connected_accounts as $connected_account ) {
246
+ if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
247
+ if ( ! isset( $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'] ) ) {
248
+ $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'] = time();
249
+ } else {
250
+ $hashtag_refresh_time = $connected_accounts[ $connected_account['user_id'] ]['hashtag_limit_reached'];
251
+ }
252
+ if ( isset( $connected_account['username'] ) ) {
253
+ $user_name = $connected_account['username'];
254
+ } else {
255
+ $user_name = $connected_account['user_id'];
256
+ }
257
+ }
258
+ }
259
+
260
+ $options['connected_accounts'] = $connected_accounts;
261
+
262
+ update_option( 'sb_instagram_settings', $options );
263
+
264
+ global $sb_instagram_posts_manager;
265
+ $sb_instagram_posts_manager->add_error( 'error_18', array( 'Too many hashtags', $response['error']['error_user_msg'] ) );
266
+
267
+ } elseif ( (int)$response['error']['code'] === 10 ) {
268
+ $user_name = $error_connected_account['username'];
269
+
270
+ $error = '<p><b>' . sprintf( __( 'Error: Connected account for the user %s does not have permission to use this feed type.', 'instagram-feed' ), $user_name ) .'</b></p>';
271
+ $error .= '<p>' . __( 'Try using the big blue button on the "Configure" tab to reconnect the account and update its permissions.', 'instagram-feed' ) . '</p>';
272
+
273
+ $sb_instagram_posts_manager->add_frontend_error( 'hashtag_limit_reached', $error );
274
+
275
+ } else if ( $response['error']['type'] === 'OAuthException'
276
+ || (int)$response['error']['code'] === 100 ) {
277
+ if ( $response['error']['code'] === 803 ) {
278
+ $error = sprintf( __( 'API error %s:', 'instagram-feed' ), $response['error']['code'] ) . ' ' . $response['error']['message'];
279
+
280
+ $sb_instagram_posts_manager->add_frontend_error( $response['error']['type'], $error );
281
+ $sb_instagram_posts_manager->add_error( 'api', array( 'Api Error', $error, $response['error']['code'] ) );
282
+ } elseif ( $response['error']['code'] === 24 ) {
283
+ $error = '<p><b>' . __( 'Error: Cannot retrieve posts for this hashtag.', 'instagram-feed' ) .'</b></p>';
284
+ $error .= '<p>' . $response['error']['error_user_msg'] . '</p>';
285
+
286
+ $sb_instagram_posts_manager->add_frontend_error( 'hashtag_error', $error );
287
+ } else {
288
+ $options = get_option( 'sb_instagram_settings', array() );
289
+
290
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
291
+ $user_name = '';
292
+ foreach ( $connected_accounts as $connected_account ) {
293
+ if ( $connected_account['access_token'] === $error_connected_account['access_token'] ) {
294
+ $connected_accounts[ $connected_account['user_id'] ]['is_valid'] = false;
295
+ $connected_accounts[ $connected_account['user_id'] ]['last_checked'] = time();
296
+ if ( isset( $connected_account['username'] ) ) {
297
+ $user_name = $connected_account['username'];
298
+ } else {
299
+ $user_name = $connected_account['user_id'];
300
+ }
301
+ }
302
+ }
303
+
304
+ $options['connected_accounts'] = $connected_accounts;
305
+
306
+ update_option( 'sb_instagram_settings', $options );
307
+ $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
308
+ $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
309
+ if ( (int)$response['error']['code'] === 100 && $error_connected_account['type'] === 'business' ) {
310
+ $error = '<p><b>' . sprintf( __( 'Error: Access Token for %s is not valid or has expired.', 'instagram-feed' ), $user_name ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b></p>';
311
+ $error .= '<p>' . sprintf( __( 'API error %s:', 'instagram-feed' ), $response['error']['code'] ) . ' ' . $response['error']['message'] . '</p>';
312
+ $sb_instagram_posts_manager->add_error( 'at_100_' . $user_name, array( 'Business 100 Error', $error, $response['error']['code'] ) );
313
+ if ( current_user_can( $cap ) ) {
314
+ $error .= '<p class="sbi-error-directions"><a href="https://smashballoon.com/instagram-feed/docs/errors/" target="_blank" rel="noopener">' . __( 'Directions on how to resolve this issue', 'instagram-feed' ) . '</a></p>';
315
+ }
316
+ $sb_instagram_posts_manager->add_frontend_error( 'at_100_' . $user_name, $error );
317
+
318
+ } else {
319
+ //set here
320
+ $error = '<p><b>' . sprintf( __( 'Error: Access Token for %s is not valid or has expired.', 'instagram-feed' ), $user_name ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b></p>';
321
+ $error .= '<p>' . __( 'There\'s an issue with the Instagram Access Token that you are using. Please obtain a new Access Token on the plugin\'s Settings page.', 'instagram-feed' );
322
+ $error .= '<p>' . sprintf( __( 'API error %s:', 'instagram-feed' ), $response['error']['code'] ) . ' ' . $response['error']['message'] . '</p>';
323
+ $sb_instagram_posts_manager->add_error( 'at_' . $user_name, array( 'Access Token Error', $error, $response['error']['code'] ) );
324
+ $link = admin_url( '?page=sb-instagram-feed' );
325
+ if ( current_user_can( $cap ) ) {
326
+ $error .= '<p class="sbi-error-directions sbi-reconnect"><a href="' . esc_url( $link ) . '" target="_blank" rel="noopener">' . __( 'Reconnect your account in the admin area', 'instagram-feed' ) . '</a></p>';
327
+ }
328
+ $sb_instagram_posts_manager->add_frontend_error( 'at_' . $user_name, $error );
329
+ }
330
+
331
+ $error_time = 3600;
332
+ $account_id = $error_connected_account['user_id'];
333
+ }
334
+
335
+ } else {
336
+ $error = '<p>' .sprintf( __( 'API error %s:', 'instagram-feed' ), $response['error']['code'] ) . ' ' . $response['error']['message'] . '</p>';
337
+
338
+ $sb_instagram_posts_manager->add_frontend_error( $response['error']['type'], $error );
339
+ $sb_instagram_posts_manager->add_error( 'api', array( 'Api Error', $error, $response['error']['code'] ) );
340
+
341
+ }
342
+
343
+ }
344
+
345
+ if ( ! empty( $account_id ) ) {
346
+ $sb_instagram_posts_manager->add_api_request_delay( $error_time, $account_id );
347
+ } else {
348
+ $sb_instagram_posts_manager->add_api_request_delay( $error_time );
349
+ }
350
+
351
+ }
352
+
353
+ /**
354
+ * Determines how and where to record an error connecting to a specified url
355
+ *
356
+ * @param $response
357
+ *
358
+ * @since 2.0/5.0
359
+ */
360
+ public static function handle_wp_remote_get_error( $response ) {
361
+ global $sb_instagram_posts_manager;
362
+ delete_option( 'sbi_dismiss_critical_notice' );
363
+ $sb_instagram_posts_manager->update_error_page( get_the_ID() );
364
+
365
+ $message = sprintf( __( 'Error connecting to %s.', 'instagram-feed' ), $response['url'] ). ' ';
366
+ if ( isset( $response['response'] ) && isset( $response['response']->errors ) ) {
367
+ foreach ( $response['response']->errors as $key => $item ) {
368
+ $message .= ' '.$key . ' - ' . $item[0] . ' |';
369
+ }
370
+ }
371
+
372
+ $sb_instagram_posts_manager->add_api_request_delay( 300 );
373
+
374
+ $sb_instagram_posts_manager->add_error( 'connection', array( 'Error connecting', $message ) );
375
+ }
376
+
377
+ /**
378
+ * Sets the url for the API request based on the account information,
379
+ * type of data needed, and additional parameters.
380
+ *
381
+ * Overwritten in the Pro version.
382
+ *
383
+ * @param array $connected_account connected account to be used in the request
384
+ * @param string $endpoint_slug header or user
385
+ * @param array $params additional params related to the request
386
+ *
387
+ * @since 2.0/5.0
388
+ * @since 2.2/5.3 added endpoints for the basic display API
389
+ */
390
+ protected function set_url( $connected_account, $endpoint_slug, $params ) {
391
+ $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
392
+ $num = ! empty( $params['num'] ) ? (int)$params['num'] : 33;
393
+
394
+ if ( $account_type === 'basic' ) {
395
+ if ( $endpoint_slug === 'access_token' ) {
396
+ $url = 'https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
397
+ } elseif ( $endpoint_slug === 'header' ) {
398
+ $url = 'https://graph.instagram.com/me?fields=id,username,media_count&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
399
+ } else {
400
+ $num = min( $num, 200 );
401
+ $url = 'https://graph.instagram.com/' . sbi_maybe_clean( $connected_account['user_id'] ) . '/media?fields=media_url,thumbnail_url,caption,id,media_type,timestamp,username,comments_count,like_count,permalink,children{media_url,id,media_type,timestamp,permalink,thumbnail_url}&limit='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
402
+ }
403
+ } elseif ( $account_type === 'personal' ) {
404
+ if ( $endpoint_slug === 'header' ) {
405
+ $url = 'https://api.instagram.com/v1/users/' . $connected_account['user_id'] . '?access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
406
+ } else {
407
+ $num = $num > 20 ? min( $num, 33 ) : 20; // minimum set at 20 due to IG TV bug
408
+ $url = 'https://api.instagram.com/v1/users/' . $connected_account['user_id'] . '/media/recent?count='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
409
+ }
410
+ } else {
411
+ if ( $endpoint_slug === 'header' ) {
412
+ $url = 'https://graph.facebook.com/' . $connected_account['user_id'] . '?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
413
+ } else {
414
+ $num = min( $num, 200 );
415
+ $url = 'https://graph.facebook.com/' . $connected_account['user_id'] . '/media?fields=media_url,thumbnail_url,caption,id,media_type,timestamp,username,comments_count,like_count,permalink,children{media_url,id,media_type,timestamp,permalink,thumbnail_url}&limit='.$num.'&access_token=' . sbi_maybe_clean( $connected_account['access_token'] );
416
+ }
417
+ }
418
+
419
+ $this->set_url_from_args( $url );
420
+ }
421
+
422
  }
inc/class-sb-instagram-cron-updater.php CHANGED
@@ -1,226 +1,226 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_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
- * "sbi_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 2.0/5.0
12
- */
13
-
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- die( '-1' );
16
- }
17
-
18
- class SB_Instagram_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 2.0/5.0
27
- */
28
- public static function do_feed_updates() {
29
- $feed_caches = SB_Instagram_Cron_Updater::get_feed_cache_option_names();
30
- shuffle( $feed_caches );
31
- $settings = sbi_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'] : false;
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
- $instagram_feed_settings = new SB_Instagram_Settings( $atts, $settings );
62
-
63
- if ( empty( $settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
64
- $report[ $feed_id ]['did_update'] = 'no - no connected account';
65
- } else {
66
- SB_Instagram_Cron_Updater::do_single_feed_cron_update( $instagram_feed_settings, $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( 'sbi_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 array $instagram_feed_settings associative array generated from
96
- * the sb_instagram_settings class
97
- * @param array $feed_data post, header, shortcode settings, and other info
98
- * associated with the feed that is saved in the cache
99
- * @param array $atts shortcode settings
100
- * @param bool $include_resize whether or not to resize images during the update since
101
- * images can also be resized with an ajax call when the feed is viewed on the frontend
102
- *
103
- * @return object
104
- *
105
- * @since 2.0/5.0
106
- */
107
- public static function do_single_feed_cron_update( $instagram_feed_settings, $feed_data, $atts, $include_resize = true ) {
108
- $instagram_feed_settings->set_feed_type_and_terms();
109
- $instagram_feed_settings->set_transient_name();
110
- $transient_name = $instagram_feed_settings->get_transient_name();
111
- $settings = $instagram_feed_settings->get_settings();
112
- $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
113
-
114
- $instagram_feed = new SB_Instagram_Feed( $transient_name );
115
-
116
- while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
117
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
118
- }
119
-
120
- $to_cache = array(
121
- 'atts' => $atts,
122
- 'last_requested' => $feed_data['last_requested'],
123
- 'last_retrieve' => time()
124
- );
125
-
126
- $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
127
-
128
- if ( $instagram_feed->need_header( $settings, $feed_type_and_terms ) ) {
129
- $instagram_feed->set_remote_header_data( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
130
-
131
- $instagram_feed->cache_header_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
132
- }
133
-
134
- if ( $include_resize ) {
135
- $post_data = $instagram_feed->get_post_data();
136
- $post_data = array_slice( $post_data, 0, $settings['num'] );
137
-
138
- if ( $settings['favor_local'] ) {
139
- $image_sizes = array(
140
- 'personal' => array( 'full' => 640, 'low' => 320 ),
141
- 'business' => array( 'full' => 640, 'low' => 320 )
142
- );
143
- } else {
144
- $image_sizes = array(
145
- 'personal' => array( 'low' => 320 ),
146
- 'business' => array( 'full' => 640, 'low' => 320 )
147
- );
148
- }
149
- $post_set = new SB_Instagram_Post_Set( $post_data, $transient_name, NULL, $image_sizes );
150
-
151
- $post_set->maybe_save_update_and_resize_images_for_posts();
152
- }
153
-
154
- return $instagram_feed;
155
- }
156
-
157
- /**
158
- * Retrieve option name column values for all feed cache transients
159
- *
160
- * @return array
161
- *
162
- * @since 2.0/5.0
163
- */
164
- public static function get_feed_cache_option_names() {
165
- global $wpdb;
166
- $feed_caches = array();
167
-
168
- $results = $wpdb->get_results( "
169
- SELECT option_name
170
- FROM $wpdb->options
171
- WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
172
- AND `option_name` NOT LIKE ('%\_transient\_sbi\_header%');", ARRAY_A );
173
-
174
- if ( isset( $results[0] ) ) {
175
- $feed_caches = $results;
176
- }
177
-
178
- return $feed_caches;
179
- }
180
-
181
- /**
182
- * Start cron jobs based on user's settings for cron cache update frequency.
183
- * This is triggered when settings are saved on the "Configure" tab.
184
- *
185
- * @param string $sbi_cache_cron_interval arbitrary name from one of the
186
- * settings on the "Configure" tab
187
- * @param string $sbi_cache_cron_time hour of the day (1 = 1:00)
188
- * @param string $sbi_cache_cron_am_pm am or pm (time of day)
189
- *
190
- * @since 2.0/5.0
191
- */
192
- public static function start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm ) {
193
- wp_clear_scheduled_hook( 'sbi_feed_update' );
194
-
195
- if ( $sbi_cache_cron_interval === '12hours' || $sbi_cache_cron_interval === '24hours' ) {
196
- $relative_time_now = time() + sbi_get_utc_offset();
197
- $base_day = strtotime( date( 'Y-m-d', $relative_time_now ) );
198
- $add_time = $sbi_cache_cron_am_pm === 'pm' ? (int)$sbi_cache_cron_time + 12 : (int)$sbi_cache_cron_time;
199
- $utc_start_time = $base_day + (($add_time * 60 * 60) - sbi_get_utc_offset());
200
-
201
- if ( $utc_start_time < time() ) {
202
- if ( $sbi_cache_cron_interval === '12hours' ) {
203
- $utc_start_time += 60*60*12;
204
- } else {
205
- $utc_start_time += 60*60*24;
206
- }
207
- }
208
-
209
- if ( $sbi_cache_cron_interval === '12hours' ) {
210
- wp_schedule_event( $utc_start_time, 'twicedaily', 'sbi_feed_update' );
211
- } else {
212
- wp_schedule_event( $utc_start_time, 'daily', 'sbi_feed_update' );
213
- }
214
-
215
- } else {
216
-
217
- if ( $sbi_cache_cron_interval === '30mins' ) {
218
- wp_schedule_event( time(), 'sbi30mins', 'sbi_feed_update' );
219
- } else {
220
- wp_schedule_event( time(), 'hourly', 'sbi_feed_update' );
221
- }
222
- }
223
-
224
- }
225
-
226
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_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
+ * "sbi_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 2.0/5.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ die( '-1' );
16
+ }
17
+
18
+ class SB_Instagram_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 2.0/5.0
27
+ */
28
+ public static function do_feed_updates() {
29
+ $feed_caches = SB_Instagram_Cron_Updater::get_feed_cache_option_names();
30
+ shuffle( $feed_caches );
31
+ $settings = sbi_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'] : false;
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
+ $instagram_feed_settings = new SB_Instagram_Settings( $atts, $settings );
62
+
63
+ if ( empty( $settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
64
+ $report[ $feed_id ]['did_update'] = 'no - no connected account';
65
+ } else {
66
+ SB_Instagram_Cron_Updater::do_single_feed_cron_update( $instagram_feed_settings, $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( 'sbi_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 array $instagram_feed_settings associative array generated from
96
+ * the sb_instagram_settings class
97
+ * @param array $feed_data post, header, shortcode settings, and other info
98
+ * associated with the feed that is saved in the cache
99
+ * @param array $atts shortcode settings
100
+ * @param bool $include_resize whether or not to resize images during the update since
101
+ * images can also be resized with an ajax call when the feed is viewed on the frontend
102
+ *
103
+ * @return object
104
+ *
105
+ * @since 2.0/5.0
106
+ */
107
+ public static function do_single_feed_cron_update( $instagram_feed_settings, $feed_data, $atts, $include_resize = true ) {
108
+ $instagram_feed_settings->set_feed_type_and_terms();
109
+ $instagram_feed_settings->set_transient_name();
110
+ $transient_name = $instagram_feed_settings->get_transient_name();
111
+ $settings = $instagram_feed_settings->get_settings();
112
+ $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
113
+
114
+ $instagram_feed = new SB_Instagram_Feed( $transient_name );
115
+
116
+ while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
117
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
118
+ }
119
+
120
+ $to_cache = array(
121
+ 'atts' => $atts,
122
+ 'last_requested' => $feed_data['last_requested'],
123
+ 'last_retrieve' => time()
124
+ );
125
+
126
+ $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
127
+
128
+ if ( $instagram_feed->need_header( $settings, $feed_type_and_terms ) ) {
129
+ $instagram_feed->set_remote_header_data( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
130
+
131
+ $instagram_feed->cache_header_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
132
+ }
133
+
134
+ if ( $include_resize ) {
135
+ $post_data = $instagram_feed->get_post_data();
136
+ $post_data = array_slice( $post_data, 0, $settings['num'] );
137
+
138
+ if ( $settings['favor_local'] ) {
139
+ $image_sizes = array(
140
+ 'personal' => array( 'full' => 640, 'low' => 320 ),
141
+ 'business' => array( 'full' => 640, 'low' => 320 )
142
+ );
143
+ } else {
144
+ $image_sizes = array(
145
+ 'personal' => array( 'low' => 320 ),
146
+ 'business' => array( 'full' => 640, 'low' => 320 )
147
+ );
148
+ }
149
+ $post_set = new SB_Instagram_Post_Set( $post_data, $transient_name, NULL, $image_sizes );
150
+
151
+ $post_set->maybe_save_update_and_resize_images_for_posts();
152
+ }
153
+
154
+ return $instagram_feed;
155
+ }
156
+
157
+ /**
158
+ * Retrieve option name column values for all feed cache transients
159
+ *
160
+ * @return array
161
+ *
162
+ * @since 2.0/5.0
163
+ */
164
+ public static function get_feed_cache_option_names() {
165
+ global $wpdb;
166
+ $feed_caches = array();
167
+
168
+ $results = $wpdb->get_results( "
169
+ SELECT option_name
170
+ FROM $wpdb->options
171
+ WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
172
+ AND `option_name` NOT LIKE ('%\_transient\_sbi\_header%');", ARRAY_A );
173
+
174
+ if ( isset( $results[0] ) ) {
175
+ $feed_caches = $results;
176
+ }
177
+
178
+ return $feed_caches;
179
+ }
180
+
181
+ /**
182
+ * Start cron jobs based on user's settings for cron cache update frequency.
183
+ * This is triggered when settings are saved on the "Configure" tab.
184
+ *
185
+ * @param string $sbi_cache_cron_interval arbitrary name from one of the
186
+ * settings on the "Configure" tab
187
+ * @param string $sbi_cache_cron_time hour of the day (1 = 1:00)
188
+ * @param string $sbi_cache_cron_am_pm am or pm (time of day)
189
+ *
190
+ * @since 2.0/5.0
191
+ */
192
+ public static function start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm ) {
193
+ wp_clear_scheduled_hook( 'sbi_feed_update' );
194
+
195
+ if ( $sbi_cache_cron_interval === '12hours' || $sbi_cache_cron_interval === '24hours' ) {
196
+ $relative_time_now = time() + sbi_get_utc_offset();
197
+ $base_day = strtotime( date( 'Y-m-d', $relative_time_now ) );
198
+ $add_time = $sbi_cache_cron_am_pm === 'pm' ? (int)$sbi_cache_cron_time + 12 : (int)$sbi_cache_cron_time;
199
+ $utc_start_time = $base_day + (($add_time * 60 * 60) - sbi_get_utc_offset());
200
+
201
+ if ( $utc_start_time < time() ) {
202
+ if ( $sbi_cache_cron_interval === '12hours' ) {
203
+ $utc_start_time += 60*60*12;
204
+ } else {
205
+ $utc_start_time += 60*60*24;
206
+ }
207
+ }
208
+
209
+ if ( $sbi_cache_cron_interval === '12hours' ) {
210
+ wp_schedule_event( $utc_start_time, 'twicedaily', 'sbi_feed_update' );
211
+ } else {
212
+ wp_schedule_event( $utc_start_time, 'daily', 'sbi_feed_update' );
213
+ }
214
+
215
+ } else {
216
+
217
+ if ( $sbi_cache_cron_interval === '30mins' ) {
218
+ wp_schedule_event( time(), 'sbi30mins', 'sbi_feed_update' );
219
+ } else {
220
+ wp_schedule_event( time(), 'hourly', 'sbi_feed_update' );
221
+ }
222
+ }
223
+
224
+ }
225
+
226
  }
inc/class-sb-instagram-display-elements.php CHANGED
@@ -1,361 +1,361 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Display_Elements
4
- *
5
- * Used to make certain parts of the html in the feed templates
6
- * abstract.
7
- *
8
- * @since 2.0/5.0
9
- */
10
-
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- die( '-1' );
13
- }
14
-
15
- class SB_Instagram_Display_Elements
16
- {
17
- /**
18
- * Images are hidden initially with the new/transition classes
19
- * except if the js image loading is disabled using the plugin
20
- * settings
21
- *
22
- * @param $settings
23
- *
24
- * @return string
25
- *
26
- * @since 2.0/5.0
27
- */
28
- public static function get_item_classes( $settings ) {
29
- if ( !$settings['disable_js_image_loading'] ) {
30
- return ' sbi_new sbi_transition';
31
- } else {
32
- return ' sbi_new sbi_no_js sbi_no_resraise sbi_js_load_disabled';
33
- }
34
- }
35
-
36
- /**
37
- * Overwritten in the Pro version.
38
- *
39
- * @param string $type key of the kind of icon needed
40
- * @param string $icon_type svg or font
41
- *
42
- * @return string the complete html for the icon
43
- *
44
- * @since 2.0/5.0
45
- */
46
- public static function get_icon( $type, $icon_type ) {
47
- return self::get_basic_icons( $type, $icon_type );
48
- }
49
-
50
- /**
51
- * Returns the best media url for an image based on settings.
52
- * By default a white placeholder image is loaded and replaced
53
- * with the most optimal image size based on the actual dimensions
54
- * of the image element in the feed.
55
- *
56
- * @param array $post data for an individual post
57
- * @param array $settings
58
- * @param array $resized_images (optional) not yet used but
59
- * can pass in existing resized images to use in the source
60
- *
61
- * @return string
62
- *
63
- * @since 2.0/5.0
64
- */
65
- public static function get_optimum_media_url( $post, $settings, $resized_images = array() ) {
66
- $media_url = '';
67
- $optimum_res = $settings['imageres'];
68
- $account_type = isset( $post['images'] ) ? 'personal' : 'business';
69
-
70
- // only use the placeholder if it will be replaced using JS
71
- if ( !$settings['disable_js_image_loading'] ) {
72
- return trailingslashit( SBI_PLUGIN_URL ) . 'img/placeholder.png';
73
- } elseif ( $settings['imageres'] === 'auto' ) {
74
- $optimum_res = 'full';
75
- $settings['imageres'] = 'full';
76
- } else {
77
- if ( $settings['imageres'] !== 'thumb' && ! empty( $resized_images ) ) {
78
- $resolution = $settings['imageres'];
79
- $post_id = SB_Instagram_Parse::get_post_id( $post );
80
- if ( isset( $resized_images[ $post_id ] )
81
- && $resized_images[ $post_id ]['id'] !== 'error'
82
- && $resized_images[ $post_id ]['id'] !== 'pending'
83
- && $resized_images[ $post_id ]['id'] !== 'video' ) {
84
- if ( $resolution === 'medium' ) {
85
- if ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
86
- $suffix = 'low';
87
- } elseif ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
88
- $suffix = 'full';
89
- }
90
- } elseif ( $resolution === 'full' ) {
91
- if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
92
- $suffix = 'full';
93
- } elseif ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
94
- $suffix = 'low';
95
- }
96
- } elseif ( $resolution === 'lightbox' ) {
97
- if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
98
- $suffix = 'full';
99
- }
100
- }
101
- if ( isset( $suffix ) ) {
102
- $media_url = sbi_get_resized_uploads_url() . $resized_images[ $post_id ]['id'] . $suffix . '.jpg';
103
- return $media_url;
104
- }
105
- }
106
- }
107
- }
108
-
109
- if ( $account_type === 'personal' ) {
110
- switch ( $optimum_res ) {
111
- case 'thumb' :
112
- $media_url = $post['images']['thumbnail']['url'];
113
- break;
114
- case 'medium' :
115
- $media_url = $post['images']['low_resolution']['url'];
116
- break;
117
- default :
118
- $media_url = $post['images']['standard_resolution']['url'];
119
- }
120
- } else {
121
- $post_id = SB_Instagram_Parse::get_post_id( $post );
122
-
123
- // use resized images if exists
124
- if ( $optimum_res === 'full' && isset( $resized_images[ $post_id ]['id'] )
125
- && $resized_images[ $post_id ]['id'] !== 'pending'
126
- && $resized_images[ $post_id ]['id'] !== 'video'
127
- && $resized_images[ $post_id ]['id'] !== 'error' ) {
128
- $media_url = sbi_get_resized_uploads_url() . $resized_images[ $post_id ]['id'] . 'full.jpg';
129
- } else {
130
- $permalink = SB_Instagram_Parse::get_permalink( $post );
131
- if ( substr_count( $permalink, '/' ) > 5 ) {
132
- $permalink_array = explode( '/', $permalink );
133
- $perm_id = $permalink_array[ count( $permalink_array ) - 2 ];
134
- $permalink = 'https://www.instagram.com/p/' . $perm_id . '/';
135
- }
136
-
137
- if ( ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') && ($optimum_res === 'lightbox' || $optimum_res === 'full')) {
138
- $media_url = $permalink . 'media?size=l';
139
- } else {
140
- switch ($optimum_res) {
141
- case 'thumb' :
142
- $media_url = $permalink . 'media?size=t';
143
- break;
144
- case 'medium' :
145
- $media_url = $permalink . 'media?size=m';
146
- break;
147
- default :
148
- $media_url = $post['media_url'];
149
- }
150
- }
151
- }
152
-
153
- }
154
-
155
- return $media_url;
156
- }
157
-
158
- /**
159
- * Images are normally styles with the imgLiquid plugin
160
- * with JavaScript. If this is disabled, the plugin will
161
- * attempt to square all images using CSS.
162
- *
163
- * @param array $post
164
- * @param array $settings
165
- * @param array $resized_images
166
- *
167
- * @return string
168
- *
169
- * @since 2.0/5.0
170
- * @since 2.1.1/5.2.1 added support for resized images
171
- */
172
- public static function get_sbi_photo_style_element( $post, $settings, $resized_images = array() ) {
173
- if ( !$settings['disable_js_image_loading'] ) {
174
- return '';
175
- } else {
176
- $full_res_image = SB_Instagram_Display_Elements::get_optimum_media_url( $post, $settings, $resized_images );
177
- /*
178
- * By setting the height to "0" the bottom padding can be used
179
- * as a percent to square the images. Since it needs to be a percent
180
- * this guesses what the percent would be based on static padding.
181
- */
182
- $padding_bottom = '100%';
183
- if ( $settings['imagepaddingunit'] === '%' ) {
184
- $padding_bottom = 100 - ($settings['imagepadding'] * 2) . '%';
185
- } else {
186
- $padding_percent = $settings['imagepadding'] > 0 ? 100 - ($settings['cols'] / 2 * $settings['imagepadding'] / 5) : 100;
187
- $padding_bottom = $padding_percent . '%';
188
- }
189
- return ' style="background-image: url(&quot;' . esc_url( $full_res_image ) . '&quot;); background-size: cover; background-position: center center; background-repeat: no-repeat; opacity: 1;height: 0;padding-bottom: ' . esc_attr( $padding_bottom ) . ';"';
190
- }
191
- }
192
-
193
- /**
194
- * Creates a style attribute that contains all of the styles for
195
- * the main feed div.
196
- *
197
- * @param $settings
198
- *
199
- * @return string
200
- */
201
- public static function get_feed_style( $settings ) {
202
-
203
- $styles = '';
204
- if ( ! empty( $settings['imagepadding'] )
205
- || ! empty( $settings['background'] )
206
- || ! empty( $settings['width'] )
207
- || ! empty( $settings['height'] ) ) {
208
- $styles = ' style="';
209
- if ( ! empty( $settings['imagepadding'] ) ) {
210
- $styles .= 'padding-bottom: ' . ((int)$settings['imagepadding'] * 2) . esc_attr( $settings['imagepaddingunit'] ) . ';';
211
- }
212
- if ( ! empty( $settings['background'] ) ) {
213
- $styles .= 'background-color: rgb(' . esc_attr( sbi_hextorgb( $settings['background'] ) ). ');';
214
- }
215
- if ( ! empty( $settings['width'] ) ) {
216
- $styles .= 'width: ' . (int)$settings['width'] . esc_attr( $settings['widthunit'] ) . ';';
217
- }
218
- if ( ! empty( $settings['height'] ) ) {
219
- $styles .= 'height: ' . (int)$settings['height'] . esc_attr( $settings['heightunit'] ) . ';';
220
- }
221
- $styles .= '"';
222
- }
223
- return $styles;
224
- }
225
-
226
- /**
227
- * Creates a style attribute for the sbi_images div
228
- *
229
- * @param $settings
230
- *
231
- * @return string
232
- */
233
- public static function get_sbi_images_style( $settings ) {
234
- if ( ! empty ( $settings['imagepadding'] ) ) {
235
- return 'style="padding: '.(int)$settings['imagepadding'] . esc_attr( $settings['imagepaddingunit'] ) . ';"';
236
- }
237
- return '';
238
- }
239
-
240
- /**
241
- * Creates a style attribute for the header. Can be used in
242
- * several places based on the header style
243
- *
244
- * @param $settings
245
- *
246
- * @return string
247
- */
248
- public static function get_header_text_color_styles( $settings ) {
249
- if ( ! empty( $settings['headercolor'] ) ) {
250
- return 'style="color: rgb(' . esc_attr( sbi_hextorgb( $settings['headercolor'] ) ). ');"';
251
- }
252
- return '';
253
- }
254
-
255
- /**
256
- * Header icon and text size is styled using the class added here.
257
- *
258
- * @param $settings
259
- *
260
- * @return string
261
- *
262
- * @since 2.0.1/5.0
263
- */
264
- public static function get_header_size_class( $settings ) {
265
- $header_size_class = in_array( strtolower( $settings['headersize'] ), array( 'medium', 'large' ) ) ? ' sbi_'.strtolower( $settings['headersize'] ) : '';
266
- return $header_size_class;
267
- }
268
-
269
- /**
270
- * Creates a style attribute for the follow button. Can be in
271
- * the feed footer or in a boxed header.
272
- *
273
- * @param $settings
274
- *
275
- * @return string
276
- */
277
- public static function get_follow_styles( $settings ) {
278
- $styles = '';
279
- if ( ! empty( $settings['followcolor'] ) || ! empty( $settings['followtextcolor'] ) ) {
280
- $styles = 'style="';
281
- if ( ! empty( $settings['followcolor'] ) ) {
282
- $styles .= 'background: rgb(' . esc_attr( sbi_hextorgb( $settings['followcolor'] ) ) . ');';
283
- }
284
- if ( ! empty( $settings['followtextcolor'] ) ) {
285
- $styles .= 'color: rgb(' . esc_attr( sbi_hextorgb( $settings['followtextcolor'] ) ). ');';
286
- }
287
- $styles .= '"';
288
- }
289
- return $styles;
290
- }
291
-
292
- /**
293
- * Creates a style attribute for styling the load more button.
294
- *
295
- * @param $settings
296
- *
297
- * @return string
298
- */
299
- public static function get_load_button_styles( $settings ) {
300
- $styles = '';
301
- if ( ! empty( $settings['buttoncolor'] ) || ! empty( $settings['buttontextcolor'] ) ) {
302
- $styles = 'style="';
303
- if ( ! empty( $settings['buttoncolor'] ) ) {
304
- $styles .= 'background: rgb(' . esc_attr( sbi_hextorgb( $settings['buttoncolor'] ) ) . ');';
305
- }
306
- if ( ! empty( $settings['buttontextcolor'] ) ) {
307
- $styles .= 'color: rgb(' . esc_attr( sbi_hextorgb( $settings['buttontextcolor'] ) ). ');';
308
- }
309
- $styles .= '"';
310
- }
311
- return $styles;
312
- }
313
-
314
- /**
315
- * Returns the html for an icon based on the kind requested
316
- *
317
- * @param string $type kind of icon needed (ex "video" is a play button
318
- * @param string $icon_type svg or font
319
- *
320
- * @return string
321
- *
322
- * @since 2.0/5.0
323
- */
324
- protected static function get_basic_icons( $type, $icon_type ) {
325
- if ( $type === 'carousel' ) {
326
- if ( $icon_type === 'svg' ) {
327
- return '<svg class="svg-inline--fa fa-clone fa-w-16 sbi_lightbox_carousel_icon" aria-hidden="true" aria-label="Clone" data-fa-proƒcessed="" data-prefix="far" data-icon="clone" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
328
- <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>
329
- </svg>';
330
- } else {
331
- return '<i class="fa fa-clone sbi_carousel_icon" aria-hidden="true"></i>';
332
- }
333
-
334
- } elseif ( $type === 'video' ) {
335
- if ( $icon_type === 'svg' ) {
336
- return '<svg style="color: rgba(255,255,255,1)" class="svg-inline--fa fa-play fa-w-14 sbi_playbtn" aria-label="Play" 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>';
337
- } else {
338
- return '<i class="fa fa-play sbi_playbtn" aria-hidden="true"></i>';
339
- }
340
- } elseif ( $type === 'instagram' ) {
341
- if ( $icon_type === 'svg' ) {
342
- return '<svg class="svg-inline--fa fa-instagram fa-w-14" aria-hidden="true" data-fa-processed="" aria-label="Instagram" data-prefix="fab" data-icon="instagram" role="img" viewBox="0 0 448 512">
343
- <path fill="currentColor" d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path>
344
- </svg>';
345
- } else {
346
- return '<i class="fa fab fa-instagram" aria-hidden="true"></i>';
347
- }
348
- } elseif ( $type === 'newlogo' ) {
349
- if ( $icon_type === 'svg' ) {
350
- return '<svg class="sbi_new_logo fa-instagram fa-w-14" aria-hidden="true" data-fa-processed="" aria-label="Instagram" data-prefix="fab" data-icon="instagram" role="img" viewBox="0 0 448 512">
351
- <path fill="currentColor" d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path>
352
- </svg>';
353
- } else {
354
- return '<i class="sbi_new_logo"></i>';
355
- }
356
- } else {
357
- return '';
358
- }
359
- }
360
-
361
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Display_Elements
4
+ *
5
+ * Used to make certain parts of the html in the feed templates
6
+ * abstract.
7
+ *
8
+ * @since 2.0/5.0
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ die( '-1' );
13
+ }
14
+
15
+ class SB_Instagram_Display_Elements
16
+ {
17
+ /**
18
+ * Images are hidden initially with the new/transition classes
19
+ * except if the js image loading is disabled using the plugin
20
+ * settings
21
+ *
22
+ * @param $settings
23
+ *
24
+ * @return string
25
+ *
26
+ * @since 2.0/5.0
27
+ */
28
+ public static function get_item_classes( $settings ) {
29
+ if ( !$settings['disable_js_image_loading'] ) {
30
+ return ' sbi_new sbi_transition';
31
+ } else {
32
+ return ' sbi_new sbi_no_js sbi_no_resraise sbi_js_load_disabled';
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Overwritten in the Pro version.
38
+ *
39
+ * @param string $type key of the kind of icon needed
40
+ * @param string $icon_type svg or font
41
+ *
42
+ * @return string the complete html for the icon
43
+ *
44
+ * @since 2.0/5.0
45
+ */
46
+ public static function get_icon( $type, $icon_type ) {
47
+ return self::get_basic_icons( $type, $icon_type );
48
+ }
49
+
50
+ /**
51
+ * Returns the best media url for an image based on settings.
52
+ * By default a white placeholder image is loaded and replaced
53
+ * with the most optimal image size based on the actual dimensions
54
+ * of the image element in the feed.
55
+ *
56
+ * @param array $post data for an individual post
57
+ * @param array $settings
58
+ * @param array $resized_images (optional) not yet used but
59
+ * can pass in existing resized images to use in the source
60
+ *
61
+ * @return string
62
+ *
63
+ * @since 2.0/5.0
64
+ */
65
+ public static function get_optimum_media_url( $post, $settings, $resized_images = array() ) {
66
+ $media_url = '';
67
+ $optimum_res = $settings['imageres'];
68
+ $account_type = isset( $post['images'] ) ? 'personal' : 'business';
69
+
70
+ // only use the placeholder if it will be replaced using JS
71
+ if ( !$settings['disable_js_image_loading'] ) {
72
+ return trailingslashit( SBI_PLUGIN_URL ) . 'img/placeholder.png';
73
+ } elseif ( $settings['imageres'] === 'auto' ) {
74
+ $optimum_res = 'full';
75
+ $settings['imageres'] = 'full';
76
+ } else {
77
+ if ( $settings['imageres'] !== 'thumb' && ! empty( $resized_images ) ) {
78
+ $resolution = $settings['imageres'];
79
+ $post_id = SB_Instagram_Parse::get_post_id( $post );
80
+ if ( isset( $resized_images[ $post_id ] )
81
+ && $resized_images[ $post_id ]['id'] !== 'error'
82
+ && $resized_images[ $post_id ]['id'] !== 'pending'
83
+ && $resized_images[ $post_id ]['id'] !== 'video' ) {
84
+ if ( $resolution === 'medium' ) {
85
+ if ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
86
+ $suffix = 'low';
87
+ } elseif ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
88
+ $suffix = 'full';
89
+ }
90
+ } elseif ( $resolution === 'full' ) {
91
+ if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
92
+ $suffix = 'full';
93
+ } elseif ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
94
+ $suffix = 'low';
95
+ }
96
+ } elseif ( $resolution === 'lightbox' ) {
97
+ if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
98
+ $suffix = 'full';
99
+ }
100
+ }
101
+ if ( isset( $suffix ) ) {
102
+ $media_url = sbi_get_resized_uploads_url() . $resized_images[ $post_id ]['id'] . $suffix . '.jpg';
103
+ return $media_url;
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ if ( $account_type === 'personal' ) {
110
+ switch ( $optimum_res ) {
111
+ case 'thumb' :
112
+ $media_url = $post['images']['thumbnail']['url'];
113
+ break;
114
+ case 'medium' :
115
+ $media_url = $post['images']['low_resolution']['url'];
116
+ break;
117
+ default :
118
+ $media_url = $post['images']['standard_resolution']['url'];
119
+ }
120
+ } else {
121
+ $post_id = SB_Instagram_Parse::get_post_id( $post );
122
+
123
+ // use resized images if exists
124
+ if ( $optimum_res === 'full' && isset( $resized_images[ $post_id ]['id'] )
125
+ && $resized_images[ $post_id ]['id'] !== 'pending'
126
+ && $resized_images[ $post_id ]['id'] !== 'video'
127
+ && $resized_images[ $post_id ]['id'] !== 'error' ) {
128
+ $media_url = sbi_get_resized_uploads_url() . $resized_images[ $post_id ]['id'] . 'full.jpg';
129
+ } else {
130
+ $permalink = SB_Instagram_Parse::get_permalink( $post );
131
+ if ( substr_count( $permalink, '/' ) > 5 ) {
132
+ $permalink_array = explode( '/', $permalink );
133
+ $perm_id = $permalink_array[ count( $permalink_array ) - 2 ];
134
+ $permalink = 'https://www.instagram.com/p/' . $perm_id . '/';
135
+ }
136
+
137
+ if ( ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') && ($optimum_res === 'lightbox' || $optimum_res === 'full')) {
138
+ $media_url = $permalink . 'media?size=l';
139
+ } else {
140
+ switch ($optimum_res) {
141
+ case 'thumb' :
142
+ $media_url = $permalink . 'media?size=t';
143
+ break;
144
+ case 'medium' :
145
+ $media_url = $permalink . 'media?size=m';
146
+ break;
147
+ default :
148
+ $media_url = $post['media_url'];
149
+ }
150
+ }
151
+ }
152
+
153
+ }
154
+
155
+ return $media_url;
156
+ }
157
+
158
+ /**
159
+ * Images are normally styles with the imgLiquid plugin
160
+ * with JavaScript. If this is disabled, the plugin will
161
+ * attempt to square all images using CSS.
162
+ *
163
+ * @param array $post
164
+ * @param array $settings
165
+ * @param array $resized_images
166
+ *
167
+ * @return string
168
+ *
169
+ * @since 2.0/5.0
170
+ * @since 2.1.1/5.2.1 added support for resized images
171
+ */
172
+ public static function get_sbi_photo_style_element( $post, $settings, $resized_images = array() ) {
173
+ if ( !$settings['disable_js_image_loading'] ) {
174
+ return '';
175
+ } else {
176
+ $full_res_image = SB_Instagram_Display_Elements::get_optimum_media_url( $post, $settings, $resized_images );
177
+ /*
178
+ * By setting the height to "0" the bottom padding can be used
179
+ * as a percent to square the images. Since it needs to be a percent
180
+ * this guesses what the percent would be based on static padding.
181
+ */
182
+ $padding_bottom = '100%';
183
+ if ( $settings['imagepaddingunit'] === '%' ) {
184
+ $padding_bottom = 100 - ($settings['imagepadding'] * 2) . '%';
185
+ } else {
186
+ $padding_percent = $settings['imagepadding'] > 0 ? 100 - ($settings['cols'] / 2 * $settings['imagepadding'] / 5) : 100;
187
+ $padding_bottom = $padding_percent . '%';
188
+ }
189
+ return ' style="background-image: url(&quot;' . esc_url( $full_res_image ) . '&quot;); background-size: cover; background-position: center center; background-repeat: no-repeat; opacity: 1;height: 0;padding-bottom: ' . esc_attr( $padding_bottom ) . ';"';
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Creates a style attribute that contains all of the styles for
195
+ * the main feed div.
196
+ *
197
+ * @param $settings
198
+ *
199
+ * @return string
200
+ */
201
+ public static function get_feed_style( $settings ) {
202
+
203
+ $styles = '';
204
+ if ( ! empty( $settings['imagepadding'] )
205
+ || ! empty( $settings['background'] )
206
+ || ! empty( $settings['width'] )
207
+ || ! empty( $settings['height'] ) ) {
208
+ $styles = ' style="';
209
+ if ( ! empty( $settings['imagepadding'] ) ) {
210
+ $styles .= 'padding-bottom: ' . ((int)$settings['imagepadding'] * 2) . esc_attr( $settings['imagepaddingunit'] ) . ';';
211
+ }
212
+ if ( ! empty( $settings['background'] ) ) {
213
+ $styles .= 'background-color: rgb(' . esc_attr( sbi_hextorgb( $settings['background'] ) ). ');';
214
+ }
215
+ if ( ! empty( $settings['width'] ) ) {
216
+ $styles .= 'width: ' . (int)$settings['width'] . esc_attr( $settings['widthunit'] ) . ';';
217
+ }
218
+ if ( ! empty( $settings['height'] ) ) {
219
+ $styles .= 'height: ' . (int)$settings['height'] . esc_attr( $settings['heightunit'] ) . ';';
220
+ }
221
+ $styles .= '"';
222
+ }
223
+ return $styles;
224
+ }
225
+
226
+ /**
227
+ * Creates a style attribute for the sbi_images div
228
+ *
229
+ * @param $settings
230
+ *
231
+ * @return string
232
+ */
233
+ public static function get_sbi_images_style( $settings ) {
234
+ if ( ! empty ( $settings['imagepadding'] ) ) {
235
+ return 'style="padding: '.(int)$settings['imagepadding'] . esc_attr( $settings['imagepaddingunit'] ) . ';"';
236
+ }
237
+ return '';
238
+ }
239
+
240
+ /**
241
+ * Creates a style attribute for the header. Can be used in
242
+ * several places based on the header style
243
+ *
244
+ * @param $settings
245
+ *
246
+ * @return string
247
+ */
248
+ public static function get_header_text_color_styles( $settings ) {
249
+ if ( ! empty( $settings['headercolor'] ) ) {
250
+ return 'style="color: rgb(' . esc_attr( sbi_hextorgb( $settings['headercolor'] ) ). ');"';
251
+ }
252
+ return '';
253
+ }
254
+
255
+ /**
256
+ * Header icon and text size is styled using the class added here.
257
+ *
258
+ * @param $settings
259
+ *
260
+ * @return string
261
+ *
262
+ * @since 2.0.1/5.0
263
+ */
264
+ public static function get_header_size_class( $settings ) {
265
+ $header_size_class = in_array( strtolower( $settings['headersize'] ), array( 'medium', 'large' ) ) ? ' sbi_'.strtolower( $settings['headersize'] ) : '';
266
+ return $header_size_class;
267
+ }
268
+
269
+ /**
270
+ * Creates a style attribute for the follow button. Can be in
271
+ * the feed footer or in a boxed header.
272
+ *
273
+ * @param $settings
274
+ *
275
+ * @return string
276
+ */
277
+ public static function get_follow_styles( $settings ) {
278
+ $styles = '';
279
+ if ( ! empty( $settings['followcolor'] ) || ! empty( $settings['followtextcolor'] ) ) {
280
+ $styles = 'style="';
281
+ if ( ! empty( $settings['followcolor'] ) ) {
282
+ $styles .= 'background: rgb(' . esc_attr( sbi_hextorgb( $settings['followcolor'] ) ) . ');';
283
+ }
284
+ if ( ! empty( $settings['followtextcolor'] ) ) {
285
+ $styles .= 'color: rgb(' . esc_attr( sbi_hextorgb( $settings['followtextcolor'] ) ). ');';
286
+ }
287
+ $styles .= '"';
288
+ }
289
+ return $styles;
290
+ }
291
+
292
+ /**
293
+ * Creates a style attribute for styling the load more button.
294
+ *
295
+ * @param $settings
296
+ *
297
+ * @return string
298
+ */
299
+ public static function get_load_button_styles( $settings ) {
300
+ $styles = '';
301
+ if ( ! empty( $settings['buttoncolor'] ) || ! empty( $settings['buttontextcolor'] ) ) {
302
+ $styles = 'style="';
303
+ if ( ! empty( $settings['buttoncolor'] ) ) {
304
+ $styles .= 'background: rgb(' . esc_attr( sbi_hextorgb( $settings['buttoncolor'] ) ) . ');';
305
+ }
306
+ if ( ! empty( $settings['buttontextcolor'] ) ) {
307
+ $styles .= 'color: rgb(' . esc_attr( sbi_hextorgb( $settings['buttontextcolor'] ) ). ');';
308
+ }
309
+ $styles .= '"';
310
+ }
311
+ return $styles;
312
+ }
313
+
314
+ /**
315
+ * Returns the html for an icon based on the kind requested
316
+ *
317
+ * @param string $type kind of icon needed (ex "video" is a play button
318
+ * @param string $icon_type svg or font
319
+ *
320
+ * @return string
321
+ *
322
+ * @since 2.0/5.0
323
+ */
324
+ protected static function get_basic_icons( $type, $icon_type ) {
325
+ if ( $type === 'carousel' ) {
326
+ if ( $icon_type === 'svg' ) {
327
+ return '<svg class="svg-inline--fa fa-clone fa-w-16 sbi_lightbox_carousel_icon" aria-hidden="true" aria-label="Clone" data-fa-proƒcessed="" data-prefix="far" data-icon="clone" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
328
+ <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>
329
+ </svg>';
330
+ } else {
331
+ return '<i class="fa fa-clone sbi_carousel_icon" aria-hidden="true"></i>';
332
+ }
333
+
334
+ } elseif ( $type === 'video' ) {
335
+ if ( $icon_type === 'svg' ) {
336
+ return '<svg style="color: rgba(255,255,255,1)" class="svg-inline--fa fa-play fa-w-14 sbi_playbtn" aria-label="Play" 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>';
337
+ } else {
338
+ return '<i class="fa fa-play sbi_playbtn" aria-hidden="true"></i>';
339
+ }
340
+ } elseif ( $type === 'instagram' ) {
341
+ if ( $icon_type === 'svg' ) {
342
+ return '<svg class="svg-inline--fa fa-instagram fa-w-14" aria-hidden="true" data-fa-processed="" aria-label="Instagram" data-prefix="fab" data-icon="instagram" role="img" viewBox="0 0 448 512">
343
+ <path fill="currentColor" d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path>
344
+ </svg>';
345
+ } else {
346
+ return '<i class="fa fab fa-instagram" aria-hidden="true"></i>';
347
+ }
348
+ } elseif ( $type === 'newlogo' ) {
349
+ if ( $icon_type === 'svg' ) {
350
+ return '<svg class="sbi_new_logo fa-instagram fa-w-14" aria-hidden="true" data-fa-processed="" aria-label="Instagram" data-prefix="fab" data-icon="instagram" role="img" viewBox="0 0 448 512">
351
+ <path fill="currentColor" d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path>
352
+ </svg>';
353
+ } else {
354
+ return '<i class="sbi_new_logo"></i>';
355
+ }
356
+ } else {
357
+ return '';
358
+ }
359
+ }
360
+
361
  }
inc/class-sb-instagram-education.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ *
5
+ * @since 5.5
6
+ */
7
+ class SB_Instagram_Education {
8
+
9
+ var $plugin_version;
10
+
11
+ /**
12
+ * Constructor.
13
+ *
14
+ * @since 5.5
15
+ */
16
+ public function __construct() {
17
+
18
+ $this->hooks();
19
+ }
20
+
21
+ /**
22
+ * Hooks.
23
+ *
24
+ * @since 5.5
25
+ */
26
+ public function hooks() {
27
+ $this->plugin_version = defined( 'SBI_STORE_URL' ) ? 'pro' : 'free';
28
+ }
29
+
30
+ /**
31
+ * "Did You Know?" messages.
32
+ *
33
+ * @since 5.5
34
+ */
35
+ public function dyk_messages() {
36
+
37
+ $free_messages = array(
38
+ array(
39
+ 'title' => esc_html__( 'Get the Most out of Hashtags', 'instagram-feed' ),
40
+ 'content' => esc_html__( 'You can use hashtags on Instagram for so many things; targeted promotions, engaging with your audience, running contests, or just for categorizing posts. Learn more about how you can display Instagram hashtag feeds on your website using the Instagram Feed Pro plugin.', 'instagram-feed' ),
41
+ 'more' => 'https://smashballoon.com/instagram-feed/features/#hashtag',
42
+ 'item' => 1,
43
+ ),
44
+ array(
45
+ 'title' => esc_html__( 'Keep Visitors on Your Site', 'instagram-feed' ),
46
+ 'content' => esc_html__( "You've done the hard work of getting a visitor onto your site, now keep them there by displaying your Instagram content inside a pop-up lightbox, rather than sending your visitors away to Instagram. Learn more about the Instagram Feed Pro lightbox feature.", 'instagram-feed' ),
47
+ 'more' => 'https://smashballoon.com/instagram-feed/features/#popuplightbox',
48
+ 'item' => 2,
49
+ ),
50
+ array(
51
+ 'title' => esc_html__( 'Highlight Your Posts and Create Carousels', 'instagram-feed' ),
52
+ 'content' => esc_html__( "Feature specific Instagram posts in your feeds by using the Highlight layout to feature specific posts, either by using their ID or a hashtag in their caption. Also create rotating carousels of your photos and videos to best utilize the space on your site. These layouts and more are available in our Pro version.", 'instagram-feed' ),
53
+ 'more' => 'https://smashballoon.com/instagram-feed/features/#highlight',
54
+ 'item' => 3,
55
+ ),
56
+ array(
57
+ 'title' => esc_html__( 'Moderate your Feed Content', 'instagram-feed' ),
58
+ 'content' => esc_html__( "Control exactly which posts show up in your feed by using the Visual Moderation Mode feature to pick and choose what to display. Remove specific posts or create a whitelist of approved content using Instagram Feed Pro.", 'instagram-feed' ),
59
+ 'more' => 'https://smashballoon.com/instagram-feed/features/#moderation',
60
+ 'item' => 4,
61
+ ),
62
+ );
63
+
64
+ $pro_messages = array(
65
+ array(
66
+ 'title' => esc_html__( 'Automated YouTube Live Streaming', 'instagram-feed' ),
67
+ 'content' => esc_html__( 'You can automatically feed live YouTube videos to your website using our Feeds For YouTube Pro plugin. It takes all the hassle out of publishing live videos to your site by automating the process.', 'instagram-feed' ),
68
+ 'more' => 'https://smashballoon.com/youtube-feed/',
69
+ 'item' => 1,
70
+ ),
71
+ array(
72
+ 'title' => esc_html__( 'Display Facebook Pages and Groups', 'instagram-feed' ),
73
+ 'content' => esc_html__( 'Have a Facebook Page or Group? Easily embed a feed of posts into your website, delivering fresh content automatically to your site from Facebook. Posts, Photos, Events, Videos, Albums, Reviews, and more!', 'instagram-feed' ),
74
+ 'more' => 'https://smashballoon.com/custom-facebook-feed/',
75
+ 'item' => 2,
76
+ ),
77
+ array(
78
+ 'title' => esc_html__( 'Adding Social Proof with Twitter Feeds', 'instagram-feed' ),
79
+ 'content' => esc_html__( 'Twitter testimonials are one of the best ways to add verifiable social proof to your website. They add credibility to your brand, product, or service by displaying reviews from real people to your site, helping to convert more visitors into customers. Our free Custom Twitter Feeds plugin makes displaying Tweets on your website a breeze.', 'instagram-feed' ),
80
+ 'more' => 'https://wordpress.org/plugins/custom-twitter-feeds/',
81
+ 'item' => 3,
82
+ ),
83
+ );
84
+
85
+ if ( $this->plugin_version === 'pro' ) {
86
+ return $pro_messages;
87
+ }
88
+ return $free_messages;
89
+
90
+ }
91
+
92
+ /**
93
+ * "Did You Know?" random message.
94
+ *
95
+ * @since 5.5
96
+ */
97
+ public function dyk_message_rnd() {
98
+
99
+ $messages = $this->dyk_messages();
100
+
101
+ $index = array_rand( $messages );
102
+
103
+ return $messages[ $index ];
104
+ }
105
+
106
+ /**
107
+ * "Did You Know?" display message.
108
+ *
109
+ * @since 5.5
110
+ *
111
+ */
112
+ public function dyk_display() {
113
+
114
+ $dyk_message = $this->dyk_message_rnd();
115
+
116
+ if ( ! empty( $dyk_message['more'] ) ) {
117
+ //utm_source=plugin-pro&utm_campaign=
118
+ $dyk_message['more'] = add_query_arg(
119
+ array(
120
+ 'utm_source' => 'plugin-'.$this->plugin_version,
121
+ 'utm_campaign' => 'sbi-issue-email',
122
+ 'utm_content' => $dyk_message['item'],
123
+ ),
124
+ $dyk_message['more']
125
+ );
126
+ }
127
+
128
+ return $dyk_message;
129
+ }
130
+ }
inc/class-sb-instagram-feed.php CHANGED
@@ -1,1449 +1,1477 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Feed
4
- *
5
- * Retrieves data and generates the html for each feed. The
6
- * "display_instagram" function in the if-functions.php file
7
- * is where this class is primarily used.
8
- *
9
- * @since 2.0/4.0
10
- */
11
-
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- die( '-1' );
14
- }
15
-
16
- class SB_Instagram_Feed
17
- {
18
- /**
19
- * @var string
20
- */
21
- private $regular_feed_transient_name;
22
-
23
- /**
24
- * @var string
25
- */
26
- private $header_transient_name;
27
-
28
- /**
29
- * @var string
30
- */
31
- private $backup_feed_transient_name;
32
-
33
- /**
34
- * @var string
35
- */
36
- private $backup_header_transient_name;
37
-
38
- /**
39
- * @var array
40
- */
41
- private $post_data;
42
-
43
- /**
44
- * @var
45
- */
46
- private $header_data;
47
-
48
- /**
49
- * @var array
50
- */
51
- private $next_pages;
52
-
53
- /**
54
- * @var array
55
- */
56
- private $transient_atts;
57
-
58
- /**
59
- * @var int
60
- */
61
- private $last_retrieve;
62
-
63
- /**
64
- * @var bool
65
- */
66
- private $should_paginate;
67
-
68
- /**
69
- * @var int
70
- */
71
- private $num_api_calls;
72
-
73
- /**
74
- * @var array
75
- */
76
- private $image_ids_post_set;
77
-
78
- /**
79
- * @var bool
80
- */
81
- private $should_use_backup;
82
-
83
- /**
84
- * @var array
85
- */
86
- private $report;
87
-
88
- /**
89
- * @var array
90
- *
91
- * @since 2.1.1/5.2.1
92
- */
93
- private $resized_images;
94
-
95
- /**
96
- * @var array
97
- *
98
- * @since 2.1.3/5.2.3
99
- */
100
- protected $one_post_found;
101
-
102
- /**
103
- * SB_Instagram_Feed constructor.
104
- *
105
- * @param string $transient_name ID of this feed
106
- * generated in the SB_Instagram_Settings class
107
- */
108
- public function __construct( $transient_name ) {
109
- $this->regular_feed_transient_name = $transient_name;
110
- $this->backup_feed_transient_name = SBI_BACKUP_PREFIX . $transient_name;
111
-
112
- $sbi_header_transient_name = str_replace( 'sbi_', 'sbi_header_', $transient_name );
113
- $sbi_header_transient_name = substr($sbi_header_transient_name, 0, 44);
114
- $this->header_transient_name = $sbi_header_transient_name;
115
- $this->backup_header_transient_name = SBI_BACKUP_PREFIX . $sbi_header_transient_name;
116
-
117
- $this->post_data = array();
118
- $this->next_pages = array();
119
- $this->should_paginate = true;
120
-
121
- // this is a count of how many api calls have been made for each feed
122
- // type and term.
123
- // By default the limit is 10
124
- $this->num_api_calls = 0;
125
- $this->max_api_calls = apply_filters( 'sbi_max_concurrent_api_calls', 10 );
126
- $this->should_use_backup = false;
127
-
128
- // used for errors and the sbi_debug report
129
- $this->report = array();
130
-
131
- $this->resized_images = array();
132
-
133
- $this->one_post_found = false;
134
- }
135
-
136
- /**
137
- * @return array
138
- *
139
- * @since 2.0/5.0
140
- */
141
- public function get_post_data() {
142
- return $this->post_data;
143
- }
144
-
145
- /**
146
- * @return array
147
- *
148
- * @since 2.0/5.0
149
- */
150
- public function set_post_data( $post_data ) {
151
- $this->post_data = $post_data;
152
- }
153
-
154
- /**
155
- * @return array
156
- *
157
- * @since 2.1.1/5.2.1
158
- */
159
- public function set_resized_images( $resized_image_data ) {
160
- $this->resized_images = $resized_image_data;
161
- }
162
-
163
- /**
164
- * @return array
165
- *
166
- * @since 2.0/5.0
167
- */
168
- public function get_next_pages() {
169
- return $this->next_pages;
170
- }
171
-
172
- /**
173
- * @return array
174
- *
175
- * @since 2.1.1/5.2.1
176
- */
177
- public function get_resized_images() {
178
- return $this->resized_images;
179
- }
180
-
181
- /**
182
- * Checks the database option related the transient expiration
183
- * to ensure it will be available when the page loads
184
- *
185
- * @return bool
186
- *
187
- * @since 2.0/4.0
188
- */
189
- public function regular_cache_exists() {
190
- //Check whether the cache transient exists in the database and is available for more than one more minute
191
- $transient_exists = get_transient( $this->regular_feed_transient_name );
192
-
193
- return $transient_exists;
194
- }
195
-
196
- /**
197
- * Checks the database option related the header transient
198
- * expiration to ensure it will be available when the page loads
199
- *
200
- * @return bool
201
- *
202
- * @since 2.0/5.0
203
- */
204
- public function regular_header_cache_exists() {
205
- $header_transient = get_transient( $this->header_transient_name );
206
-
207
- return $header_transient;
208
- }
209
-
210
- /**
211
- * @return bool
212
- *
213
- * @since 2.0/5.0
214
- */
215
- public function should_use_backup() {
216
- return $this->should_use_backup || empty( $this->post_data );
217
- }
218
-
219
- /**
220
- * The header is only displayed when the setting is enabled and
221
- * an account has been connected
222
- *
223
- * Overwritten in the Pro version
224
- *
225
- * @param array $settings settings specific to this feed
226
- * @param array $feed_types_and_terms organized settings related to feed data
227
- * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
228
- *
229
- * @return bool
230
- *
231
- * @since 2.0/5.0
232
- */
233
- public function need_header( $settings, $feed_types_and_terms ) {
234
- $showheader = ($settings['showheader'] === 'on' || $settings['showheader'] === 'true' || $settings['showheader'] === true);
235
- return ($showheader && isset( $feed_types_and_terms['users'] ));
236
- }
237
-
238
- /**
239
- * Use the transient name to retrieve cached data for header
240
- *
241
- * @since 2.0/5.0
242
- */
243
- public function set_header_data_from_cache() {
244
- $header_cache = get_transient( $this->header_transient_name );
245
-
246
- $header_cache = json_decode( $header_cache, true );
247
-
248
- if ( ! empty( $header_cache ) ) {
249
- $this->header_data = $header_cache;
250
- }
251
- }
252
-
253
- public function set_header_data( $header_data ) {
254
- $this->header_data = $header_data;
255
- }
256
-
257
- /**
258
- * @since 2.0/5.0
259
- */
260
- public function get_header_data() {
261
- return $this->header_data;
262
- }
263
-
264
- /**
265
- * Sets the post data, pagination data, shortcode atts used (cron cache),
266
- * and timestamp of last retrieval from transient (cron cache)
267
- *
268
- * @param array $atts available for cron caching
269
- *
270
- * @since 2.0/5.0
271
- */
272
- public function set_post_data_from_cache( $atts = array() ) {
273
- $transient_data = get_transient( $this->regular_feed_transient_name );
274
-
275
- $transient_data = json_decode( $transient_data, true );
276
-
277
- if ( $transient_data ) {
278
- $post_data = isset( $transient_data['data'] ) ? $transient_data['data'] : array();
279
- $this->post_data = $post_data;
280
- $this->next_pages = isset( $transient_data['pagination'] ) ? $transient_data['pagination'] : array();
281
-
282
- if ( isset( $transient_data['atts'] ) ) {
283
- $this->transient_atts = $transient_data['atts'];
284
- $this->last_retrieve = $transient_data['last_retrieve'];
285
- }
286
- }
287
- }
288
-
289
- /**
290
- * Sets post data from a permanent database backup of feed
291
- * if it was created
292
- *
293
- * @since 2.0/5.0
294
- * @since 2.0/5.1.2 if backup feed data used, header data also set from backup
295
- */
296
- public function maybe_set_post_data_from_backup() {
297
- $backup_data = get_option( $this->backup_feed_transient_name, false );
298
-
299
- if ( $backup_data ) {
300
- $backup_data = json_decode( $backup_data, true );
301
-
302
- $post_data = isset( $backup_data['data'] ) ? $backup_data['data'] : array();
303
- $this->post_data = $post_data;
304
- $this->next_pages = isset( $backup_data['pagination'] ) ? $backup_data['pagination'] : array();
305
-
306
- if ( isset( $backup_data['atts'] ) ) {
307
- $this->transient_atts = $backup_data['atts'];
308
- $this->last_retrieve = $backup_data['last_retrieve'];
309
- }
310
-
311
- $this->maybe_set_header_data_from_backup();
312
-
313
- return true;
314
- } else {
315
- $this->add_report( 'no backup post data found' );
316
-
317
- return false;
318
- }
319
- }
320
-
321
- /**
322
- * Sets header data from a permanent database backup of feed
323
- * if it was created
324
- *
325
- * @since 2.0/5.0
326
- */
327
- public function maybe_set_header_data_from_backup() {
328
- $backup_header_data = get_option( $this->backup_header_transient_name, false );
329
-
330
- if ( ! empty( $backup_header_data ) ) {
331
- $backup_header_data = json_decode( $backup_header_data, true );
332
- $this->header_data = $backup_header_data;
333
-
334
- return true;
335
- } else {
336
- $this->add_report( 'no backup header data found' );
337
-
338
- return false;
339
- }
340
- }
341
-
342
- /**
343
- * Returns recorded image IDs for this post set
344
- * for use with image resizing
345
- *
346
- * @return array
347
- *
348
- * @since 2.0/5.0
349
- */
350
- public function get_image_ids_post_set() {
351
- return $this->image_ids_post_set;
352
- }
353
-
354
- /**
355
- * Retrieves data related to resized images from custom
356
- * tables using either a number, offset, and transient name
357
- * or the ids of the posts.
358
- *
359
- * Retrieving by offset and transient name not used currently
360
- * but may be needed in future updates.
361
- *
362
- * @param array/int $num_or_array_of_ids post ids from the Instagram
363
- * API
364
- * @param int $offset number of records to skip
365
- * @param string $transient_name ID of the feed
366
- *
367
- * @return array
368
- *
369
- * @since 2.0/5.0
370
- */
371
- public static function get_resized_images_source_set( $num_or_array_of_ids, $offset = 0, $transient_name = '' ) {
372
- global $sb_instagram_posts_manager;
373
-
374
- if ( $sb_instagram_posts_manager->image_resizing_disabled() ) {
375
- return array();
376
- }
377
-
378
- global $wpdb;
379
-
380
- $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
381
- $feeds_posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
382
-
383
- $feed_id_array = explode( '#', $transient_name );
384
- $feed_id = $feed_id_array[0];
385
-
386
- if ( is_array( $num_or_array_of_ids ) ) {
387
- $ids = $num_or_array_of_ids;
388
-
389
- $id_string = "'" . implode( "','", $ids ) . "'";
390
- $results = $wpdb->get_results( $wpdb->prepare( "
391
- SELECT p.media_id, p.instagram_id, p.aspect_ratio, p.sizes
392
- FROM $posts_table_name AS p
393
- INNER JOIN $feeds_posts_table_name AS f ON p.id = f.id
394
- WHERE f.feed_id = %s
395
- AND p.instagram_id IN($id_string)
396
- AND p.images_done = 1", $feed_id ), ARRAY_A );
397
-
398
- $return = array();
399
- if ( !empty( $results ) && is_array( $results ) ) {
400
-
401
- foreach ( $results as $result ) {
402
- $sizes = maybe_unserialize( $result['sizes'] );
403
- if ( ! is_array( $sizes ) ) {
404
- $sizes = array( 'full' => 640 );
405
- }
406
- $return[ $result['instagram_id'] ] = array(
407
- 'id' => $result['media_id'],
408
- 'ratio' => $result['aspect_ratio'],
409
- 'sizes' => $sizes
410
- );
411
- }
412
-
413
- }
414
- } else {
415
- $num = $num_or_array_of_ids;
416
-
417
- $results = $wpdb->get_results( $wpdb->prepare( "
418
- SELECT p.media_id, p.instagram_id, p.aspect_ratio, p.sizes
419
- FROM $posts_table_name AS p
420
- INNER JOIN $feeds_posts_table_name AS f ON p.id = f.id
421
- WHERE f.feed_id = %s
422
- AND p.images_done = 1
423
- ORDER BY p.time_stamp
424
- DESC LIMIT %d, %d", $feed_id, $offset, (int)$num ), ARRAY_A );
425
-
426
- $return = array();
427
- if ( !empty( $results ) && is_array( $results ) ) {
428
-
429
- foreach ( $results as $result ) {
430
- $sizes = maybe_unserialize( $result['sizes'] );
431
- if ( ! is_array( $sizes ) ) {
432
- $sizes = array( 'full' => 640 );
433
- }
434
- $return[ $result['instagram_id'] ] = array(
435
- 'id' => $result['media_id'],
436
- 'ratio' => $result['aspect_ratio'],
437
- 'sizes' => $sizes
438
- );
439
- }
440
-
441
- }
442
- }
443
-
444
-
445
- return $return;
446
- }
447
-
448
- /**
449
- * The plugin tracks when a post was last requested so only the most
450
- * recently displayed posts are kept in the database.
451
- * This function updates the timestamp for a set of posts
452
- * on the page.
453
- *
454
- * @param $array_of_ids
455
- *
456
- * @since 2.0/5.0
457
- */
458
- public static function update_last_requested( $array_of_ids ) {
459
- if ( empty( $array_of_ids ) ) {
460
- return;
461
- }
462
-
463
- global $wpdb;
464
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
465
- $id_string = "'" . implode( "','", $array_of_ids ) . "'";
466
-
467
- $query = $wpdb->query( $wpdb->prepare( "UPDATE $table_name
468
- SET last_requested = %s
469
- WHERE instagram_id IN ({$id_string});", date( 'Y-m-d H:i:s' ) ) );
470
- }
471
-
472
- /**
473
- * Cron caching needs additional data saved in the transient
474
- * to work properly. This function checks to make sure it's present
475
- *
476
- * @return bool
477
- *
478
- * @since 2.0/5.0
479
- */
480
- public function need_to_start_cron_job() {
481
- return (( ! empty( $this->post_data ) && ! isset( $this->transient_atts )) || empty( $this->post_data ));
482
- }
483
-
484
- /**
485
- * Checks to see if there are enough posts available to create
486
- * the current page of the feed
487
- *
488
- * @param int $num
489
- * @param int $offset
490
- *
491
- * @return bool
492
- *
493
- * @since 2.0/5.0
494
- */
495
- public function need_posts( $num, $offset = 0 ) {
496
- $num_existing_posts = is_array( $this->post_data ) ? count( $this->post_data ) : 0;
497
- $num_needed_for_page = (int)$num + (int)$offset;
498
-
499
- ($num_existing_posts < $num_needed_for_page) ? $this->add_report( 'need more posts' ) : $this->add_report( 'have enough posts' );
500
-
501
- return ($num_existing_posts < $num_needed_for_page);
502
- }
503
-
504
- /**
505
- * Checks to see if there are additional pages available for any of the
506
- * accounts in the feed and that the max conccurrent api request limit
507
- * has not been reached
508
- *
509
- * @return bool
510
- *
511
- * @since 2.0/5.0
512
- */
513
- public function can_get_more_posts() {
514
- $one_type_and_term_has_more_ages = $this->next_pages !== false;
515
- $max_concurrent_api_calls_not_met = $this->num_api_calls < $this->max_api_calls;
516
- $max_concurrent_api_calls_not_met ? $this->add_report( 'max conccurrent requests not met' ) : $this->add_report( 'max concurrent met' );
517
- $one_type_and_term_has_more_ages ? $this->add_report( 'more pages available' ) : $this->add_report( 'no next page' );
518
-
519
- return ($one_type_and_term_has_more_ages && $max_concurrent_api_calls_not_met);
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', 'custominstagramfeed' )
528
- * @param array $connected_accounts_for_feed connected account data for the
529
- * feed types and terms
530
- *
531
- * @since 2.0/5.0
532
- * @since 2.0/5.1 added logic to make a second attempt at an API connection
533
- * @since 2.0/5.1.2 remote posts only retrieved if API requests are not
534
- * delayed, terms shuffled if there are more than 5
535
- * @since 2.2/5.3 added logic to refresh the access token for basic display
536
- * accounts if needed before using it in an API request
537
- */
538
- public function add_remote_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
539
- $new_post_sets = array();
540
- $next_pages = $this->next_pages;
541
- global $sb_instagram_posts_manager;
542
-
543
- /**
544
- * Number of posts to retrieve in each API call
545
- *
546
- * @param int Minimum number of posts needed in each API request
547
- * @param array $settings Settings for this feed
548
- *
549
- * @since 2.0/5.0
550
- */
551
- $num = apply_filters( 'sbi_num_in_request', $settings['minnum'], $settings );
552
- $num = max( $num, (int)$settings['apinum'] );
553
- $params = array(
554
- 'num' => $num
555
- );
556
-
557
- $one_successful_connection = false;
558
- $one_post_found = false;
559
- $next_page_found = false;
560
- $one_api_request_delayed = false;
561
-
562
- foreach ( $feed_types_and_terms as $type => $terms ) {
563
- if ( is_array( $terms ) && count( $terms ) > 5 ) {
564
- shuffle( $terms );
565
- }
566
- foreach ( $terms as $term_and_params ) {
567
- $term = $term_and_params['term'];
568
- $params = array_merge( $params, $term_and_params['params'] );
569
- $connected_account_for_term = $connected_accounts_for_feed[ $term ];
570
-
571
- $api_requests_delayed = $sb_instagram_posts_manager->are_current_api_request_delays( $connected_account_for_term['user_id'] );
572
-
573
- if ( ! $api_requests_delayed
574
- && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== false) ) {
575
-
576
- $account_type = isset( $connected_account_for_term['type'] ) ? $connected_account_for_term['type'] : 'personal';
577
- $skip_connection = false;
578
-
579
- // basic account access tokens need to be refreshed every 60 days
580
- // normally done using WP Cron but can be done here as a fail safe
581
- if ( $account_type === 'basic' ) {
582
- if ( SB_Instagram_Token_Refresher::refresh_time_has_passed_threshold( $connected_account_for_term )
583
- && SB_Instagram_Token_Refresher::minimum_time_interval_since_last_attempt_has_passed( $connected_account_for_term ) ) {
584
- $refresher = new SB_Instagram_Token_Refresher( $connected_account_for_term );
585
- $refresher->attempt_token_refresh();
586
- $this->add_report( 'trying to refresh token ' . $term . '_' . $type );
587
- }
588
- } elseif( $account_type === 'personal' && sbi_is_after_deprecation_deadline() ) {
589
- $skip_connection = true;
590
- }
591
-
592
- if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
593
- $next_page_term = $next_pages[ $term . '_' . $type ];
594
- if ( strpos( $next_page_term, 'https://' ) !== false ) {
595
- $connection = $this->make_api_connection( $next_page_term );
596
- } else {
597
- $params['cursor'] = $next_page_term;
598
- $connection = $this->make_api_connection( $connected_account_for_term, $type, $params );
599
- }
600
- } else {
601
- $connection = $this->make_api_connection( $connected_account_for_term, $type, $params );
602
- }
603
- $this->add_report( 'api call made for ' . $term . ' - ' . $type );
604
-
605
- if ( ! $skip_connection ) {
606
- $connection->connect();
607
- }
608
- $this->num_api_calls++;
609
-
610
- if ( ! $skip_connection && ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
611
- $one_successful_connection = true;
612
-
613
- $data = $connection->get_data();
614
-
615
- if ( !$connected_account_for_term['is_valid'] ) {
616
- $this->add_report( 'clearing invalid token' );
617
- $this->clear_expired_access_token_notice( $connected_account_for_term );
618
- }
619
-
620
- if ( isset( $data[0]['id'] ) ) {
621
- $one_post_found = true;
622
-
623
- $post_set = $this->filter_posts( $data, $settings );
624
-
625
- $new_post_sets[] = $post_set;
626
- }
627
-
628
- $next_page = $connection->get_next_page();
629
- if ( ! empty( $next_page ) ) {
630
- $next_pages[ $term . '_' . $type ] = $next_page;
631
- $next_page_found = true;
632
- } else {
633
- $next_pages[ $term . '_' . $type ] = false;
634
- }
635
- } else {
636
-
637
- if ( $this->can_try_another_request( $type, $connected_accounts_for_feed[ $term ] ) ) {
638
- $this->add_report( 'trying other accounts' );
639
- $i = 0;
640
- $attempted = array( $connected_accounts_for_feed[ $term ]['user_id'] );
641
- $success = false;
642
- $different = true;
643
- $error = false;
644
-
645
- while ( $different
646
- && ! $success
647
- && $this->can_try_another_request( $type, $connected_accounts_for_feed[ $term ], $i ) ) {
648
- $different = $this->get_different_connected_account( $type, $attempted );
649
- $this->add_report( 'trying the account ' . $different['user_id'] );
650
-
651
- if ( $different ) {
652
- $connected_accounts_for_feed[ $term ] = $this->get_different_connected_account( $type, $attempted );
653
- $attempted[] = $connected_accounts_for_feed[ $term ]['user_id'];
654
- if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
655
- $connection = $this->make_api_connection( $next_pages[ $term . '_' . $type ] );
656
- } else {
657
- $connection = $this->make_api_connection( $connected_accounts_for_feed[ $term ], $type, $params );
658
- }
659
- $connection->connect();
660
- $this->num_api_calls++;
661
- if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
662
- $one_successful_connection = true;
663
- $data = $connection->get_data();
664
- if ( isset( $data[0]['id'] ) ) {
665
- $one_post_found = true;
666
- $post_set = $this->filter_posts( $data, $settings );
667
- $new_post_sets[] = $post_set;
668
- }
669
- $next_page = $connection->get_next_page();
670
- if ( ! empty( $next_page ) ) {
671
- $next_pages[ $term . '_' . $type ] = $next_page;
672
- $next_page_found = true;
673
- } else {
674
- $next_pages[ $term . '_' . $type ] = false;
675
- }
676
- } else {
677
- if ( $connection->is_wp_error() ) {
678
- $error = $connection->get_wp_error();
679
- } else {
680
- $error = $connection->get_data();
681
- }
682
- }
683
- $i++;
684
- }
685
- }
686
-
687
- if ( ! $success && $error ) {
688
- if ( is_wp_error( $error ) ) {
689
- SB_Instagram_API_Connect::handle_wp_remote_get_error( $error );
690
- } else {
691
- SB_Instagram_API_Connect::handle_instagram_error( $error, $connected_accounts_for_feed[ $term ], $type );
692
- }
693
- $next_pages[ $term . '_' . $type ] = false;
694
- }
695
- } else {
696
- if ( $skip_connection ) {
697
-
698
- } elseif ( $connection->is_wp_error() ) {
699
- SB_Instagram_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
700
- } else {
701
- SB_Instagram_API_Connect::handle_instagram_error( $connection->get_data(), $connected_accounts_for_feed[ $term ], $type );
702
- }
703
-
704
- $next_pages[ $term . '_' . $type ] = false;
705
- }
706
- }
707
- } elseif ( $api_requests_delayed ) {
708
- $one_api_request_delayed = true;
709
-
710
- $this->add_report( 'delaying API request for ' . $term . ' - ' . $type );
711
-
712
- $error = '<p><b>' . sprintf( __( 'Error: API requests are being delayed for this account.', 'instagram-feed' ), $connected_account_for_term['username'] ) . ' ' . __( 'New posts will not be retrieved.', 'instagram-feed' ) . '</b></p>';
713
- $errors = $sb_instagram_posts_manager->get_errors();
714
- if ( ! empty( $errors ) && current_user_can( 'manage_options' ) ) {
715
- if ( isset( $errors['api'] ) ) {
716
- $error .= '<p>' . $errors['api'][1] . '</p>';
717
- } elseif ( isset( $errors['connection'] ) ) {
718
- $error .= '<p>' . $errors['connection'][1] . '</p>';
719
- } // https://smashballoon.com/instagram-feed/docs/errors/
720
- $error .= '<p><a href="https://smashballoon.com/instagram-feed/docs/errors/">' . __( 'Click here to troubleshoot', 'instagram-feed' ) . '</a></p>';
721
- } else {
722
- $error .= '<p>' . __( 'There may be an issue with the Instagram access token that you are using. Your server might also be unable to connect to Instagram at this time.', 'instagram-feed' ) . '</p>';
723
- }
724
-
725
- $sb_instagram_posts_manager->add_frontend_error( 'at_' . $connected_account_for_term['username'], $error );
726
- }
727
-
728
- }
729
- }
730
-
731
- if ( ! $one_successful_connection || ($one_api_request_delayed && empty( $new_post_sets )) ) {
732
- $this->should_use_backup = true;
733
- }
734
- $posts = $this->merge_posts( $new_post_sets, $settings );
735
-
736
- $posts = $this->sort_posts( $posts, $settings );
737
-
738
- if ( ! empty( $this->post_data ) && is_array( $this->post_data ) ) {
739
- $posts = array_merge( $this->post_data, $posts );
740
- } elseif ( $one_post_found ) {
741
- $this->one_post_found = true;
742
- }
743
-
744
- $this->post_data = $posts;
745
-
746
- if ( isset( $next_page_found ) && $next_page_found ) {
747
- $this->next_pages = $next_pages;
748
- } else {
749
- $this->next_pages = false;
750
- }
751
- }
752
-
753
- /**
754
- * Connects to the Instagram API and records returned data
755
- *
756
- * @param $settings
757
- * @param array $feed_types_and_terms organized settings related to feed data
758
- * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
759
- * @param array $connected_accounts_for_feed connected account data for the
760
- * feed types and terms
761
- *
762
- * @since 2.0/5.0
763
- * @since 2.2/5.3 added logic to append bio data from the related
764
- * connected account if not available in the API response
765
- */
766
- public function set_remote_header_data( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
767
- $first_user = $this->get_first_user( $feed_types_and_terms );
768
- $this->header_data = false;
769
- global $sb_instagram_posts_manager;
770
-
771
- $api_requests_delayed = $sb_instagram_posts_manager->are_current_api_request_delays( $connected_accounts_for_feed[ $first_user ]['user_id'] );
772
-
773
- if ( isset( $connected_accounts_for_feed[ $first_user ] ) && ! $api_requests_delayed ) {
774
- $connection = new SB_Instagram_API_Connect( $connected_accounts_for_feed[ $first_user ], 'header', array() );
775
-
776
- $connection->connect();
777
-
778
- if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
779
- $this->header_data = $connection->get_data();
780
-
781
- if ( isset( $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) && $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) {
782
- $upload = wp_upload_dir();
783
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
784
-
785
- $full_file_name = $resized_url . $this->header_data['username'] . '.jpg';
786
- $this->header_data['local_avatar'] = $full_file_name;
787
- }
788
- if ( empty( $this->header_data['bio'] )
789
- && isset( $connected_accounts_for_feed[ $first_user ]['bio'] ) ) {
790
-
791
- $this->header_data['bio'] = sbi_decode_emoji( $connected_accounts_for_feed[ $first_user ]['bio'] );
792
- }
793
- } else {
794
- if ( $connection->is_wp_error() ) {
795
- SB_Instagram_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
796
- } else {
797
- SB_Instagram_API_Connect::handle_instagram_error( $connection->get_data(), $connected_accounts_for_feed[ $first_user ], 'header' );
798
- }
799
- }
800
- }
801
- }
802
-
803
- /**
804
- * Stores feed data in a transient for a specified time
805
- *
806
- * @param int $cache_time
807
- * @param bool $save_backup
808
- *
809
- * @since 2.0/5.0
810
- * @since 2.0/5.1 duplicate posts removed
811
- */
812
- public function cache_feed_data( $cache_time, $save_backup = true ) {
813
- if ( ! empty( $this->post_data ) || ! empty( $this->next_pages ) ) {
814
- $this->remove_duplicate_posts();
815
- $this->trim_posts_to_max();
816
-
817
- $to_cache = array(
818
- 'data' => $this->post_data,
819
- 'pagination' => $this->next_pages
820
- );
821
-
822
- set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
823
-
824
- if ( $save_backup ) {
825
- update_option( $this->backup_feed_transient_name, wp_json_encode( $to_cache ), false );
826
- }
827
- } else {
828
- $this->add_report( 'no data not caching' );
829
- }
830
- }
831
-
832
- /**
833
- * Stores feed data with additional data specifically for cron caching
834
- *
835
- * @param array $to_cache feed data with additional things like the shortcode
836
- * settings, when the cache was last requested, when new posts were last retrieved
837
- * @param int $cache_time how long the cache will last
838
- * @param bool $save_backup whether or not to also save this as a permanent cache
839
- *
840
- * @since 2.0/5.0
841
- * @since 2.0/5.1 duplicate posts removed, cache set trimmed to a maximum
842
- */
843
- public function set_cron_cache( $to_cache, $cache_time, $save_backup = true ) {
844
- if ( ! empty( $this->post_data )
845
- || ! empty( $this->next_pages )
846
- || ! empty( $to_cache['data'] ) ) {
847
- $this->remove_duplicate_posts();
848
- $this->trim_posts_to_max();
849
-
850
- $to_cache['data'] = isset( $to_cache['data'] ) ? $to_cache['data'] : $this->post_data;
851
- $to_cache['pagination'] = isset( $to_cache['next_pages'] ) ? $to_cache['next_pages'] : $this->next_pages;
852
- $to_cache['atts'] = isset( $to_cache['atts'] ) ? $to_cache['atts'] : $this->transient_atts;
853
- $to_cache['last_requested'] = isset( $to_cache['last_requested'] ) ? $to_cache['last_requested'] : time();
854
- $to_cache['last_retrieve'] = isset( $to_cache['last_retrieve'] ) ? $to_cache['last_retrieve'] : $this->last_retrieve;
855
-
856
- set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
857
-
858
- if ( $save_backup ) {
859
- update_option( $this->backup_feed_transient_name, wp_json_encode( $to_cache ), false );
860
- }
861
- } else {
862
- $this->add_report( 'no data not caching' );
863
- }
864
-
865
- }
866
-
867
- /**
868
- * Stores header data for a specified time as a transient
869
- *
870
- * @param int $cache_time
871
- * @param bool $save_backup
872
- *
873
- * @since 2.0/5.0
874
- */
875
- public function cache_header_data( $cache_time, $save_backup = true ) {
876
- if ( $this->header_data ) {
877
- set_transient( $this->header_transient_name, wp_json_encode( $this->header_data ), $cache_time );
878
-
879
- if ( $save_backup ) {
880
- update_option( $this->backup_header_transient_name, wp_json_encode( $this->header_data ), false );
881
- }
882
- }
883
- }
884
-
885
- /**
886
- * Used to randomly trigger an updating of the last requested data for cron caching
887
- *
888
- * @return bool
889
- *
890
- * @since 2.0/5.0
891
- */
892
- public function should_update_last_requested() {
893
- return (rand( 1, 20 ) === 20);
894
- }
895
-
896
- /**
897
- * Determines if pagination can and should be used based on settings and available feed data
898
- *
899
- * @param array $settings
900
- * @param int $offset
901
- *
902
- * @return bool
903
- *
904
- * @since 2.0/5.0
905
- */
906
- public function should_use_pagination( $settings, $offset = 0 ) {
907
- if ( $settings['minnum'] < 1 ) {
908
- return false;
909
- }
910
- $posts_available = count( $this->post_data ) - ($offset + $settings['num']);
911
- $show_loadmore_button_by_settings = ($settings['showbutton'] == 'on' || $settings['showbutton'] == 'true' || $settings['showbutton'] == true ) && $settings['showbutton'] !== 'false';
912
-
913
- if ( $show_loadmore_button_by_settings ) {
914
- // used for permanent and whitelist feeds
915
- if ( $this->feed_is_complete( $settings, $offset ) ) {
916
- $this->add_report( 'no pagination, feed complete' );
917
- return false;
918
- }
919
- if ( $posts_available > 0 ) {
920
- $this->add_report( 'do pagination, posts available' );
921
- return true;
922
- }
923
- $pages = $this->next_pages;
924
-
925
- if ( $pages && ! $this->should_use_backup() ) {
926
- foreach ( $pages as $page ) {
927
- if ( ! empty( $page ) ) {
928
- return true;
929
- }
930
- }
931
- }
932
-
933
- }
934
-
935
-
936
- $this->add_report( 'no pagination, no posts available' );
937
-
938
- return false;
939
- }
940
-
941
- /**
942
- * Generates the HTML for the feed if post data is available. Although it seems
943
- * some of the variables ar not used they are set here to hide where they
944
- * come from when used in the feed templates.
945
- *
946
- * @param array $settings
947
- * @param array $atts
948
- * @param array $feed_types_and_terms organized settings related to feed data
949
- * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
950
- * @param array $connected_accounts_for_feed connected account data for the
951
- * feed types and terms
952
- *
953
- * @return false|string
954
- *
955
- * @since 2.0/5.0
956
- */
957
- public function get_the_feed_html( $settings, $atts, $feed_types_and_terms, $connected_accounts_for_feed ) {
958
- global $sb_instagram_posts_manager;
959
-
960
- if ( empty( $this->post_data ) && ! empty( $connected_accounts_for_feed ) && $settings['minnum'] > 0 ) {
961
- $this->handle_no_posts_found( $settings, $feed_types_and_terms );
962
- }
963
- $posts = array_slice( $this->post_data, 0, $settings['minnum'] );
964
- $header_data = ! empty( $this->header_data ) ? $this->header_data : false;
965
-
966
- $first_user = ! empty( $feed_types_and_terms['users'][0] ) ? $feed_types_and_terms['users'][0]['term'] : false;
967
- $first_username = false;
968
- if ( $first_user ) {
969
- $first_username = isset( $connected_accounts_for_feed[ $first_user ]['username'] ) ? $connected_accounts_for_feed[ $first_user ]['username'] : $first_user;
970
- } elseif ( $header_data ) { // in case no connected account for feed
971
- $first_username = SB_Instagram_Parse::get_username( $header_data );
972
- } elseif ( isset( $feed_types_and_terms['users'] ) && isset( $this->post_data[0] ) ) { // in case no connected account and no header
973
- $first_username = SB_Instagram_Parse::get_username( $this->post_data[0] );
974
- }
975
- $use_pagination = $this->should_use_pagination( $settings, 0 );
976
-
977
- $feed_id = $this->regular_feed_transient_name;
978
- $shortcode_atts = ! empty( $atts ) ? wp_json_encode( $atts ) : '{}';
979
-
980
- $settings['header_outside'] = false;
981
- $settings['header_inside'] = false;
982
- if ( $header_data && $settings['showheader'] ) {
983
- $settings['header_inside'] = true;
984
- }
985
-
986
- $other_atts = '';
987
-
988
- $classes = array();
989
- if ( empty( $settings['widthresp'] ) || $settings['widthresp'] == 'on' || $settings['widthresp'] == 'true' || $settings['widthresp'] === true ) {
990
- if ( $settings['widthresp'] !== 'false' ) {
991
- $classes[] = 'sbi_width_resp';
992
- }
993
- }
994
- if ( ! empty( $settings['class'] ) ) {
995
- $classes[] = esc_attr( $settings['class'] );
996
- }
997
- if ( ! empty( $settings['height'] )
998
- && (((int)$settings['height'] < 100 && $settings['heightunit'] === '%') || $settings['heightunit'] === 'px') ) {
999
- $classes[] = 'sbi_fixed_height';
1000
- }
1001
- if ( ! empty( $settings['disablemobile'] )
1002
- && ($settings['disablemobile'] == 'on' || $settings['disablemobile'] == 'true' || $settings['disablemobile'] == true) ) {
1003
- if ( $settings['disablemobile'] !== 'false' ) {
1004
- $classes[] = 'sbi_disable_mobile';
1005
- }
1006
- }
1007
-
1008
- $additional_classes = '';
1009
- if ( ! empty( $classes ) ) {
1010
- $additional_classes = ' ' . implode( ' ', $classes );
1011
- }
1012
-
1013
- $other_atts = $this->add_other_atts( $other_atts, $settings );
1014
-
1015
- $flags = array();
1016
-
1017
- if ( $settings['disable_resize'] ) {
1018
- $flags[] = 'resizeDisable';
1019
- } elseif ( $settings['favor_local'] ) {
1020
- $flags[] = 'favorLocal';
1021
- }
1022
-
1023
- if ( $settings['disable_js_image_loading'] ) {
1024
- $flags[] = 'imageLoadDisable';
1025
- }
1026
- if ( $settings['ajax_post_load'] ) {
1027
- $flags[] = 'ajaxPostLoad';
1028
- }
1029
- if ( isset( $_GET['sbi_debug'] ) ) {
1030
- $flags[] = 'debug';
1031
- }
1032
-
1033
- $ajax_test_status = $sb_instagram_posts_manager->get_ajax_status();
1034
-
1035
- if ( $sb_instagram_posts_manager->maybe_start_ajax_test() && ! $ajax_test_status['successful'] ) {
1036
- $flags[] = 'testAjax';
1037
- } elseif ( $sb_instagram_posts_manager->should_add_ajax_test_notice() ) {
1038
- $error = '<p><b>' . __( 'Error: admin-ajax.php test was not successful. Some features may not be available.', 'instagram-feed' ) . '</b>';
1039
- $error .= '<p>' . __( sprintf( 'Please visit %s to troubleshoot.', '<a href="https://smashballoon.com/admin-ajax-requests-are-not-working/">'.__( 'this page', 'instagram-feed' ).'</a>' ), 'instagram-feed' ) . '</p>';
1040
-
1041
- $sb_instagram_posts_manager->add_frontend_error( 'ajax', $error );
1042
- }
1043
-
1044
- if ( ! empty( $flags ) ) {
1045
- $other_atts .= ' data-sbi-flags="' . implode(',', $flags ) . '"';
1046
- }
1047
-
1048
- ob_start();
1049
- include sbi_get_feed_template_part( 'feed', $settings );
1050
- $html = ob_get_contents();
1051
- ob_get_clean();
1052
-
1053
- if ( $settings['ajaxtheme'] ) {
1054
- $html .= $this->get_ajax_page_load_html();
1055
- }
1056
-
1057
- return $html;
1058
- }
1059
-
1060
- /**
1061
- * Generates HTML for individual sbi_item elements
1062
- *
1063
- * @param array $settings
1064
- * @param int $offset
1065
- * @param array $feed_types_and_terms organized settings related to feed data
1066
- * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
1067
- * @param array $connected_accounts_for_feed connected account data for the
1068
- * feed types and terms
1069
- *
1070
- * @return false|string
1071
- *
1072
- * @since 2.0/5.0
1073
- */
1074
- public function get_the_items_html( $settings, $offset, $feed_types_and_terms, $connected_accounts_for_feed ) {
1075
- if ( empty( $this->post_data ) ) {
1076
- ob_start();
1077
- $html = ob_get_contents();
1078
- ob_get_clean(); ?>
1079
- <p><?php _e( 'No posts found.', 'instagram-feed' ); ?></p>
1080
- <?php
1081
- $html = ob_get_contents();
1082
- ob_get_clean();
1083
- return $html;
1084
- }
1085
-
1086
- $posts = array_slice( $this->post_data, $offset, $settings['num'] );
1087
-
1088
- ob_start();
1089
-
1090
- $this->posts_loop( $posts, $settings, $offset );
1091
-
1092
- $html = ob_get_contents();
1093
- ob_get_clean();
1094
-
1095
- return $html;
1096
- }
1097
-
1098
- /**
1099
- * Overwritten in the Pro version
1100
- *
1101
- * @return object
1102
- */
1103
- public function make_api_connection( $connected_account_or_page, $type = NULL, $params = NULL ) {
1104
- return new SB_Instagram_API_Connect( $connected_account_or_page, $type, $params );
1105
- }
1106
-
1107
- /**
1108
- * When the feed is loaded with AJAX, the JavaScript for the plugin
1109
- * needs to be triggered again. This function is a workaround that adds
1110
- * the file and settings to the page whenever the feed is generated.
1111
- *
1112
- * @return string
1113
- *
1114
- * @since 2.0/5.0
1115
- */
1116
- public static function get_ajax_page_load_html() {
1117
- $sbi_options = sbi_get_database_settings();
1118
- $font_method = isset( $sbi_options['sbi_font_method'] ) ? $sbi_options['sbi_font_method'] : 'svg';
1119
- $upload = wp_upload_dir();
1120
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
1121
-
1122
- $js_options = array(
1123
- 'font_method' => $font_method,
1124
- 'placeholder' => trailingslashit( SBI_PLUGIN_URL ) . 'img/placeholder.png',
1125
- 'resized_url' => $resized_url
1126
- );
1127
-
1128
- $encoded_options = wp_json_encode( $js_options );
1129
-
1130
- $js_option_html = '<script type="text/javascript">var sb_instagram_js_options = ' . $encoded_options . ';</script>';
1131
- $js_option_html .= "<script type='text/javascript' src='" . trailingslashit( SBI_PLUGIN_URL ) . 'js/sb-instagram.min.js?ver=' . SBIVER . "'></script>";
1132
-
1133
- return $js_option_html;
1134
- }
1135
-
1136
- /**
1137
- * Overwritten in the Pro version
1138
- *
1139
- * @param $feed_types_and_terms
1140
- *
1141
- * @return string
1142
- *
1143
- * @since 2.1/5.2
1144
- */
1145
- public function get_first_user( $feed_types_and_terms ) {
1146
- if ( isset( $feed_types_and_terms['users'][0] ) ) {
1147
- return $feed_types_and_terms['users'][0]['term'];
1148
- } else {
1149
- return '';
1150
- }
1151
- }
1152
-
1153
- /**
1154
- * Adds recorded strings to an array
1155
- *
1156
- * @param $to_add
1157
- *
1158
- * @since 2.0/5.0
1159
- */
1160
- public function add_report( $to_add ) {
1161
- $this->report[] = $to_add;
1162
- }
1163
-
1164
- /**
1165
- * @return array
1166
- *
1167
- * @since 2.0/5.0
1168
- */
1169
- public function get_report() {
1170
- return $this->report;
1171
- }
1172
-
1173
- /**
1174
- * Additional options/settings added to the main div
1175
- * for the feed
1176
- *
1177
- * Overwritten in the Pro version
1178
- *
1179
- * @param $other_atts
1180
- * @param $settings
1181
- *
1182
- * @return string
1183
- */
1184
- protected function add_other_atts( $other_atts, $settings ) {
1185
- return '';
1186
- }
1187
-
1188
- /**
1189
- * Used for filtering a single API request worth of posts
1190
- *
1191
- * Overwritten in the Pro version
1192
- *
1193
- * @param array $post_set a single set of post data from the api
1194
- *
1195
- * @return mixed|array
1196
- *
1197
- * @since 2.0/5.0
1198
- */
1199
- protected function filter_posts( $post_set, $settings = array() ) {
1200
- // array_unique( $post_set, SORT_REGULAR);
1201
-
1202
- return $post_set;
1203
- }
1204
-
1205
- protected function handle_no_posts_found( $settings = array(), $feed_types_and_terms = array() ) {
1206
- global $sb_instagram_posts_manager;
1207
-
1208
- $error = '<p><b>' . __( 'Error: No posts found.', 'instagram-feed' ) . '</b>';
1209
- $error .= '<p>' . __( 'Make sure this account has posts available on instagram.com.', 'instagram-feed' ) . '</p>';
1210
- $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
1211
- $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
1212
- if ( current_user_can( $cap ) ) {
1213
- $error .= '<p><a href="https://smashballoon.com/instagram-feed/docs/errors/">' . __( 'Click here to troubleshoot', 'instagram-feed' ) . '</a></p>';
1214
- }
1215
-
1216
- $sb_instagram_posts_manager->add_frontend_error( 'noposts', $error );
1217
- }
1218
-
1219
- protected function remove_duplicate_posts() {
1220
- $posts = $this->post_data;
1221
- $ids_in_feed = array();
1222
- $non_duplicate_posts = array();
1223
- $removed = array();
1224
-
1225
- foreach ( $posts as $post ) {
1226
- $post_id = SB_Instagram_Parse::get_post_id( $post );
1227
- if ( ! in_array( $post_id, $ids_in_feed, true ) ) {
1228
- $ids_in_feed[] = $post_id;
1229
- $non_duplicate_posts[] = $post;
1230
- } else {
1231
- $removed[] = $post_id;
1232
- }
1233
- }
1234
-
1235
- $this->add_report( 'removed duplicates: ' . implode(', ', $removed ) );
1236
- $this->set_post_data( $non_duplicate_posts );
1237
- }
1238
-
1239
- /**
1240
- * Used for limiting the cache size
1241
- *
1242
- * @since 2.0/5.1.1
1243
- */
1244
- protected function trim_posts_to_max() {
1245
- if ( ! is_array( $this->post_data ) ) {
1246
- return;
1247
- }
1248
-
1249
- $max = apply_filters( 'sbi_max_cache_size', 500 );
1250
- $this->set_post_data( array_slice( $this->post_data , 0, $max ) );
1251
-
1252
- }
1253
-
1254
- /**
1255
- * Used for permanent feeds or white list feeds to
1256
- * stop pagination if all posts are already added
1257
- *
1258
- * Overwritten in the Pro version
1259
- *
1260
- * @param array $settings
1261
- * @param int $offset
1262
- *
1263
- * @return bool
1264
- *
1265
- * @since 2.0/5.0
1266
- */
1267
- protected function feed_is_complete( $settings, $offset = 0 ) {
1268
- return false;
1269
- }
1270
-
1271
- /**
1272
- * @param $connected_account_for_term
1273
- *
1274
- * @since 2.0/5.1.2
1275
- */
1276
- private function clear_expired_access_token_notice( $connected_account_for_term ) {
1277
- $sbi_options = get_option( 'sb_instagram_settings' );
1278
- $ca_to_save = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
1279
-
1280
- if ( ! empty( $ca_to_save ) && ! empty( $connected_account_for_term ) ) {
1281
-
1282
- foreach ( $ca_to_save as $account ) {
1283
- if ( $connected_account_for_term['access_token'] === $account['access_token'] ) {
1284
- $ca_to_save[ $account['user_id'] ]['is_valid'] = true;
1285
- }
1286
- }
1287
-
1288
- $sbi_options['connected_accounts'] = $ca_to_save;
1289
-
1290
- update_option( 'sb_instagram_settings', $sbi_options );
1291
- }
1292
- }
1293
-
1294
- /**
1295
- * Iterates through post data and tracks the index of the current post.
1296
- * The actual post ids of the posts are stored in an array so the plugin
1297
- * can search for local images that may be available.
1298
- *
1299
- * @param array $posts final filtered post data for the feed
1300
- * @param array $settings
1301
- * @param int $offset
1302
- *
1303
- * @since 2.0/5.0
1304
- */
1305
- private function posts_loop( $posts, $settings, $offset = 0 ) {
1306
-
1307
- $image_ids = array();
1308
- $post_index = $offset;
1309
- $icon_type = $settings['font_method'];
1310
- $resized_images = $this->get_resized_images();
1311
-
1312
- foreach ( $posts as $post ) {
1313
- $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
1314
- $account_type = SB_Instagram_Parse::get_account_type( $post );
1315
- include sbi_get_feed_template_part( 'item', $settings );
1316
- $post_index++;
1317
- }
1318
-
1319
- $this->image_ids_post_set = $image_ids;
1320
- }
1321
-
1322
- /**
1323
- * Uses array of API request results and merges them based on how
1324
- * the feed should be sorted. Mixed feeds are always sorted alternating
1325
- * since there is no post date for hashtag feeds.
1326
- *
1327
- * @param array $post_sets an array of single API request worth
1328
- * of posts
1329
- * @param array $settings
1330
- *
1331
- * @return array
1332
- *
1333
- * @since 2.0/5.0
1334
- */
1335
- private function merge_posts( $post_sets, $settings ) {
1336
- $merged_posts = array();
1337
- if ( $settings['sortby'] === 'alternate' ) {
1338
- // don't bother merging posts if there is only one post set
1339
- if ( isset( $post_sets[1] ) ) {
1340
- $min_cycles = max( 1, (int)$settings['num'] );
1341
- for( $i = 0; $i <= $min_cycles; $i++ ) {
1342
- foreach ( $post_sets as $post_set ) {
1343
- if ( isset( $post_set[ $i ] ) && isset( $post_set[ $i ]['id'] ) ) {
1344
- $merged_posts[] = $post_set[ $i ];
1345
- }
1346
- }
1347
- }
1348
- } else {
1349
- $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1350
- }
1351
- } else {
1352
- // don't bother merging posts if there is only one post set
1353
- if ( isset( $post_sets[1] ) ) {
1354
- foreach ( $post_sets as $post_set ) {
1355
- if ( isset( $post_set[0]['id'] ) ) {
1356
- $merged_posts = array_merge( $merged_posts, $post_set );
1357
- }
1358
- }
1359
- } else {
1360
- $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1361
- }
1362
- }
1363
-
1364
-
1365
- return $merged_posts;
1366
- }
1367
-
1368
- /**
1369
- * Sorts a post set based on sorting settings. Sorting by "alternate"
1370
- * is done when merging posts for efficiency's sake so the post set is
1371
- * just returned as it is.
1372
- *
1373
- * @param array $post_set
1374
- * @param array $settings
1375
- *
1376
- * @return mixed|array
1377
- *
1378
- * @since 2.0/5.0
1379
- * @since 2.1/5.2 added filter hook for applying custom sorting
1380
- */
1381
- private function sort_posts( $post_set, $settings ) {
1382
- if ( empty( $post_set ) ) {
1383
- return $post_set;
1384
- }
1385
-
1386
- // sorting done with "merge_posts" to be more efficient
1387
- if ( $settings['sortby'] === 'alternate' ) {
1388
- $return_post_set = $post_set;
1389
- } elseif ( $settings['sortby'] === 'random' ) {
1390
- /*
1391
- * randomly selects posts in a random order. Cache saves posts
1392
- * in this random order so paginating does not cause some posts to show up
1393
- * twice or not at all
1394
- */
1395
- usort($post_set, 'sbi_rand_sort' );
1396
- $return_post_set = $post_set;
1397
-
1398
- } else {
1399
- // compares posted on dates of posts
1400
- usort($post_set, 'sbi_date_sort' );
1401
- $return_post_set = $post_set;
1402
- }
1403
-
1404
- /**
1405
- * Apply a custom sorting of posts
1406
- *
1407
- * @param array $return_post_set Ordered set of filtered posts
1408
- * @param array $settings Settings for this feed
1409
- *
1410
- * @since 2.1/5.2
1411
- */
1412
-
1413
- return apply_filters( 'sbi_sorted_posts', $return_post_set, $settings );
1414
- }
1415
-
1416
- /**
1417
- * Can trigger a second attempt at getting posts from the API
1418
- *
1419
- * Overwritten in the Pro version
1420
- *
1421
- * @param string $type
1422
- * @param array $connected_account_with_error
1423
- * @param int $attempts
1424
- *
1425
- * @return bool
1426
- *
1427
- * @since 2.0/5.1.1
1428
- */
1429
- protected function can_try_another_request( $type, $connected_account_with_error, $attempts = 0 ) {
1430
- return false;
1431
- }
1432
-
1433
- /**
1434
- * returns a second connected account if it exists
1435
- *
1436
- * Overwritten in the Pro version
1437
- *
1438
- * @param string $type
1439
- * @param array $attempted_connected_accounts
1440
- *
1441
- * @return bool
1442
- *
1443
- * @since 2.0/5.1.1
1444
- */
1445
- protected function get_different_connected_account( $type, $attempted_connected_accounts ) {
1446
- return false;
1447
- }
1448
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1449
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Feed
4
+ *
5
+ * Retrieves data and generates the html for each feed. The
6
+ * "display_instagram" function in the if-functions.php file
7
+ * is where this class is primarily used.
8
+ *
9
+ * @since 2.0/4.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ die( '-1' );
14
+ }
15
+
16
+ class SB_Instagram_Feed
17
+ {
18
+ /**
19
+ * @var string
20
+ */
21
+ private $regular_feed_transient_name;
22
+
23
+ /**
24
+ * @var string
25
+ */
26
+ private $header_transient_name;
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ private $backup_feed_transient_name;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ private $backup_header_transient_name;
37
+
38
+ /**
39
+ * @var array
40
+ */
41
+ private $post_data;
42
+
43
+ /**
44
+ * @var
45
+ */
46
+ private $header_data;
47
+
48
+ /**
49
+ * @var array
50
+ */
51
+ private $next_pages;
52
+
53
+ /**
54
+ * @var array
55
+ */
56
+ private $transient_atts;
57
+
58
+ /**
59
+ * @var int
60
+ */
61
+ private $last_retrieve;
62
+
63
+ /**
64
+ * @var bool
65
+ */
66
+ private $should_paginate;
67
+
68
+ /**
69
+ * @var int
70
+ */
71
+ private $num_api_calls;
72
+
73
+ /**
74
+ * @var array
75
+ */
76
+ private $image_ids_post_set;
77
+
78
+ /**
79
+ * @var bool
80
+ */
81
+ private $should_use_backup;
82
+
83
+ /**
84
+ * @var array
85
+ */
86
+ private $report;
87
+
88
+ /**
89
+ * @var array
90
+ *
91
+ * @since 2.1.1/5.2.1
92
+ */
93
+ private $resized_images;
94
+
95
+ /**
96
+ * @var array
97
+ *
98
+ * @since 2.1.3/5.2.3
99
+ */
100
+ protected $one_post_found;
101
+
102
+ /**
103
+ * SB_Instagram_Feed constructor.
104
+ *
105
+ * @param string $transient_name ID of this feed
106
+ * generated in the SB_Instagram_Settings class
107
+ */
108
+ public function __construct( $transient_name ) {
109
+ $this->regular_feed_transient_name = $transient_name;
110
+ $this->backup_feed_transient_name = SBI_BACKUP_PREFIX . $transient_name;
111
+
112
+ $sbi_header_transient_name = str_replace( 'sbi_', 'sbi_header_', $transient_name );
113
+ $sbi_header_transient_name = substr($sbi_header_transient_name, 0, 44);
114
+ $this->header_transient_name = $sbi_header_transient_name;
115
+ $this->backup_header_transient_name = SBI_BACKUP_PREFIX . $sbi_header_transient_name;
116
+
117
+ $this->post_data = array();
118
+ $this->next_pages = array();
119
+ $this->should_paginate = true;
120
+
121
+ // this is a count of how many api calls have been made for each feed
122
+ // type and term.
123
+ // By default the limit is 10
124
+ $this->num_api_calls = 0;
125
+ $this->max_api_calls = apply_filters( 'sbi_max_concurrent_api_calls', 10 );
126
+ $this->should_use_backup = false;
127
+
128
+ // used for errors and the sbi_debug report
129
+ $this->report = array();
130
+
131
+ $this->resized_images = array();
132
+
133
+ $this->one_post_found = false;
134
+ }
135
+
136
+ /**
137
+ * @return array
138
+ *
139
+ * @since 2.0/5.0
140
+ */
141
+ public function get_post_data() {
142
+ return $this->post_data;
143
+ }
144
+
145
+ /**
146
+ * @return array
147
+ *
148
+ * @since 2.0/5.0
149
+ */
150
+ public function set_post_data( $post_data ) {
151
+ $this->post_data = $post_data;
152
+ }
153
+
154
+ /**
155
+ * @return array
156
+ *
157
+ * @since 2.1.1/5.2.1
158
+ */
159
+ public function set_resized_images( $resized_image_data ) {
160
+ $this->resized_images = $resized_image_data;
161
+ }
162
+
163
+ /**
164
+ * @return array
165
+ *
166
+ * @since 2.0/5.0
167
+ */
168
+ public function get_next_pages() {
169
+ return $this->next_pages;
170
+ }
171
+
172
+ /**
173
+ * @return array
174
+ *
175
+ * @since 2.1.1/5.2.1
176
+ */
177
+ public function get_resized_images() {
178
+ return $this->resized_images;
179
+ }
180
+
181
+ /**
182
+ * Checks the database option related the transient expiration
183
+ * to ensure it will be available when the page loads
184
+ *
185
+ * @return bool
186
+ *
187
+ * @since 2.0/4.0
188
+ */
189
+ public function regular_cache_exists() {
190
+ //Check whether the cache transient exists in the database and is available for more than one more minute
191
+ $transient_exists = get_transient( $this->regular_feed_transient_name );
192
+
193
+ return $transient_exists;
194
+ }
195
+
196
+ /**
197
+ * Checks the database option related the header transient
198
+ * expiration to ensure it will be available when the page loads
199
+ *
200
+ * @return bool
201
+ *
202
+ * @since 2.0/5.0
203
+ */
204
+ public function regular_header_cache_exists() {
205
+ $header_transient = get_transient( $this->header_transient_name );
206
+
207
+ return $header_transient;
208
+ }
209
+
210
+ /**
211
+ * @return bool
212
+ *
213
+ * @since 2.0/5.0
214
+ */
215
+ public function should_use_backup() {
216
+ return $this->should_use_backup || empty( $this->post_data );
217
+ }
218
+
219
+ /**
220
+ * The header is only displayed when the setting is enabled and
221
+ * an account has been connected
222
+ *
223
+ * Overwritten in the Pro version
224
+ *
225
+ * @param array $settings settings specific to this feed
226
+ * @param array $feed_types_and_terms organized settings related to feed data
227
+ * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
228
+ *
229
+ * @return bool
230
+ *
231
+ * @since 2.0/5.0
232
+ */
233
+ public function need_header( $settings, $feed_types_and_terms ) {
234
+ $showheader = ($settings['showheader'] === 'on' || $settings['showheader'] === 'true' || $settings['showheader'] === true);
235
+ return ($showheader && isset( $feed_types_and_terms['users'] ));
236
+ }
237
+
238
+ /**
239
+ * Use the transient name to retrieve cached data for header
240
+ *
241
+ * @since 2.0/5.0
242
+ */
243
+ public function set_header_data_from_cache() {
244
+ $header_cache = get_transient( $this->header_transient_name );
245
+
246
+ $header_cache = json_decode( $header_cache, true );
247
+
248
+ if ( ! empty( $header_cache ) ) {
249
+ $this->header_data = $header_cache;
250
+ }
251
+ }
252
+
253
+ public function set_header_data( $header_data ) {
254
+ $this->header_data = $header_data;
255
+ }
256
+
257
+ /**
258
+ * @since 2.0/5.0
259
+ */
260
+ public function get_header_data() {
261
+ return $this->header_data;
262
+ }
263
+
264
+ /**
265
+ * Sets the post data, pagination data, shortcode atts used (cron cache),
266
+ * and timestamp of last retrieval from transient (cron cache)
267
+ *
268
+ * @param array $atts available for cron caching
269
+ *
270
+ * @since 2.0/5.0
271
+ */
272
+ public function set_post_data_from_cache( $atts = array() ) {
273
+ $transient_data = get_transient( $this->regular_feed_transient_name );
274
+
275
+ $transient_data = json_decode( $transient_data, true );
276
+
277
+ if ( $transient_data ) {
278
+ $post_data = isset( $transient_data['data'] ) ? $transient_data['data'] : array();
279
+ $this->post_data = $post_data;
280
+ $this->next_pages = isset( $transient_data['pagination'] ) ? $transient_data['pagination'] : array();
281
+
282
+ if ( isset( $transient_data['atts'] ) ) {
283
+ $this->transient_atts = $transient_data['atts'];
284
+ $this->last_retrieve = $transient_data['last_retrieve'];
285
+ }
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Sets post data from a permanent database backup of feed
291
+ * if it was created
292
+ *
293
+ * @since 2.0/5.0
294
+ * @since 2.0/5.1.2 if backup feed data used, header data also set from backup
295
+ */
296
+ public function maybe_set_post_data_from_backup() {
297
+ $backup_data = get_option( $this->backup_feed_transient_name, false );
298
+
299
+ if ( $backup_data ) {
300
+ $backup_data = json_decode( $backup_data, true );
301
+
302
+ $post_data = isset( $backup_data['data'] ) ? $backup_data['data'] : array();
303
+ $this->post_data = $post_data;
304
+ $this->next_pages = isset( $backup_data['pagination'] ) ? $backup_data['pagination'] : array();
305
+
306
+ if ( isset( $backup_data['atts'] ) ) {
307
+ $this->transient_atts = $backup_data['atts'];
308
+ $this->last_retrieve = $backup_data['last_retrieve'];
309
+ }
310
+
311
+ $this->maybe_set_header_data_from_backup();
312
+
313
+ return true;
314
+ } else {
315
+ $this->add_report( 'no backup post data found' );
316
+
317
+ return false;
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Sets header data from a permanent database backup of feed
323
+ * if it was created
324
+ *
325
+ * @since 2.0/5.0
326
+ */
327
+ public function maybe_set_header_data_from_backup() {
328
+ $backup_header_data = get_option( $this->backup_header_transient_name, false );
329
+
330
+ if ( ! empty( $backup_header_data ) ) {
331
+ $backup_header_data = json_decode( $backup_header_data, true );
332
+ $this->header_data = $backup_header_data;
333
+
334
+ return true;
335
+ } else {
336
+ $this->add_report( 'no backup header data found' );
337
+
338
+ return false;
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Returns recorded image IDs for this post set
344
+ * for use with image resizing
345
+ *
346
+ * @return array
347
+ *
348
+ * @since 2.0/5.0
349
+ */
350
+ public function get_image_ids_post_set() {
351
+ return $this->image_ids_post_set;
352
+ }
353
+
354
+ /**
355
+ * Retrieves data related to resized images from custom
356
+ * tables using either a number, offset, and transient name
357
+ * or the ids of the posts.
358
+ *
359
+ * Retrieving by offset and transient name not used currently
360
+ * but may be needed in future updates.
361
+ *
362
+ * @param array/int $num_or_array_of_ids post ids from the Instagram
363
+ * API
364
+ * @param int $offset number of records to skip
365
+ * @param string $transient_name ID of the feed
366
+ *
367
+ * @return array
368
+ *
369
+ * @since 2.0/5.0
370
+ */
371
+ public static function get_resized_images_source_set( $num_or_array_of_ids, $offset = 0, $transient_name = '' ) {
372
+ global $sb_instagram_posts_manager;
373
+
374
+ if ( $sb_instagram_posts_manager->image_resizing_disabled() ) {
375
+ return array();
376
+ }
377
+
378
+ global $wpdb;
379
+
380
+ $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
381
+ $feeds_posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
382
+
383
+ $feed_id_array = explode( '#', $transient_name );
384
+ $feed_id = $feed_id_array[0];
385
+
386
+ if ( is_array( $num_or_array_of_ids ) ) {
387
+ $ids = $num_or_array_of_ids;
388
+
389
+ $id_string = "'" . implode( "','", $ids ) . "'";
390
+ $results = $wpdb->get_results( $wpdb->prepare( "
391
+ SELECT p.media_id, p.instagram_id, p.aspect_ratio, p.sizes
392
+ FROM $posts_table_name AS p
393
+ INNER JOIN $feeds_posts_table_name AS f ON p.id = f.id
394
+ WHERE f.feed_id = %s
395
+ AND p.instagram_id IN($id_string)
396
+ AND p.images_done = 1", $feed_id ), ARRAY_A );
397
+
398
+ $return = array();
399
+ if ( !empty( $results ) && is_array( $results ) ) {
400
+
401
+ foreach ( $results as $result ) {
402
+ $sizes = maybe_unserialize( $result['sizes'] );
403
+ if ( ! is_array( $sizes ) ) {
404
+ $sizes = array( 'full' => 640 );
405
+ }
406
+ $return[ $result['instagram_id'] ] = array(
407
+ 'id' => $result['media_id'],
408
+ 'ratio' => $result['aspect_ratio'],
409
+ 'sizes' => $sizes
410
+ );
411
+ }
412
+
413
+ }
414
+ } else {
415
+ $num = $num_or_array_of_ids;
416
+
417
+ $results = $wpdb->get_results( $wpdb->prepare( "
418
+ SELECT p.media_id, p.instagram_id, p.aspect_ratio, p.sizes
419
+ FROM $posts_table_name AS p
420
+ INNER JOIN $feeds_posts_table_name AS f ON p.id = f.id
421
+ WHERE f.feed_id = %s
422
+ AND p.images_done = 1
423
+ ORDER BY p.time_stamp
424
+ DESC LIMIT %d, %d", $feed_id, $offset, (int)$num ), ARRAY_A );
425
+
426
+ $return = array();
427
+ if ( !empty( $results ) && is_array( $results ) ) {
428
+
429
+ foreach ( $results as $result ) {
430
+ $sizes = maybe_unserialize( $result['sizes'] );
431
+ if ( ! is_array( $sizes ) ) {
432
+ $sizes = array( 'full' => 640 );
433
+ }
434
+ $return[ $result['instagram_id'] ] = array(
435
+ 'id' => $result['media_id'],
436
+ 'ratio' => $result['aspect_ratio'],
437
+ 'sizes' => $sizes
438
+ );
439
+ }
440
+
441
+ }
442
+ }
443
+
444
+
445
+ return $return;
446
+ }
447
+
448
+ /**
449
+ * The plugin tracks when a post was last requested so only the most
450
+ * recently displayed posts are kept in the database.
451
+ * This function updates the timestamp for a set of posts
452
+ * on the page.
453
+ *
454
+ * @param $array_of_ids
455
+ *
456
+ * @since 2.0/5.0
457
+ */
458
+ public static function update_last_requested( $array_of_ids ) {
459
+ if ( empty( $array_of_ids ) ) {
460
+ return;
461
+ }
462
+
463
+ global $wpdb;
464
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
465
+ $id_string = "'" . implode( "','", $array_of_ids ) . "'";
466
+
467
+ $query = $wpdb->query( $wpdb->prepare( "UPDATE $table_name
468
+ SET last_requested = %s
469
+ WHERE instagram_id IN ({$id_string});", date( 'Y-m-d H:i:s' ) ) );
470
+ }
471
+
472
+ /**
473
+ * Cron caching needs additional data saved in the transient
474
+ * to work properly. This function checks to make sure it's present
475
+ *
476
+ * @return bool
477
+ *
478
+ * @since 2.0/5.0
479
+ */
480
+ public function need_to_start_cron_job() {
481
+ return (( ! empty( $this->post_data ) && ! isset( $this->transient_atts )) || empty( $this->post_data ));
482
+ }
483
+
484
+ /**
485
+ * Checks to see if there are enough posts available to create
486
+ * the current page of the feed
487
+ *
488
+ * @param int $num
489
+ * @param int $offset
490
+ *
491
+ * @return bool
492
+ *
493
+ * @since 2.0/5.0
494
+ */
495
+ public function need_posts( $num, $offset = 0 ) {
496
+ $num_existing_posts = is_array( $this->post_data ) ? count( $this->post_data ) : 0;
497
+ $num_needed_for_page = (int)$num + (int)$offset;
498
+
499
+ ($num_existing_posts < $num_needed_for_page) ? $this->add_report( 'need more posts' ) : $this->add_report( 'have enough posts' );
500
+
501
+ return ($num_existing_posts < $num_needed_for_page);
502
+ }
503
+
504
+ /**
505
+ * Checks to see if there are additional pages available for any of the
506
+ * accounts in the feed and that the max conccurrent api request limit
507
+ * has not been reached
508
+ *
509
+ * @return bool
510
+ *
511
+ * @since 2.0/5.0
512
+ */
513
+ public function can_get_more_posts() {
514
+ $one_type_and_term_has_more_ages = $this->next_pages !== false;
515
+ $max_concurrent_api_calls_not_met = $this->num_api_calls < $this->max_api_calls;
516
+ $max_concurrent_api_calls_not_met ? $this->add_report( 'max conccurrent requests not met' ) : $this->add_report( 'max concurrent met' );
517
+ $one_type_and_term_has_more_ages ? $this->add_report( 'more pages available' ) : $this->add_report( 'no next page' );
518
+
519
+ return ($one_type_and_term_has_more_ages && $max_concurrent_api_calls_not_met);
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', 'custominstagramfeed' )
528
+ * @param array $connected_accounts_for_feed connected account data for the
529
+ * feed types and terms
530
+ *
531
+ * @since 2.0/5.0
532
+ * @since 2.0/5.1 added logic to make a second attempt at an API connection
533
+ * @since 2.0/5.1.2 remote posts only retrieved if API requests are not
534
+ * delayed, terms shuffled if there are more than 5
535
+ * @since 2.2/5.3 added logic to refresh the access token for basic display
536
+ * accounts if needed before using it in an API request
537
+ */
538
+ public function add_remote_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
539
+ $new_post_sets = array();
540
+ $next_pages = $this->next_pages;
541
+ global $sb_instagram_posts_manager;
542
+
543
+ /**
544
+ * Number of posts to retrieve in each API call
545
+ *
546
+ * @param int Minimum number of posts needed in each API request
547
+ * @param array $settings Settings for this feed
548
+ *
549
+ * @since 2.0/5.0
550
+ */
551
+ $num = apply_filters( 'sbi_num_in_request', $settings['minnum'], $settings );
552
+ $num = max( $num, (int)$settings['apinum'] );
553
+ $params = array(
554
+ 'num' => $num
555
+ );
556
+
557
+ $one_successful_connection = false;
558
+ $one_post_found = false;
559
+ $next_page_found = false;
560
+ $one_api_request_delayed = false;
561
+
562
+ foreach ( $feed_types_and_terms as $type => $terms ) {
563
+ if ( is_array( $terms ) && count( $terms ) > 5 ) {
564
+ shuffle( $terms );
565
+ }
566
+ foreach ( $terms as $term_and_params ) {
567
+ $term = $term_and_params['term'];
568
+ $params = array_merge( $params, $term_and_params['params'] );
569
+ $connected_account_for_term = $connected_accounts_for_feed[ $term ];
570
+
571
+ $api_requests_delayed = $sb_instagram_posts_manager->are_current_api_request_delays( $connected_account_for_term['user_id'] );
572
+
573
+ if ( ! $api_requests_delayed
574
+ && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== false) ) {
575
+
576
+ $account_type = isset( $connected_account_for_term['type'] ) ? $connected_account_for_term['type'] : 'personal';
577
+ $skip_connection = false;
578
+
579
+ // basic account access tokens need to be refreshed every 60 days
580
+ // normally done using WP Cron but can be done here as a fail safe
581
+ if ( $account_type === 'basic' ) {
582
+ if ( SB_Instagram_Token_Refresher::refresh_time_has_passed_threshold( $connected_account_for_term )
583
+ && SB_Instagram_Token_Refresher::minimum_time_interval_since_last_attempt_has_passed( $connected_account_for_term ) ) {
584
+ $refresher = new SB_Instagram_Token_Refresher( $connected_account_for_term );
585
+ $refresher->attempt_token_refresh();
586
+ $this->add_report( 'trying to refresh token ' . $term . '_' . $type );
587
+ }
588
+ } elseif( $account_type === 'personal' && sbi_is_after_deprecation_deadline() ) {
589
+ $skip_connection = true;
590
+ }
591
+
592
+ if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
593
+ $next_page_term = $next_pages[ $term . '_' . $type ];
594
+ if ( strpos( $next_page_term, 'https://' ) !== false ) {
595
+ $connection = $this->make_api_connection( $next_page_term );
596
+ } else {
597
+ $params['cursor'] = $next_page_term;
598
+ $connection = $this->make_api_connection( $connected_account_for_term, $type, $params );
599
+ }
600
+ } else {
601
+ $connection = $this->make_api_connection( $connected_account_for_term, $type, $params );
602
+ }
603
+ $this->add_report( 'api call made for ' . $term . ' - ' . $type );
604
+
605
+ if ( ! $skip_connection ) {
606
+ $connection->connect();
607
+ }
608
+ $this->num_api_calls++;
609
+
610
+ if ( ! $skip_connection && ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
611
+ $one_successful_connection = true;
612
+
613
+ $sb_instagram_posts_manager->remove_error( 'connection' );
614
+ $sb_instagram_posts_manager->remove_error( 'api' );
615
+ $sb_instagram_posts_manager->remove_error( 'at_' . $term );
616
+
617
+ $data = $connection->get_data();
618
+
619
+ if ( !$connected_account_for_term['is_valid'] ) {
620
+ $this->add_report( 'clearing invalid token' );
621
+ $this->clear_expired_access_token_notice( $connected_account_for_term );
622
+ }
623
+
624
+ if ( isset( $data[0]['id'] ) ) {
625
+ $one_post_found = true;
626
+
627
+ $post_set = $this->filter_posts( $data, $settings );
628
+
629
+ $new_post_sets[] = $post_set;
630
+ }
631
+
632
+ $next_page = $connection->get_next_page( $type );
633
+ if ( ! empty( $next_page ) ) {
634
+ $next_pages[ $term . '_' . $type ] = $next_page;
635
+ $next_page_found = true;
636
+ } else {
637
+ $next_pages[ $term . '_' . $type ] = false;
638
+ }
639
+ } else {
640
+
641
+ if ( $this->can_try_another_request( $type, $connected_accounts_for_feed[ $term ] ) ) {
642
+ $this->add_report( 'trying other accounts' );
643
+ $i = 0;
644
+ $attempted = array( $connected_accounts_for_feed[ $term ]['user_id'] );
645
+ $success = false;
646
+ $different = true;
647
+ $error = false;
648
+
649
+ while ( $different
650
+ && ! $success
651
+ && $this->can_try_another_request( $type, $connected_accounts_for_feed[ $term ], $i ) ) {
652
+ $different = $this->get_different_connected_account( $type, $attempted );
653
+ $this->add_report( 'trying the account ' . $different['user_id'] );
654
+
655
+ if ( $different ) {
656
+ $connected_accounts_for_feed[ $term ] = $this->get_different_connected_account( $type, $attempted );
657
+ $attempted[] = $connected_accounts_for_feed[ $term ]['user_id'];
658
+ if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
659
+ $connection = $this->make_api_connection( $next_pages[ $term . '_' . $type ] );
660
+ } else {
661
+ $connection = $this->make_api_connection( $connected_accounts_for_feed[ $term ], $type, $params );
662
+ }
663
+ $connection->connect();
664
+ $this->num_api_calls++;
665
+ if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
666
+ $one_successful_connection = true;
667
+
668
+ $sb_instagram_posts_manager->remove_error( 'connection' );
669
+ $sb_instagram_posts_manager->remove_error( 'api' );
670
+ $sb_instagram_posts_manager->remove_error( 'at_' . $term );
671
+
672
+ $data = $connection->get_data();
673
+ if ( isset( $data[0]['id'] ) ) {
674
+ $one_post_found = true;
675
+ $post_set = $this->filter_posts( $data, $settings );
676
+ $new_post_sets[] = $post_set;
677
+ }
678
+ $next_page = $connection->get_next_page( $type );
679
+ if ( ! empty( $next_page ) ) {
680
+ $next_pages[ $term . '_' . $type ] = $next_page;
681
+ $next_page_found = true;
682
+ } else {
683
+ $next_pages[ $term . '_' . $type ] = false;
684
+ }
685
+ } else {
686
+ if ( $connection->is_wp_error() ) {
687
+ $error = $connection->get_wp_error();
688
+ } else {
689
+ $error = $connection->get_data();
690
+ }
691
+ }
692
+ $i++;
693
+ }
694
+ }
695
+
696
+ if ( ! $success && $error ) {
697
+ if ( $connection->is_wp_error() ) {
698
+ SB_Instagram_API_Connect::handle_wp_remote_get_error( $error );
699
+ } else {
700
+ SB_Instagram_API_Connect::handle_instagram_error( $error, $connected_accounts_for_feed[ $term ], $type );
701
+ }
702
+ $next_pages[ $term . '_' . $type ] = false;
703
+ $show_error_message = true;
704
+
705
+ }
706
+ } else {
707
+ if ( $skip_connection ) {
708
+
709
+ } elseif ( $connection->is_wp_error() ) {
710
+ SB_Instagram_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
711
+ } else {
712
+ SB_Instagram_API_Connect::handle_instagram_error( $connection->get_data(), $connected_accounts_for_feed[ $term ], $type );
713
+ }
714
+ $show_error_message = true;
715
+
716
+ $next_pages[ $term . '_' . $type ] = false;
717
+ }
718
+ }
719
+ } elseif ( $api_requests_delayed ) {
720
+ $one_api_request_delayed = true;
721
+
722
+ $this->add_report( 'delaying API request for ' . $term . ' - ' . $type );
723
+ $show_error_message = true;
724
+ }
725
+
726
+ if ( isset( $show_error_message ) ) {
727
+ $error = '';
728
+ if ( $sb_instagram_posts_manager->are_critical_errors() ) {
729
+ $error .= $sb_instagram_posts_manager->get_critical_errors();
730
+ } else {
731
+ $errors = $sb_instagram_posts_manager->get_frontend_errors();
732
+ $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
733
+ $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
734
+ if ( current_user_can( $cap ) ) {
735
+ foreach ( $errors as $error_message ) {
736
+ $error .= $error_message;
737
+ }
738
+ $error .= '<p class="sbi-error-directions"><a href="https://smashballoon.com/instagram-feed/docs/errors/" target="_blank" rel="noopener">' . __( 'Directions on how to resolve this issue.', 'instagram-feed' ) . '</a></p>';
739
+ } else {
740
+ $error = '<p><b>' . sprintf( __( 'Error: API requests are being delayed for this account.', 'instagram-feed' ), $connected_account_for_term['username'] ) . ' ' . __( 'New posts will not be retrieved.', 'instagram-feed' ) . '</b></p>';
741
+ $error .= '<p>' . __( 'Log in as an administrator and view the Instagram Feed settings page for more details.', 'instagram-feed' ) . '</p>';
742
+ }
743
+ }
744
+
745
+ $sb_instagram_posts_manager->add_frontend_error( 'at_' . $connected_account_for_term['username'], $error );
746
+ }
747
+
748
+ }
749
+ }
750
+
751
+ if ( ! $one_successful_connection || ($one_api_request_delayed && empty( $new_post_sets )) ) {
752
+ $this->should_use_backup = true;
753
+ }
754
+ $posts = $this->merge_posts( $new_post_sets, $settings );
755
+
756
+ $posts = $this->sort_posts( $posts, $settings );
757
+
758
+ if ( ! empty( $this->post_data ) && is_array( $this->post_data ) ) {
759
+ $posts = array_merge( $this->post_data, $posts );
760
+ } elseif ( $one_post_found ) {
761
+ $this->one_post_found = true;
762
+ }
763
+
764
+ $this->post_data = $posts;
765
+
766
+ if ( isset( $next_page_found ) && $next_page_found ) {
767
+ $this->next_pages = $next_pages;
768
+ } else {
769
+ $this->next_pages = false;
770
+ }
771
+ }
772
+
773
+ /**
774
+ * Connects to the Instagram API and records returned data
775
+ *
776
+ * @param $settings
777
+ * @param array $feed_types_and_terms organized settings related to feed data
778
+ * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
779
+ * @param array $connected_accounts_for_feed connected account data for the
780
+ * feed types and terms
781
+ *
782
+ * @since 2.0/5.0
783
+ * @since 2.2/5.3 added logic to append bio data from the related
784
+ * connected account if not available in the API response
785
+ */
786
+ public function set_remote_header_data( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
787
+ $first_user = $this->get_first_user( $feed_types_and_terms );
788
+ $this->header_data = false;
789
+ global $sb_instagram_posts_manager;
790
+
791
+ $api_requests_delayed = isset( $connected_accounts_for_feed[ $first_user ]['user_id'] ) ? $sb_instagram_posts_manager->are_current_api_request_delays( $connected_accounts_for_feed[ $first_user ]['user_id'] ) : $sb_instagram_posts_manager->are_current_api_request_delays();
792
+
793
+ if ( isset( $connected_accounts_for_feed[ $first_user ] ) && ! $api_requests_delayed ) {
794
+ $connection = new SB_Instagram_API_Connect( $connected_accounts_for_feed[ $first_user ], 'header', array() );
795
+
796
+ $connection->connect();
797
+
798
+ if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
799
+ $this->header_data = $connection->get_data();
800
+
801
+ $sb_instagram_posts_manager->remove_error( 'connection' );
802
+ $sb_instagram_posts_manager->remove_error( 'api' );
803
+ $sb_instagram_posts_manager->remove_error( 'at_' . $first_user );
804
+
805
+ if ( isset( $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) && $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) {
806
+ $upload = wp_upload_dir();
807
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
808
+
809
+ $full_file_name = $resized_url . $this->header_data['username'] . '.jpg';
810
+ $this->header_data['local_avatar'] = $full_file_name;
811
+ }
812
+ if ( empty( $this->header_data['bio'] )
813
+ && isset( $connected_accounts_for_feed[ $first_user ]['bio'] ) ) {
814
+
815
+ $this->header_data['bio'] = sbi_decode_emoji( $connected_accounts_for_feed[ $first_user ]['bio'] );
816
+ }
817
+ } else {
818
+ if ( $connection->is_wp_error() ) {
819
+ SB_Instagram_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
820
+ } else {
821
+ SB_Instagram_API_Connect::handle_instagram_error( $connection->get_data(), $connected_accounts_for_feed[ $first_user ], 'header' );
822
+ }
823
+ }
824
+ }
825
+ }
826
+
827
+ /**
828
+ * Stores feed data in a transient for a specified time
829
+ *
830
+ * @param int $cache_time
831
+ * @param bool $save_backup
832
+ *
833
+ * @since 2.0/5.0
834
+ * @since 2.0/5.1 duplicate posts removed
835
+ */
836
+ public function cache_feed_data( $cache_time, $save_backup = true ) {
837
+ if ( ! empty( $this->post_data ) || ! empty( $this->next_pages ) ) {
838
+ $this->remove_duplicate_posts();
839
+ $this->trim_posts_to_max();
840
+
841
+ $to_cache = array(
842
+ 'data' => $this->post_data,
843
+ 'pagination' => $this->next_pages
844
+ );
845
+
846
+ set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
847
+
848
+ if ( $save_backup ) {
849
+ update_option( $this->backup_feed_transient_name, wp_json_encode( $to_cache ), false );
850
+ }
851
+ } else {
852
+ $this->add_report( 'no data not caching' );
853
+ }
854
+ }
855
+
856
+ /**
857
+ * Stores feed data with additional data specifically for cron caching
858
+ *
859
+ * @param array $to_cache feed data with additional things like the shortcode
860
+ * settings, when the cache was last requested, when new posts were last retrieved
861
+ * @param int $cache_time how long the cache will last
862
+ * @param bool $save_backup whether or not to also save this as a permanent cache
863
+ *
864
+ * @since 2.0/5.0
865
+ * @since 2.0/5.1 duplicate posts removed, cache set trimmed to a maximum
866
+ */
867
+ public function set_cron_cache( $to_cache, $cache_time, $save_backup = true ) {
868
+ if ( ! empty( $this->post_data )
869
+ || ! empty( $this->next_pages )
870
+ || ! empty( $to_cache['data'] ) ) {
871
+ $this->remove_duplicate_posts();
872
+ $this->trim_posts_to_max();
873
+
874
+ $to_cache['data'] = isset( $to_cache['data'] ) ? $to_cache['data'] : $this->post_data;
875
+ $to_cache['pagination'] = isset( $to_cache['next_pages'] ) ? $to_cache['next_pages'] : $this->next_pages;
876
+ $to_cache['atts'] = isset( $to_cache['atts'] ) ? $to_cache['atts'] : $this->transient_atts;
877
+ $to_cache['last_requested'] = isset( $to_cache['last_requested'] ) ? $to_cache['last_requested'] : time();
878
+ $to_cache['last_retrieve'] = isset( $to_cache['last_retrieve'] ) ? $to_cache['last_retrieve'] : $this->last_retrieve;
879
+
880
+ set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
881
+
882
+ if ( $save_backup ) {
883
+ update_option( $this->backup_feed_transient_name, wp_json_encode( $to_cache ), false );
884
+ }
885
+ } else {
886
+ $this->add_report( 'no data not caching' );
887
+ }
888
+
889
+ }
890
+
891
+ /**
892
+ * Stores header data for a specified time as a transient
893
+ *
894
+ * @param int $cache_time
895
+ * @param bool $save_backup
896
+ *
897
+ * @since 2.0/5.0
898
+ */
899
+ public function cache_header_data( $cache_time, $save_backup = true ) {
900
+ if ( $this->header_data ) {
901
+ set_transient( $this->header_transient_name, wp_json_encode( $this->header_data ), $cache_time );
902
+
903
+ if ( $save_backup ) {
904
+ update_option( $this->backup_header_transient_name, wp_json_encode( $this->header_data ), false );
905
+ }
906
+ }
907
+ }
908
+
909
+ /**
910
+ * Used to randomly trigger an updating of the last requested data for cron caching
911
+ *
912
+ * @return bool
913
+ *
914
+ * @since 2.0/5.0
915
+ */
916
+ public function should_update_last_requested() {
917
+ return (rand( 1, 20 ) === 20);
918
+ }
919
+
920
+ /**
921
+ * Determines if pagination can and should be used based on settings and available feed data
922
+ *
923
+ * @param array $settings
924
+ * @param int $offset
925
+ *
926
+ * @return bool
927
+ *
928
+ * @since 2.0/5.0
929
+ */
930
+ public function should_use_pagination( $settings, $offset = 0 ) {
931
+ if ( $settings['minnum'] < 1 ) {
932
+ return false;
933
+ }
934
+ $posts_available = count( $this->post_data ) - ($offset + $settings['num']);
935
+ $show_loadmore_button_by_settings = ($settings['showbutton'] == 'on' || $settings['showbutton'] == 'true' || $settings['showbutton'] == true ) && $settings['showbutton'] !== 'false';
936
+
937
+ if ( $show_loadmore_button_by_settings ) {
938
+ // used for permanent and whitelist feeds
939
+ if ( $this->feed_is_complete( $settings, $offset ) ) {
940
+ $this->add_report( 'no pagination, feed complete' );
941
+ return false;
942
+ }
943
+ if ( $posts_available > 0 ) {
944
+ $this->add_report( 'do pagination, posts available' );
945
+ return true;
946
+ }
947
+ $pages = $this->next_pages;
948
+
949
+ if ( $pages && ! $this->should_use_backup() ) {
950
+ foreach ( $pages as $page ) {
951
+ if ( ! empty( $page ) ) {
952
+ return true;
953
+ }
954
+ }
955
+ }
956
+
957
+ }
958
+
959
+
960
+ $this->add_report( 'no pagination, no posts available' );
961
+
962
+ return false;
963
+ }
964
+
965
+ /**
966
+ * Generates the HTML for the feed if post data is available. Although it seems
967
+ * some of the variables ar not used they are set here to hide where they
968
+ * come from when used in the feed templates.
969
+ *
970
+ * @param array $settings
971
+ * @param array $atts
972
+ * @param array $feed_types_and_terms organized settings related to feed data
973
+ * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
974
+ * @param array $connected_accounts_for_feed connected account data for the
975
+ * feed types and terms
976
+ *
977
+ * @return false|string
978
+ *
979
+ * @since 2.0/5.0
980
+ */
981
+ public function get_the_feed_html( $settings, $atts, $feed_types_and_terms, $connected_accounts_for_feed ) {
982
+ global $sb_instagram_posts_manager;
983
+
984
+ if ( empty( $this->post_data ) && ! empty( $connected_accounts_for_feed ) && $settings['minnum'] > 0 ) {
985
+ $this->handle_no_posts_found( $settings, $feed_types_and_terms );
986
+ }
987
+ $posts = array_slice( $this->post_data, 0, $settings['minnum'] );
988
+ $header_data = ! empty( $this->header_data ) ? $this->header_data : false;
989
+
990
+ $first_user = ! empty( $feed_types_and_terms['users'][0] ) ? $feed_types_and_terms['users'][0]['term'] : false;
991
+ $first_username = false;
992
+ if ( $first_user ) {
993
+ $first_username = isset( $connected_accounts_for_feed[ $first_user ]['username'] ) ? $connected_accounts_for_feed[ $first_user ]['username'] : $first_user;
994
+ } elseif ( $header_data ) { // in case no connected account for feed
995
+ $first_username = SB_Instagram_Parse::get_username( $header_data );
996
+ } elseif ( isset( $feed_types_and_terms['users'] ) && isset( $this->post_data[0] ) ) { // in case no connected account and no header
997
+ $first_username = SB_Instagram_Parse::get_username( $this->post_data[0] );
998
+ }
999
+ $use_pagination = $this->should_use_pagination( $settings, 0 );
1000
+
1001
+ $feed_id = $this->regular_feed_transient_name;
1002
+ $shortcode_atts = ! empty( $atts ) ? wp_json_encode( $atts ) : '{}';
1003
+
1004
+ $settings['header_outside'] = false;
1005
+ $settings['header_inside'] = false;
1006
+ if ( $header_data && $settings['showheader'] ) {
1007
+ $settings['header_inside'] = true;
1008
+ }
1009
+
1010
+ $other_atts = '';
1011
+
1012
+ $classes = array();
1013
+ if ( empty( $settings['widthresp'] ) || $settings['widthresp'] == 'on' || $settings['widthresp'] == 'true' || $settings['widthresp'] === true ) {
1014
+ if ( $settings['widthresp'] !== 'false' ) {
1015
+ $classes[] = 'sbi_width_resp';
1016
+ }
1017
+ }
1018
+ if ( ! empty( $settings['class'] ) ) {
1019
+ $classes[] = esc_attr( $settings['class'] );
1020
+ }
1021
+ if ( ! empty( $settings['height'] )
1022
+ && (((int)$settings['height'] < 100 && $settings['heightunit'] === '%') || $settings['heightunit'] === 'px') ) {
1023
+ $classes[] = 'sbi_fixed_height';
1024
+ }
1025
+ if ( ! empty( $settings['disablemobile'] )
1026
+ && ($settings['disablemobile'] == 'on' || $settings['disablemobile'] == 'true' || $settings['disablemobile'] == true) ) {
1027
+ if ( $settings['disablemobile'] !== 'false' ) {
1028
+ $classes[] = 'sbi_disable_mobile';
1029
+ }
1030
+ }
1031
+
1032
+ $additional_classes = '';
1033
+ if ( ! empty( $classes ) ) {
1034
+ $additional_classes = ' ' . implode( ' ', $classes );
1035
+ }
1036
+
1037
+ $other_atts = $this->add_other_atts( $other_atts, $settings );
1038
+
1039
+ $flags = array();
1040
+
1041
+ if ( $settings['disable_resize'] || $settings['isgutenberg'] ) {
1042
+ $flags[] = 'resizeDisable';
1043
+ } elseif ( $settings['favor_local'] ) {
1044
+ $flags[] = 'favorLocal';
1045
+ }
1046
+
1047
+ if ( $settings['disable_js_image_loading'] ) {
1048
+ $flags[] = 'imageLoadDisable';
1049
+ }
1050
+ if ( $settings['ajax_post_load'] ) {
1051
+ $flags[] = 'ajaxPostLoad';
1052
+ }
1053
+ if ( isset( $_GET['sbi_debug'] ) ) {
1054
+ $flags[] = 'debug';
1055
+ }
1056
+
1057
+ $ajax_test_status = $sb_instagram_posts_manager->get_ajax_status();
1058
+
1059
+ if ( $sb_instagram_posts_manager->maybe_start_ajax_test() && ! $ajax_test_status['successful'] ) {
1060
+ $flags[] = 'testAjax';
1061
+ }
1062
+
1063
+ if ( ! empty( $flags ) ) {
1064
+ $other_atts .= ' data-sbi-flags="' . implode(',', $flags ) . '"';
1065
+ }
1066
+
1067
+ ob_start();
1068
+ include sbi_get_feed_template_part( 'feed', $settings );
1069
+ $html = ob_get_contents();
1070
+ ob_get_clean();
1071
+
1072
+ if ( $settings['ajaxtheme'] ) {
1073
+ $html .= $this->get_ajax_page_load_html();
1074
+ }
1075
+
1076
+ return $html;
1077
+ }
1078
+
1079
+ /**
1080
+ * Generates HTML for individual sbi_item elements
1081
+ *
1082
+ * @param array $settings
1083
+ * @param int $offset
1084
+ * @param array $feed_types_and_terms organized settings related to feed data
1085
+ * (ex. 'user' => array( 'smashballoon', 'custominstagramfeed' )
1086
+ * @param array $connected_accounts_for_feed connected account data for the
1087
+ * feed types and terms
1088
+ *
1089
+ * @return false|string
1090
+ *
1091
+ * @since 2.0/5.0
1092
+ */
1093
+ public function get_the_items_html( $settings, $offset, $feed_types_and_terms, $connected_accounts_for_feed ) {
1094
+ if ( empty( $this->post_data ) ) {
1095
+ ob_start();
1096
+ $html = ob_get_contents();
1097
+ ob_get_clean(); ?>
1098
+ <p><?php _e( 'No posts found.', 'instagram-feed' ); ?></p>
1099
+ <?php
1100
+ $html = ob_get_contents();
1101
+ ob_get_clean();
1102
+ return $html;
1103
+ }
1104
+
1105
+ $posts = array_slice( $this->post_data, $offset, $settings['num'] );
1106
+
1107
+ ob_start();
1108
+
1109
+ $this->posts_loop( $posts, $settings, $offset );
1110
+
1111
+ $html = ob_get_contents();
1112
+ ob_get_clean();
1113
+
1114
+ return $html;
1115
+ }
1116
+
1117
+ /**
1118
+ * Overwritten in the Pro version
1119
+ *
1120
+ * @return object
1121
+ */
1122
+ public function make_api_connection( $connected_account_or_page, $type = NULL, $params = NULL ) {
1123
+ return new SB_Instagram_API_Connect( $connected_account_or_page, $type, $params );
1124
+ }
1125
+
1126
+ /**
1127
+ * When the feed is loaded with AJAX, the JavaScript for the plugin
1128
+ * needs to be triggered again. This function is a workaround that adds
1129
+ * the file and settings to the page whenever the feed is generated.
1130
+ *
1131
+ * @return string
1132
+ *
1133
+ * @since 2.0/5.0
1134
+ */
1135
+ public static function get_ajax_page_load_html() {
1136
+ if ( SB_Instagram_Blocks::is_gb_editor() ) {
1137
+ return '';
1138
+ }
1139
+ $sbi_options = sbi_get_database_settings();
1140
+ $font_method = isset( $sbi_options['sbi_font_method'] ) ? $sbi_options['sbi_font_method'] : 'svg';
1141
+ $upload = wp_upload_dir();
1142
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
1143
+
1144
+ $js_options = array(
1145
+ 'font_method' => $font_method,
1146
+ 'placeholder' => trailingslashit( SBI_PLUGIN_URL ) . 'img/placeholder.png',
1147
+ 'resized_url' => $resized_url
1148
+ );
1149
+
1150
+ $encoded_options = wp_json_encode( $js_options );
1151
+
1152
+ $js_option_html = '<script type="text/javascript">var sb_instagram_js_options = ' . $encoded_options . ';</script>';
1153
+ $js_option_html .= "<script type='text/javascript' src='" . trailingslashit( SBI_PLUGIN_URL ) . 'js/sb-instagram.min.js?ver=' . SBIVER . "'></script>";
1154
+
1155
+ return $js_option_html;
1156
+ }
1157
+
1158
+ /**
1159
+ * Overwritten in the Pro version
1160
+ *
1161
+ * @param $feed_types_and_terms
1162
+ *
1163
+ * @return string
1164
+ *
1165
+ * @since 2.1/5.2
1166
+ */
1167
+ public function get_first_user( $feed_types_and_terms ) {
1168
+ if ( isset( $feed_types_and_terms['users'][0] ) ) {
1169
+ return $feed_types_and_terms['users'][0]['term'];
1170
+ } else {
1171
+ return '';
1172
+ }
1173
+ }
1174
+
1175
+ /**
1176
+ * Adds recorded strings to an array
1177
+ *
1178
+ * @param $to_add
1179
+ *
1180
+ * @since 2.0/5.0
1181
+ */
1182
+ public function add_report( $to_add ) {
1183
+ $this->report[] = $to_add;
1184
+ }
1185
+
1186
+ /**
1187
+ * @return array
1188
+ *
1189
+ * @since 2.0/5.0
1190
+ */
1191
+ public function get_report() {
1192
+ return $this->report;
1193
+ }
1194
+
1195
+ /**
1196
+ * Additional options/settings added to the main div
1197
+ * for the feed
1198
+ *
1199
+ * Overwritten in the Pro version
1200
+ *
1201
+ * @param $other_atts
1202
+ * @param $settings
1203
+ *
1204
+ * @return string
1205
+ */
1206
+ protected function add_other_atts( $other_atts, $settings ) {
1207
+ return '';
1208
+ }
1209
+
1210
+ /**
1211
+ * Used for filtering a single API request worth of posts
1212
+ *
1213
+ * Overwritten in the Pro version
1214
+ *
1215
+ * @param array $post_set a single set of post data from the api
1216
+ *
1217
+ * @return mixed|array
1218
+ *
1219
+ * @since 2.0/5.0
1220
+ */
1221
+ protected function filter_posts( $post_set, $settings = array() ) {
1222
+ // array_unique( $post_set, SORT_REGULAR);
1223
+
1224
+ return $post_set;
1225
+ }
1226
+
1227
+ protected function handle_no_posts_found( $settings = array(), $feed_types_and_terms = array() ) {
1228
+ global $sb_instagram_posts_manager;
1229
+
1230
+ $error = '<p><b>' . __( 'Error: No posts found.', 'instagram-feed' ) . '</b>';
1231
+ $error .= '<p>' . __( 'Make sure this account has posts available on instagram.com.', 'instagram-feed' ) . '</p>';
1232
+ $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
1233
+ $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
1234
+ if ( current_user_can( $cap ) ) {
1235
+ $error .= '<p><a href="https://smashballoon.com/instagram-feed/docs/errors/">' . __( 'Click here to troubleshoot', 'instagram-feed' ) . '</a></p>';
1236
+ }
1237
+
1238
+ $sb_instagram_posts_manager->add_frontend_error( 'noposts', $error );
1239
+ }
1240
+
1241
+ protected function remove_duplicate_posts() {
1242
+ $posts = $this->post_data;
1243
+ $ids_in_feed = array();
1244
+ $non_duplicate_posts = array();
1245
+ $removed = array();
1246
+
1247
+ foreach ( $posts as $post ) {
1248
+ $post_id = SB_Instagram_Parse::get_post_id( $post );
1249
+ if ( ! in_array( $post_id, $ids_in_feed, true ) ) {
1250
+ $ids_in_feed[] = $post_id;
1251
+ $non_duplicate_posts[] = $post;
1252
+ } else {
1253
+ $removed[] = $post_id;
1254
+ }
1255
+ }
1256
+
1257
+ $this->add_report( 'removed duplicates: ' . implode(', ', $removed ) );
1258
+ $this->set_post_data( $non_duplicate_posts );
1259
+ }
1260
+
1261
+ /**
1262
+ * Used for limiting the cache size
1263
+ *
1264
+ * @since 2.0/5.1.1
1265
+ */
1266
+ protected function trim_posts_to_max() {
1267
+ if ( ! is_array( $this->post_data ) ) {
1268
+ return;
1269
+ }
1270
+
1271
+ $max = apply_filters( 'sbi_max_cache_size', 500 );
1272
+ $this->set_post_data( array_slice( $this->post_data , 0, $max ) );
1273
+
1274
+ }
1275
+
1276
+ /**
1277
+ * Used for permanent feeds or white list feeds to
1278
+ * stop pagination if all posts are already added
1279
+ *
1280
+ * Overwritten in the Pro version
1281
+ *
1282
+ * @param array $settings
1283
+ * @param int $offset
1284
+ *
1285
+ * @return bool
1286
+ *
1287
+ * @since 2.0/5.0
1288
+ */
1289
+ protected function feed_is_complete( $settings, $offset = 0 ) {
1290
+ return false;
1291
+ }
1292
+
1293
+ /**
1294
+ * @param $connected_account_for_term
1295
+ *
1296
+ * @since 2.0/5.1.2
1297
+ */
1298
+ private function clear_expired_access_token_notice( $connected_account_for_term ) {
1299
+ $sbi_options = get_option( 'sb_instagram_settings' );
1300
+ $ca_to_save = isset( $sbi_options['connected_accounts'] ) ? $sbi_options['connected_accounts'] : array();
1301
+
1302
+ if ( ! empty( $ca_to_save ) && ! empty( $connected_account_for_term ) ) {
1303
+
1304
+ foreach ( $ca_to_save as $account ) {
1305
+ if ( $connected_account_for_term['access_token'] === $account['access_token'] ) {
1306
+ $ca_to_save[ $account['user_id'] ]['is_valid'] = true;
1307
+ }
1308
+ }
1309
+
1310
+ $sbi_options['connected_accounts'] = $ca_to_save;
1311
+
1312
+ update_option( 'sb_instagram_settings', $sbi_options );
1313
+ }
1314
+ }
1315
+
1316
+ /**
1317
+ * Iterates through post data and tracks the index of the current post.
1318
+ * The actual post ids of the posts are stored in an array so the plugin
1319
+ * can search for local images that may be available.
1320
+ *
1321
+ * @param array $posts final filtered post data for the feed
1322
+ * @param array $settings
1323
+ * @param int $offset
1324
+ *
1325
+ * @since 2.0/5.0
1326
+ */
1327
+ private function posts_loop( $posts, $settings, $offset = 0 ) {
1328
+
1329
+ $image_ids = array();
1330
+ $post_index = $offset;
1331
+ $icon_type = $settings['font_method'];
1332
+ $resized_images = $this->get_resized_images();
1333
+
1334
+ foreach ( $posts as $post ) {
1335
+ $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
1336
+ $account_type = SB_Instagram_Parse::get_account_type( $post );
1337
+ include sbi_get_feed_template_part( 'item', $settings );
1338
+ $post_index++;
1339
+ }
1340
+
1341
+ $this->image_ids_post_set = $image_ids;
1342
+ }
1343
+
1344
+ /**
1345
+ * Uses array of API request results and merges them based on how
1346
+ * the feed should be sorted. Mixed feeds are always sorted alternating
1347
+ * since there is no post date for hashtag feeds.
1348
+ *
1349
+ * @param array $post_sets an array of single API request worth
1350
+ * of posts
1351
+ * @param array $settings
1352
+ *
1353
+ * @return array
1354
+ *
1355
+ * @since 2.0/5.0
1356
+ */
1357
+ private function merge_posts( $post_sets, $settings ) {
1358
+ $merged_posts = array();
1359
+ if ( $settings['sortby'] === 'alternate' ) {
1360
+ // don't bother merging posts if there is only one post set
1361
+ if ( isset( $post_sets[1] ) ) {
1362
+ $min_cycles = max( 1, (int)$settings['num'] );
1363
+ for( $i = 0; $i <= $min_cycles; $i++ ) {
1364
+ foreach ( $post_sets as $post_set ) {
1365
+ if ( isset( $post_set[ $i ] ) && isset( $post_set[ $i ]['id'] ) ) {
1366
+ $merged_posts[] = $post_set[ $i ];
1367
+ }
1368
+ }
1369
+ }
1370
+ } else {
1371
+ $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1372
+ }
1373
+ } elseif ( $settings['sortby'] === 'api' ) {
1374
+ if ( isset( $post_sets[0] ) ) {
1375
+ foreach ( $post_sets as $post_set ) {
1376
+ $merged_posts = array_merge( $merged_posts, $post_set );
1377
+ }
1378
+ }
1379
+ } else {
1380
+ // don't bother merging posts if there is only one post set
1381
+ if ( isset( $post_sets[1] ) ) {
1382
+ foreach ( $post_sets as $post_set ) {
1383
+ if ( isset( $post_set[0]['id'] ) ) {
1384
+ $merged_posts = array_merge( $merged_posts, $post_set );
1385
+ }
1386
+ }
1387
+ } else {
1388
+ $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1389
+ }
1390
+ }
1391
+
1392
+
1393
+ return $merged_posts;
1394
+ }
1395
+
1396
+ /**
1397
+ * Sorts a post set based on sorting settings. Sorting by "alternate"
1398
+ * is done when merging posts for efficiency's sake so the post set is
1399
+ * just returned as it is.
1400
+ *
1401
+ * @param array $post_set
1402
+ * @param array $settings
1403
+ *
1404
+ * @return mixed|array
1405
+ *
1406
+ * @since 2.0/5.0
1407
+ * @since 2.1/5.2 added filter hook for applying custom sorting
1408
+ */
1409
+ private function sort_posts( $post_set, $settings ) {
1410
+ if ( empty( $post_set ) ) {
1411
+ return $post_set;
1412
+ }
1413
+
1414
+ // sorting done with "merge_posts" to be more efficient
1415
+ if ( $settings['sortby'] === 'alternate' || $settings['sortby'] === 'api' ) {
1416
+ $return_post_set = $post_set;
1417
+ } elseif ( $settings['sortby'] === 'random' ) {
1418
+ /*
1419
+ * randomly selects posts in a random order. Cache saves posts
1420
+ * in this random order so paginating does not cause some posts to show up
1421
+ * twice or not at all
1422
+ */
1423
+ usort($post_set, 'sbi_rand_sort' );
1424
+ $return_post_set = $post_set;
1425
+
1426
+ } else {
1427
+ // compares posted on dates of posts
1428
+ usort($post_set, 'sbi_date_sort' );
1429
+ $return_post_set = $post_set;
1430
+ }
1431
+
1432
+ /**
1433
+ * Apply a custom sorting of posts
1434
+ *
1435
+ * @param array $return_post_set Ordered set of filtered posts
1436
+ * @param array $settings Settings for this feed
1437
+ *
1438
+ * @since 2.1/5.2
1439
+ */
1440
+
1441
+ return apply_filters( 'sbi_sorted_posts', $return_post_set, $settings );
1442
+ }
1443
+
1444
+ /**
1445
+ * Can trigger a second attempt at getting posts from the API
1446
+ *
1447
+ * Overwritten in the Pro version
1448
+ *
1449
+ * @param string $type
1450
+ * @param array $connected_account_with_error
1451
+ * @param int $attempts
1452
+ *
1453
+ * @return bool
1454
+ *
1455
+ * @since 2.0/5.1.1
1456
+ */
1457
+ protected function can_try_another_request( $type, $connected_account_with_error, $attempts = 0 ) {
1458
+ return false;
1459
+ }
1460
+
1461
+ /**
1462
+ * returns a second connected account if it exists
1463
+ *
1464
+ * Overwritten in the Pro version
1465
+ *
1466
+ * @param string $type
1467
+ * @param array $attempted_connected_accounts
1468
+ *
1469
+ * @return bool
1470
+ *
1471
+ * @since 2.0/5.1.1
1472
+ */
1473
+ protected function get_different_connected_account( $type, $attempted_connected_accounts ) {
1474
+ return false;
1475
+ }
1476
+
1477
  }
inc/class-sb-instagram-parse.php CHANGED
@@ -1,314 +1,314 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Parse
4
- *
5
- * The structure of the data coming from the Instagram API is different
6
- * for the old API vs the new graph API. This class is used to parse
7
- * whatever structure the data has as well as use this to generate
8
- * parts of the html used for image sources.
9
- *
10
- * @since 2.0/5.0
11
- */
12
-
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- die( '-1' );
15
- }
16
-
17
- class SB_Instagram_Parse
18
- {
19
- /**
20
- * @param $post array
21
- *
22
- * @return mixed
23
- *
24
- * @since 2.0/5.0
25
- */
26
- public static function get_post_id( $post ) {
27
- return $post['id'];
28
- }
29
-
30
- /**
31
- * @param $post array
32
- *
33
- * @return string
34
- *
35
- * @since 2.0/5.0
36
- */
37
- public static function get_account_type( $post ) {
38
- if (isset( $post['media_type'] ) ) {
39
- return 'business';
40
- } else {
41
- return 'personal';
42
- }
43
- }
44
-
45
- /**
46
- * @param $post array
47
- *
48
- * @return false|int
49
- *
50
- * @since 2.0/5.0
51
- */
52
- public static function get_timestamp( $post ) {
53
- $timestamp = 0;
54
- if ( isset( $post['created_time'] ) ) {
55
- $timestamp = $post['created_time'];
56
- } else if ( isset( $post['timestamp'] ) ) {
57
- // some date formatting functions have trouble with the "T", "+", and extra zeroes added by Instagram
58
- $remove_plus = trim( str_replace( array('T', '+', ' 0000' ), ' ', $post['timestamp'] ) );
59
- $timestamp = strtotime( $remove_plus );
60
- }
61
-
62
- return $timestamp;
63
- }
64
-
65
- /**
66
- * @param $post array
67
- *
68
- * @return string
69
- *
70
- * @since 2.0/5.0
71
- */
72
- public static function get_media_type( $post ) {
73
- if ( isset( $post['type'] ) ) {
74
- return $post['type'];
75
- }
76
-
77
- return strtolower( str_replace( '_ALBUM','', $post['media_type'] ) );
78
- }
79
-
80
- /**
81
- * @param $post array
82
- *
83
- * @return mixed
84
- *
85
- * @since 2.0/5.0
86
- */
87
- public static function get_permalink( $post ) {
88
- if ( isset( $post['permalink'] ) ) {
89
- return $post['permalink'];
90
- }
91
-
92
- return $post['link'];
93
- }
94
-
95
- /**
96
- * @param array $post
97
- * @param string $resolution
98
- *
99
- * @return string
100
- *
101
- * @since 2.0/5.0
102
- */
103
- public static function get_media_url( $post, $resolution = 'lightbox' ) {
104
- $account_type = isset( $post['images'] ) ? 'personal' : 'business';
105
-
106
- if ( $account_type === 'personal' ) {
107
- return $post['images']['standard_resolution']['url'];
108
- } else {
109
- if ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') {
110
- if ( isset( $post['thumbnail_url'] ) ) {
111
- return $post['thumbnail_url'];
112
- } elseif ( $post['media_type'] === 'CAROUSEL_ALBUM' && isset( $post['media_url'] ) ) {
113
- return $post['media_url'];
114
- } else {
115
- $permalink = SB_Instagram_Parse::fix_permalink( SB_Instagram_Parse::get_permalink( $post ) );
116
-
117
- return $permalink . 'media?size=l';
118
- }
119
- } else {
120
- return $post['media_url'];
121
- }
122
- }
123
-
124
- }
125
-
126
- /**
127
- * Uses the existing data for the indvidual instagram post to
128
- * set the best image sources for each resolution size. Due to
129
- * random bugs or just how the API works, different post types
130
- * need special treatment.
131
- *
132
- * @param array $post
133
- * @param array $resized_images
134
- *
135
- * @return array
136
- *
137
- * @since 2.0/5.0
138
- * @since 2.1.3/5.2.3 added 'd' element as a default backup from the API
139
- */
140
- public static function get_media_src_set( $post, $resized_images = array() ) {
141
- $media_urls = array(
142
- 'd' => SB_Instagram_Parse::get_media_url( $post ),
143
- '150' => '',
144
- '320' => '',
145
- '640' => ''
146
- );
147
- $account_type = isset( $post['images'] ) ? 'personal' : 'business';
148
-
149
-
150
- if ( $account_type === 'personal' ) {
151
- $media_urls['150'] = $post['images']['thumbnail']['url'];
152
- $media_urls['320'] = $post['images']['low_resolution']['url'];
153
- $media_urls['640'] = $post['images']['standard_resolution']['url'];
154
- } else {
155
- $post_id = SB_Instagram_Parse::get_post_id( $post );
156
-
157
- $permalink = SB_Instagram_Parse::fix_permalink( SB_Instagram_Parse::get_permalink( $post ) );
158
-
159
- if ( ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') && ($media_urls['640'] === '' || $media_urls['640'] === 'video' || $media_urls['640'] === 'pending')) {
160
- $media_urls['640'] = $permalink . 'media?size=l';
161
- } else {
162
- $media_urls['640'] = $post['media_url'];
163
- }
164
- $media_urls['150'] = $permalink . 'media?size=t';
165
- $media_urls['320'] = $permalink . 'media?size=m';
166
-
167
- // use resized images if exists
168
- if ( isset( $resized_images[ $post_id ]['id'] )
169
- && $resized_images[ $post_id ]['id'] !== 'pending'
170
- && $resized_images[ $post_id ]['id'] !== 'video'
171
- && $resized_images[ $post_id ]['id'] !== 'error' ) {
172
- if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
173
- $media_urls['640'] = $resized_images[ $post_id ]['id'];
174
- }
175
- if ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
176
- $media_urls['320'] = $resized_images[ $post_id ]['id'];
177
- }
178
- }
179
-
180
- }
181
-
182
- return $media_urls;
183
- }
184
-
185
- /**
186
- * A default can be set in the case that the user doesn't use captions
187
- * for posts as this is also used as the alt text for the image.
188
- *
189
- * @param $post
190
- * @param string $default
191
- *
192
- * @return string
193
- *
194
- * @since 2.0/5.0
195
- */
196
- public static function get_caption( $post, $default = '' ) {
197
- $caption = $default;
198
- if ( ! empty( $post['caption'] ) && ! is_array( $post['caption'] ) ) {
199
- $caption = $post['caption'];
200
- } elseif ( ! empty( $post['caption']['text'] ) ) {
201
- $caption = $post['caption']['text'];
202
- }
203
-
204
- return $caption;
205
- }
206
-
207
- /**
208
- * @param array $header_data
209
- *
210
- * @return string
211
- *
212
- * @since 2.0/5.0
213
- */
214
- public static function get_username( $header_data ) {
215
- if ( isset( $header_data['username'] ) ) {
216
- return $header_data['username'];
217
- } elseif ( isset( $header_data['user'] ) ) {
218
- return $header_data['user']['username'];
219
- } elseif ( isset( $header_data['data'] ) ) {
220
- return $header_data['data']['username'];
221
- }
222
- return '';
223
- }
224
-
225
- /**
226
- * @param array $header_data
227
- * @param array $settings
228
- *
229
- * @return string
230
- *
231
- * @since 2.0/5.0
232
- * @since 2.2/5.3 added support for a custom avatar in settings
233
- */
234
- public static function get_avatar( $header_data, $settings = array( 'favor_local' => false ) ) {
235
- if ( ! empty( $settings['customavatar'] ) ) {
236
- return $settings['customavatar'];
237
- } elseif ( ! empty( $header_data['local_avatar'] ) ) {
238
- return $header_data['local_avatar'];
239
- } else {
240
- if ( isset( $header_data['profile_picture'] ) ) {
241
- return $header_data['profile_picture'];
242
- } elseif ( isset( $header_data['profile_picture_url'] ) ) {
243
- return $header_data['profile_picture_url'];
244
- } elseif ( isset( $header_data['user'] ) ) {
245
- return $header_data['user']['profile_picture'];
246
- } elseif ( isset( $header_data['data'] ) ) {
247
- return $header_data['data']['profile_picture'];
248
- }
249
- }
250
-
251
- return '';
252
- }
253
-
254
- /**
255
- * The full name attached to the user account
256
- *
257
- * @param array $header_data
258
- *
259
- * @return string
260
- *
261
- * @since 2.0/5.0
262
- */
263
- public static function get_name( $header_data ) {
264
- if ( isset( $header_data['name'] ) ) {
265
- return $header_data['name'];
266
- } elseif ( isset( $header_data['data'] ) ) {
267
- return $header_data['data']['full_name'];
268
- }
269
- return '';
270
- }
271
-
272
- /**
273
- * Account bio/description used in header
274
- *
275
- * @param $header_data
276
- *
277
- * @return string
278
- *
279
- * @since 2.0.1/5.0
280
- * @since 2.2/5.3 added support for a custom bio in settings
281
- */
282
- public static function get_bio( $header_data, $settings = array() ) {
283
- if ( ! empty( $settings['custombio'] ) ) {
284
- return $settings['custombio'];
285
- } elseif ( isset( $header_data['data']['bio'] ) ) {
286
- return $header_data['data']['bio'];
287
- } elseif ( isset( $header_data['bio'] ) ){
288
- return $header_data['bio'];
289
- } elseif ( isset( $header_data['biography'] ) ){
290
- return $header_data['biography'];
291
- }
292
- return '';
293
- }
294
-
295
- /**
296
- * There seems to be occasional bugs with the Instagram API
297
- * and permalinks. This corrects it.
298
- *
299
- * @param string $permalink
300
- *
301
- * @return string
302
- *
303
- * @since 2.0/5.0
304
- */
305
- protected static function fix_permalink( $permalink ) {
306
- if ( substr_count( $permalink, '/' ) > 5 ) {
307
- $permalink_array = explode( '/', $permalink );
308
- $perm_id = $permalink_array[ count( $permalink_array ) - 2 ];
309
- $permalink = 'https://www.instagram.com/p/' . $perm_id . '/';
310
- }
311
-
312
- return $permalink;
313
- }
314
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Parse
4
+ *
5
+ * The structure of the data coming from the Instagram API is different
6
+ * for the old API vs the new graph API. This class is used to parse
7
+ * whatever structure the data has as well as use this to generate
8
+ * parts of the html used for image sources.
9
+ *
10
+ * @since 2.0/5.0
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ die( '-1' );
15
+ }
16
+
17
+ class SB_Instagram_Parse
18
+ {
19
+ /**
20
+ * @param $post array
21
+ *
22
+ * @return mixed
23
+ *
24
+ * @since 2.0/5.0
25
+ */
26
+ public static function get_post_id( $post ) {
27
+ return $post['id'];
28
+ }
29
+
30
+ /**
31
+ * @param $post array
32
+ *
33
+ * @return string
34
+ *
35
+ * @since 2.0/5.0
36
+ */
37
+ public static function get_account_type( $post ) {
38
+ if (isset( $post['media_type'] ) ) {
39
+ return 'business';
40
+ } else {
41
+ return 'personal';
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @param $post array
47
+ *
48
+ * @return false|int
49
+ *
50
+ * @since 2.0/5.0
51
+ */
52
+ public static function get_timestamp( $post ) {
53
+ $timestamp = 0;
54
+ if ( isset( $post['created_time'] ) ) {
55
+ $timestamp = $post['created_time'];
56
+ } else if ( isset( $post['timestamp'] ) ) {
57
+ // some date formatting functions have trouble with the "T", "+", and extra zeroes added by Instagram
58
+ $remove_plus = trim( str_replace( array('T', '+', ' 0000' ), ' ', $post['timestamp'] ) );
59
+ $timestamp = strtotime( $remove_plus );
60
+ }
61
+
62
+ return $timestamp;
63
+ }
64
+
65
+ /**
66
+ * @param $post array
67
+ *
68
+ * @return string
69
+ *
70
+ * @since 2.0/5.0
71
+ */
72
+ public static function get_media_type( $post ) {
73
+ if ( isset( $post['type'] ) ) {
74
+ return $post['type'];
75
+ }
76
+
77
+ return strtolower( str_replace( '_ALBUM','', $post['media_type'] ) );
78
+ }
79
+
80
+ /**
81
+ * @param $post array
82
+ *
83
+ * @return mixed
84
+ *
85
+ * @since 2.0/5.0
86
+ */
87
+ public static function get_permalink( $post ) {
88
+ if ( isset( $post['permalink'] ) ) {
89
+ return $post['permalink'];
90
+ }
91
+
92
+ return $post['link'];
93
+ }
94
+
95
+ /**
96
+ * @param array $post
97
+ * @param string $resolution
98
+ *
99
+ * @return string
100
+ *
101
+ * @since 2.0/5.0
102
+ */
103
+ public static function get_media_url( $post, $resolution = 'lightbox' ) {
104
+ $account_type = isset( $post['images'] ) ? 'personal' : 'business';
105
+
106
+ if ( $account_type === 'personal' ) {
107
+ return $post['images']['standard_resolution']['url'];
108
+ } else {
109
+ if ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') {
110
+ if ( isset( $post['thumbnail_url'] ) ) {
111
+ return $post['thumbnail_url'];
112
+ } elseif ( $post['media_type'] === 'CAROUSEL_ALBUM' && isset( $post['media_url'] ) ) {
113
+ return $post['media_url'];
114
+ } else {
115
+ $permalink = SB_Instagram_Parse::fix_permalink( SB_Instagram_Parse::get_permalink( $post ) );
116
+
117
+ return $permalink . 'media?size=l';
118
+ }
119
+ } else {
120
+ return $post['media_url'];
121
+ }
122
+ }
123
+
124
+ }
125
+
126
+ /**
127
+ * Uses the existing data for the indvidual instagram post to
128
+ * set the best image sources for each resolution size. Due to
129
+ * random bugs or just how the API works, different post types
130
+ * need special treatment.
131
+ *
132
+ * @param array $post
133
+ * @param array $resized_images
134
+ *
135
+ * @return array
136
+ *
137
+ * @since 2.0/5.0
138
+ * @since 2.1.3/5.2.3 added 'd' element as a default backup from the API
139
+ */
140
+ public static function get_media_src_set( $post, $resized_images = array() ) {
141
+ $media_urls = array(
142
+ 'd' => SB_Instagram_Parse::get_media_url( $post ),
143
+ '150' => '',
144
+ '320' => '',
145
+ '640' => ''
146
+ );
147
+ $account_type = isset( $post['images'] ) ? 'personal' : 'business';
148
+
149
+
150
+ if ( $account_type === 'personal' ) {
151
+ $media_urls['150'] = $post['images']['thumbnail']['url'];
152
+ $media_urls['320'] = $post['images']['low_resolution']['url'];
153
+ $media_urls['640'] = $post['images']['standard_resolution']['url'];
154
+ } else {
155
+ $post_id = SB_Instagram_Parse::get_post_id( $post );
156
+
157
+ $permalink = SB_Instagram_Parse::fix_permalink( SB_Instagram_Parse::get_permalink( $post ) );
158
+
159
+ if ( ($post['media_type'] === 'CAROUSEL_ALBUM' || $post['media_type'] === 'VIDEO') && ($media_urls['640'] === '' || $media_urls['640'] === 'video' || $media_urls['640'] === 'pending')) {
160
+ $media_urls['640'] = $permalink . 'media?size=l';
161
+ } else {
162
+ $media_urls['640'] = $post['media_url'];
163
+ }
164
+ $media_urls['150'] = $permalink . 'media?size=t';
165
+ $media_urls['320'] = $permalink . 'media?size=m';
166
+
167
+ // use resized images if exists
168
+ if ( isset( $resized_images[ $post_id ]['id'] )
169
+ && $resized_images[ $post_id ]['id'] !== 'pending'
170
+ && $resized_images[ $post_id ]['id'] !== 'video'
171
+ && $resized_images[ $post_id ]['id'] !== 'error' ) {
172
+ if ( isset( $resized_images[ $post_id ]['sizes']['full'] ) ) {
173
+ $media_urls['640'] = $resized_images[ $post_id ]['id'];
174
+ }
175
+ if ( isset( $resized_images[ $post_id ]['sizes']['low'] ) ) {
176
+ $media_urls['320'] = $resized_images[ $post_id ]['id'];
177
+ }
178
+ }
179
+
180
+ }
181
+
182
+ return $media_urls;
183
+ }
184
+
185
+ /**
186
+ * A default can be set in the case that the user doesn't use captions
187
+ * for posts as this is also used as the alt text for the image.
188
+ *
189
+ * @param $post
190
+ * @param string $default
191
+ *
192
+ * @return string
193
+ *
194
+ * @since 2.0/5.0
195
+ */
196
+ public static function get_caption( $post, $default = '' ) {
197
+ $caption = $default;
198
+ if ( ! empty( $post['caption'] ) && ! is_array( $post['caption'] ) ) {
199
+ $caption = $post['caption'];
200
+ } elseif ( ! empty( $post['caption']['text'] ) ) {
201
+ $caption = $post['caption']['text'];
202
+ }
203
+
204
+ return $caption;
205
+ }
206
+
207
+ /**
208
+ * @param array $header_data
209
+ *
210
+ * @return string
211
+ *
212
+ * @since 2.0/5.0
213
+ */
214
+ public static function get_username( $header_data ) {
215
+ if ( isset( $header_data['username'] ) ) {
216
+ return $header_data['username'];
217
+ } elseif ( isset( $header_data['user'] ) ) {
218
+ return $header_data['user']['username'];
219
+ } elseif ( isset( $header_data['data'] ) ) {
220
+ return $header_data['data']['username'];
221
+ }
222
+ return '';
223
+ }
224
+
225
+ /**
226
+ * @param array $header_data
227
+ * @param array $settings
228
+ *
229
+ * @return string
230
+ *
231
+ * @since 2.0/5.0
232
+ * @since 2.2/5.3 added support for a custom avatar in settings
233
+ */
234
+ public static function get_avatar( $header_data, $settings = array( 'favor_local' => false ) ) {
235
+ if ( ! empty( $settings['customavatar'] ) ) {
236
+ return $settings['customavatar'];
237
+ } elseif ( ! empty( $header_data['local_avatar'] ) ) {
238
+ return $header_data['local_avatar'];
239
+ } else {
240
+ if ( isset( $header_data['profile_picture'] ) ) {
241
+ return $header_data['profile_picture'];
242
+ } elseif ( isset( $header_data['profile_picture_url'] ) ) {
243
+ return $header_data['profile_picture_url'];
244
+ } elseif ( isset( $header_data['user'] ) ) {
245
+ return $header_data['user']['profile_picture'];
246
+ } elseif ( isset( $header_data['data'] ) ) {
247
+ return $header_data['data']['profile_picture'];
248
+ }
249
+ }
250
+
251
+ return '';
252
+ }
253
+
254
+ /**
255
+ * The full name attached to the user account
256
+ *
257
+ * @param array $header_data
258
+ *
259
+ * @return string
260
+ *
261
+ * @since 2.0/5.0
262
+ */
263
+ public static function get_name( $header_data ) {
264
+ if ( isset( $header_data['name'] ) ) {
265
+ return $header_data['name'];
266
+ } elseif ( isset( $header_data['data'] ) ) {
267
+ return $header_data['data']['full_name'];
268
+ }
269
+ return '';
270
+ }
271
+
272
+ /**
273
+ * Account bio/description used in header
274
+ *
275
+ * @param $header_data
276
+ *
277
+ * @return string
278
+ *
279
+ * @since 2.0.1/5.0
280
+ * @since 2.2/5.3 added support for a custom bio in settings
281
+ */
282
+ public static function get_bio( $header_data, $settings = array() ) {
283
+ if ( ! empty( $settings['custombio'] ) ) {
284
+ return $settings['custombio'];
285
+ } elseif ( isset( $header_data['data']['bio'] ) ) {
286
+ return $header_data['data']['bio'];
287
+ } elseif ( isset( $header_data['bio'] ) ){
288
+ return $header_data['bio'];
289
+ } elseif ( isset( $header_data['biography'] ) ){
290
+ return $header_data['biography'];
291
+ }
292
+ return '';
293
+ }
294
+
295
+ /**
296
+ * There seems to be occasional bugs with the Instagram API
297
+ * and permalinks. This corrects it.
298
+ *
299
+ * @param string $permalink
300
+ *
301
+ * @return string
302
+ *
303
+ * @since 2.0/5.0
304
+ */
305
+ protected static function fix_permalink( $permalink ) {
306
+ if ( substr_count( $permalink, '/' ) > 5 ) {
307
+ $permalink_array = explode( '/', $permalink );
308
+ $perm_id = $permalink_array[ count( $permalink_array ) - 2 ];
309
+ $permalink = 'https://www.instagram.com/p/' . $perm_id . '/';
310
+ }
311
+
312
+ return $permalink;
313
+ }
314
  }
inc/class-sb-instagram-post-set.php CHANGED
@@ -1,188 +1,188 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Post_Set
4
- *
5
- * Useful for iterating over an array of posts and resizing images for
6
- * them or updating data in the custom database tables.
7
- *
8
- * @since 2.0/4.0
9
- */
10
-
11
- // Don't load directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- die( '-1' );
14
- }
15
-
16
- class SB_Instagram_Post_Set {
17
- /**
18
- * @var array
19
- */
20
- private $post_data;
21
-
22
- /**
23
- * @var array
24
- */
25
- private $resized_image_data_for_set;
26
-
27
- /**
28
- * @var string|null
29
- */
30
- private $upload_dir;
31
-
32
- /**
33
- * @var string|null
34
- */
35
- private $upload_url;
36
-
37
- /**
38
- * @var bool
39
- */
40
- private $transient_name;
41
-
42
- /**
43
- * @var null
44
- */
45
- private $fill_in_timestamp;
46
-
47
- /**
48
- * @var
49
- */
50
- private $first_post_top_time_stamp;
51
-
52
- /**
53
- * SB_Instagram_Post_Set constructor.
54
- *
55
- * @param array $post_data
56
- * @param bool $transient_name
57
- * @param null $fill_in_timestamp (optional)
58
- * @param array $image_sizes (optional) sizes to create for personal and business account
59
- * currently thumb, low, and full can be set
60
- * @param null $upload_dir (optional)
61
- * @param null $upload_url (optional)
62
- *
63
- * @since 2.0/4.0
64
- */
65
- public function __construct( $post_data, $transient_name = false, $fill_in_timestamp = NULL, $image_sizes = array( 'personal' => array( 'low' => 320 ), 'business' => array( 'full' => 640, 'low' => 320 ) ), $upload_dir = NULL, $upload_url = NULL ) {
66
- $this->post_data = $post_data;
67
-
68
- $this->image_sizes = $image_sizes;
69
-
70
- if ( ! isset( $upload_dir ) || ! isset( $upload_url ) ) {
71
- $upload = wp_upload_dir();
72
- $upload_dir = $upload['basedir'];
73
- $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
74
-
75
- $upload_url = trailingslashit( $upload['baseurl'] ) . SBI_UPLOADS_NAME;
76
- }
77
-
78
- $this->upload_dir = $upload_dir;
79
-
80
- $this->upload_url = $upload_url;
81
-
82
- $this->transient_name = $transient_name;
83
-
84
- $this->fill_in_timestamp = $fill_in_timestamp;
85
- }
86
-
87
- /**
88
- * @return array
89
- *
90
- * @since 2.0/4.0
91
- */
92
- public function get_post_data() {
93
- if ( is_array( $this->post_data ) ) {
94
- return $this->post_data;
95
- } else {
96
- return array();
97
- }
98
- }
99
-
100
- /**
101
- * @return array
102
- *
103
- * @since 2.0/4.0
104
- */
105
- public function get_resized_image_data_for_set() {
106
- return $this->resized_image_data_for_set;
107
- }
108
-
109
- /**
110
- * Loop through set of posts and update or create resized images based on
111
- * whether or not they have been created and whether or not a record has been
112
- * saved for this feed id
113
- *
114
- * @since 2.0/4.0
115
- */
116
- public function maybe_save_update_and_resize_images_for_posts() {
117
- global $sb_instagram_posts_manager;
118
-
119
- $posts_iterated_through = 0;
120
- $number_resized = 0;
121
- $number_updated = 0;
122
- $resized_image_data_for_set = array();
123
- $resizing_disabled = $sb_instagram_posts_manager->image_resizing_disabled() || $sb_instagram_posts_manager->max_resizing_per_time_period_reached();
124
- $is_top_post_feed = (substr( $this->transient_name, 4, 1 ) === '+');
125
-
126
- foreach ( $this->post_data as $single_instagram_post_data ) {
127
-
128
- if ( $posts_iterated_through < 60 ) {
129
- $single_post = new SB_Instagram_Post( $single_instagram_post_data['id'] );
130
- $single_post->set_instagram_api_data( $single_instagram_post_data );
131
- $resized_image_data_for_set[ $single_instagram_post_data['id'] ] = array();
132
-
133
- if ( $is_top_post_feed ) {
134
- if ( empty( $this->first_post_top_time_stamp ) ) {
135
- $this_post_top_time_stamp = $single_post->get_top_time_stamp();
136
- if ( empty( $this_post_top_time_stamp ) ) {
137
- $this->first_post_top_time_stamp = $this->fill_in_timestamp;
138
- } else {
139
- $this->first_post_top_time_stamp = $single_post->get_top_time_stamp();
140
- }
141
- }
142
- }
143
-
144
- if ( ! $resizing_disabled ) {
145
- if ( (! $single_post->exists_in_posts_table() || ! $single_post->images_done_resizing()) && $number_resized < 30 ) {
146
-
147
- if ( $sb_instagram_posts_manager->max_total_records_reached() ) {
148
- $sb_instagram_posts_manager->delete_least_used_image();
149
- }
150
-
151
- if ( ! $single_post->images_done_resizing() && $single_post->exists_in_posts_table() ) {
152
- $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
153
- } else {
154
- if ( $is_top_post_feed ) {
155
- if ( $single_post->save_in_db( $this->transient_name, date( 'Y-m-d H:i:s', strtotime( $this->first_post_top_time_stamp ) - (120 * $posts_iterated_through) - 1 ) ) ) {
156
- $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
157
- }
158
- } else {
159
- if ( $single_post->save_in_db( $this->transient_name, date( 'Y-m-d H:i:s', strtotime( $this->fill_in_timestamp ) - (120 * $posts_iterated_through) ) ) ) {
160
- $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
161
- }
162
- }
163
- }
164
-
165
- $number_resized++;
166
- } else {
167
- if ( $is_top_post_feed ) {
168
- $single_post->update_db_data( true, $this->transient_name, $this->image_sizes, $this->upload_dir, $this->upload_url, date( 'Y-m-d H:i:s', strtotime( $this->first_post_top_time_stamp ) - (120 * $posts_iterated_through) ) );
169
- } else {
170
- $single_post->update_db_data( true, $this->transient_name, $this->image_sizes, $this->upload_dir, $this->upload_url );
171
- }
172
- if ( ! $single_post->exists_in_feeds_posts_table( $this->transient_name ) ) {
173
- $single_post->insert_sbi_instagram_feeds_posts( $this->transient_name );
174
- }
175
- $number_updated++;
176
- }
177
-
178
- $resized_image_data_for_set[ $single_instagram_post_data['id'] ] = $single_post->get_resized_image_array();
179
- }
180
- }
181
-
182
- $posts_iterated_through++;
183
- }
184
-
185
- $this->resized_image_data_for_set = $resized_image_data_for_set;
186
- }
187
-
188
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Post_Set
4
+ *
5
+ * Useful for iterating over an array of posts and resizing images for
6
+ * them or updating data in the custom database tables.
7
+ *
8
+ * @since 2.0/4.0
9
+ */
10
+
11
+ // Don't load directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ die( '-1' );
14
+ }
15
+
16
+ class SB_Instagram_Post_Set {
17
+ /**
18
+ * @var array
19
+ */
20
+ private $post_data;
21
+
22
+ /**
23
+ * @var array
24
+ */
25
+ private $resized_image_data_for_set;
26
+
27
+ /**
28
+ * @var string|null
29
+ */
30
+ private $upload_dir;
31
+
32
+ /**
33
+ * @var string|null
34
+ */
35
+ private $upload_url;
36
+
37
+ /**
38
+ * @var bool
39
+ */
40
+ private $transient_name;
41
+
42
+ /**
43
+ * @var null
44
+ */
45
+ private $fill_in_timestamp;
46
+
47
+ /**
48
+ * @var
49
+ */
50
+ private $first_post_top_time_stamp;
51
+
52
+ /**
53
+ * SB_Instagram_Post_Set constructor.
54
+ *
55
+ * @param array $post_data
56
+ * @param bool $transient_name
57
+ * @param null $fill_in_timestamp (optional)
58
+ * @param array $image_sizes (optional) sizes to create for personal and business account
59
+ * currently thumb, low, and full can be set
60
+ * @param null $upload_dir (optional)
61
+ * @param null $upload_url (optional)
62
+ *
63
+ * @since 2.0/4.0
64
+ */
65
+ public function __construct( $post_data, $transient_name = false, $fill_in_timestamp = NULL, $image_sizes = array( 'personal' => array( 'low' => 320 ), 'business' => array( 'full' => 640, 'low' => 320 ) ), $upload_dir = NULL, $upload_url = NULL ) {
66
+ $this->post_data = $post_data;
67
+
68
+ $this->image_sizes = $image_sizes;
69
+
70
+ if ( ! isset( $upload_dir ) || ! isset( $upload_url ) ) {
71
+ $upload = wp_upload_dir();
72
+ $upload_dir = $upload['basedir'];
73
+ $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
74
+
75
+ $upload_url = trailingslashit( $upload['baseurl'] ) . SBI_UPLOADS_NAME;
76
+ }
77
+
78
+ $this->upload_dir = $upload_dir;
79
+
80
+ $this->upload_url = $upload_url;
81
+
82
+ $this->transient_name = $transient_name;
83
+
84
+ $this->fill_in_timestamp = $fill_in_timestamp;
85
+ }
86
+
87
+ /**
88
+ * @return array
89
+ *
90
+ * @since 2.0/4.0
91
+ */
92
+ public function get_post_data() {
93
+ if ( is_array( $this->post_data ) ) {
94
+ return $this->post_data;
95
+ } else {
96
+ return array();
97
+ }
98
+ }
99
+
100
+ /**
101
+ * @return array
102
+ *
103
+ * @since 2.0/4.0
104
+ */
105
+ public function get_resized_image_data_for_set() {
106
+ return $this->resized_image_data_for_set;
107
+ }
108
+
109
+ /**
110
+ * Loop through set of posts and update or create resized images based on
111
+ * whether or not they have been created and whether or not a record has been
112
+ * saved for this feed id
113
+ *
114
+ * @since 2.0/4.0
115
+ */
116
+ public function maybe_save_update_and_resize_images_for_posts() {
117
+ global $sb_instagram_posts_manager;
118
+
119
+ $posts_iterated_through = 0;
120
+ $number_resized = 0;
121
+ $number_updated = 0;
122
+ $resized_image_data_for_set = array();
123
+ $resizing_disabled = $sb_instagram_posts_manager->image_resizing_disabled() || $sb_instagram_posts_manager->max_resizing_per_time_period_reached();
124
+ $is_top_post_feed = (substr( $this->transient_name, 4, 1 ) === '+');
125
+
126
+ foreach ( $this->post_data as $single_instagram_post_data ) {
127
+
128
+ if ( $posts_iterated_through < 60 ) {
129
+ $single_post = new SB_Instagram_Post( $single_instagram_post_data['id'] );
130
+ $single_post->set_instagram_api_data( $single_instagram_post_data );
131
+ $resized_image_data_for_set[ $single_instagram_post_data['id'] ] = array();
132
+
133
+ if ( $is_top_post_feed ) {
134
+ if ( empty( $this->first_post_top_time_stamp ) ) {
135
+ $this_post_top_time_stamp = $single_post->get_top_time_stamp();
136
+ if ( empty( $this_post_top_time_stamp ) ) {
137
+ $this->first_post_top_time_stamp = $this->fill_in_timestamp;
138
+ } else {
139
+ $this->first_post_top_time_stamp = $single_post->get_top_time_stamp();
140
+ }
141
+ }
142
+ }
143
+
144
+ if ( ! $resizing_disabled ) {
145
+ if ( (! $single_post->exists_in_posts_table() || ! $single_post->images_done_resizing()) && $number_resized < 30 ) {
146
+
147
+ if ( $sb_instagram_posts_manager->max_total_records_reached() ) {
148
+ $sb_instagram_posts_manager->delete_least_used_image();
149
+ }
150
+
151
+ if ( ! $single_post->images_done_resizing() && $single_post->exists_in_posts_table() ) {
152
+ $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
153
+ } else {
154
+ if ( $is_top_post_feed ) {
155
+ if ( $single_post->save_in_db( $this->transient_name, date( 'Y-m-d H:i:s', strtotime( $this->first_post_top_time_stamp ) - (120 * $posts_iterated_through) - 1 ) ) ) {
156
+ $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
157
+ }
158
+ } else {
159
+ if ( $single_post->save_in_db( $this->transient_name, date( 'Y-m-d H:i:s', strtotime( $this->fill_in_timestamp ) - (120 * $posts_iterated_through) ) ) ) {
160
+ $single_post->resize_and_save_image( $this->image_sizes, $this->upload_dir, $this->upload_url );
161
+ }
162
+ }
163
+ }
164
+
165
+ $number_resized++;
166
+ } else {
167
+ if ( $is_top_post_feed ) {
168
+ $single_post->update_db_data( true, $this->transient_name, $this->image_sizes, $this->upload_dir, $this->upload_url, date( 'Y-m-d H:i:s', strtotime( $this->first_post_top_time_stamp ) - (120 * $posts_iterated_through) ) );
169
+ } else {
170
+ $single_post->update_db_data( true, $this->transient_name, $this->image_sizes, $this->upload_dir, $this->upload_url );
171
+ }
172
+ if ( ! $single_post->exists_in_feeds_posts_table( $this->transient_name ) ) {
173
+ $single_post->insert_sbi_instagram_feeds_posts( $this->transient_name );
174
+ }
175
+ $number_updated++;
176
+ }
177
+
178
+ $resized_image_data_for_set[ $single_instagram_post_data['id'] ] = $single_post->get_resized_image_array();
179
+ }
180
+ }
181
+
182
+ $posts_iterated_through++;
183
+ }
184
+
185
+ $this->resized_image_data_for_set = $resized_image_data_for_set;
186
+ }
187
+
188
  }
inc/class-sb-instagram-post.php CHANGED
@@ -1,547 +1,547 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Post
4
- *
5
- * Primarily used for resizing and storing images, this class
6
- * performs certain tasks with data for a single post.
7
- *
8
- * Currently used only by the SB_Instagram_Post_Set class
9
- *
10
- * @since 2.0/4.0
11
- */
12
-
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- die( '-1' );
15
- }
16
-
17
- class SB_Instagram_Post
18
- {
19
- /**
20
- * @var string
21
- */
22
- private $instagram_post_id;
23
-
24
- /**
25
- * @var array
26
- */
27
- private $instagram_api_data;
28
-
29
- /**
30
- * @var string
31
- */
32
- private $db_id;
33
-
34
- /**
35
- * @var string
36
- */
37
- private $media_id;
38
-
39
- /**
40
- * @var string
41
- */
42
- private $top_time_stamp;
43
-
44
- /**
45
- * @var bool|int
46
- */
47
- private $images_done;
48
-
49
- /**
50
- * @var array
51
- */
52
- private $resized_image_array;
53
-
54
- /**
55
- * SB_Instagram_Post constructor.
56
- *
57
- * @param string $instagram_post_id from the Instagram API
58
- */
59
- public function __construct( $instagram_post_id ) {
60
- global $wpdb;
61
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
62
-
63
- $feed_id_match = $wpdb->get_results( $wpdb->prepare( "SELECT id, media_id, top_time_stamp, images_done FROM $table_name WHERE instagram_id = %s LIMIT 1", $instagram_post_id ), ARRAY_A );
64
-
65
- $this->db_id = ! empty( $feed_id_match ) ? $feed_id_match[0]['id'] : '';
66
- $this->media_id = ! empty( $feed_id_match ) ? $feed_id_match[0]['media_id'] : '';
67
- $this->top_time_stamp = ! empty( $feed_id_match ) && isset( $feed_id_match[0]['top_time_stamp'] ) ? $feed_id_match[0]['top_time_stamp'] : '';
68
- $this->images_done = ! empty( $feed_id_match ) && isset( $feed_id_match[0]['images_done'] ) ? $feed_id_match[0]['images_done'] === '1' : 0;
69
-
70
- $this->instagram_post_id = $instagram_post_id;
71
- }
72
-
73
- /**
74
- * Whether or not this post has already been saved in the custom table
75
- *
76
- * @return bool
77
- *
78
- * @since 2.0/4.0
79
- */
80
- public function exists_in_posts_table() {
81
- return ! empty( $this->db_id );
82
- }
83
-
84
- /**
85
- * Whether or not resized image files have already been recorded as being created
86
- * in the database table
87
- *
88
- * @return bool|int
89
- *
90
- * @since 2.0/4.0
91
- */
92
- public function images_done_resizing() {
93
- return $this->images_done;
94
- }
95
-
96
- /**
97
- * @param array $instagram_api_data
98
- *
99
- * @since 2.0/4.0
100
- */
101
- public function set_instagram_api_data( $instagram_api_data ) {
102
- $this->instagram_api_data = $instagram_api_data;
103
- }
104
-
105
- /**
106
- * Used for sorting top posts since they don't have a posted on date
107
- *
108
- * @return string
109
- *
110
- * @since 2.0/4.0
111
- */
112
- public function get_top_time_stamp() {
113
- return $this->top_time_stamp;
114
- }
115
-
116
- /**
117
- * Record newly created images so they can be returned and used right away.
118
- *
119
- * Not used in version 2.0/5.0 but can be used to resize and use
120
- * images "on the fly" when the feed is being displayed.
121
- *
122
- * @param string $key
123
- * @param string $val
124
- *
125
- * @since 2.0/4.0
126
- */
127
- public function add_resized_image_to_obj_array( $key, $val ) {
128
- $this->resized_image_array[ $key ] = $val;
129
- }
130
-
131
- /**
132
- * Used to save information about the post before image resizing is done to
133
- * prevent a potentially storing multiple entries for the same post
134
- *
135
- * @param mixed|string|bool $transient_name (optional)
136
- * @param null $timestamp_override (optional)
137
- *
138
- * @return bool
139
- *
140
- * @since 2.0/4.0
141
- */
142
- public function save_in_db( $transient_name = false, $timestamp_override = NULL ) {
143
- global $wpdb;
144
-
145
- $parsed_data = $this->get_parsed_post_data();
146
-
147
- $timestamp = ! empty( $timestamp_override ) && empty( $parsed_data['timestamp'] ) ? $timestamp_override : $parsed_data['timestamp'];
148
-
149
- $entry_data = array(
150
- "'" . date( 'Y-m-d H:i:s' ) . "'",
151
- "'" . esc_sql( $parsed_data['id'] ) . "'",
152
- "'" . esc_sql( $timestamp ) . "'",
153
- "'" . esc_sql( wp_json_encode( $this->instagram_api_data ) ) . "'",
154
- "'pending'",
155
- "'pending'",
156
- 0,
157
- "'".date( 'Y-m-d H:i:s' )."'"
158
- );
159
-
160
- $entry_string = implode( ',',$entry_data );
161
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
162
-
163
- $timestamp_column = 'time_stamp';
164
- if ( substr( $transient_name, 4, 1 ) === '+') {
165
- $timestamp_column = 'top_time_stamp';
166
- }
167
-
168
- $error = $wpdb->query( "INSERT INTO $table_name
169
- (created_on,instagram_id,$timestamp_column,json_data,media_id,sizes,images_done,last_requested) VALUES ($entry_string);" );
170
-
171
- if ( $error !== false ) {
172
- $this->db_id = $wpdb->insert_id;
173
- $this->insert_sbi_instagram_feeds_posts( $transient_name );
174
- } else {
175
- // log error
176
- }
177
-
178
- return true;
179
- }
180
-
181
- /**
182
- * Uses the post's data to get a relevant full size image url and resize it
183
- *
184
- * @param array $image_sizes
185
- * @param string $upload_dir
186
- * @param string $upload_url
187
- *
188
- * @since 2.0/4.0
189
- * @since 2.0/5.0 loop through assoc array (res setting => desired width of image) to
190
- * accommodate personal accounts and possible
191
- * custom sizes in the future
192
- */
193
- public function resize_and_save_image( $image_sizes, $upload_dir, $upload_url ) {
194
- if ( isset( $this->instagram_api_data['id'] ) ) {
195
- $image_source_set = SB_Instagram_Parse::get_media_src_set( $this->instagram_api_data );
196
- $account_type = SB_Instagram_Parse::get_account_type( $this->instagram_api_data );
197
- $image_sizes_to_make = isset( $image_sizes[ $account_type ] ) ? $image_sizes[ $account_type ] : array();
198
- // if it's a personal account or a weird url, the post id is used, otherwise the last part of the image url is used
199
- if ( $account_type === 'business' ) {
200
- $new_file_name = explode( '?', SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' ) );
201
- if ( strlen( basename( $new_file_name[0], '.jpg' ) ) > 10 ) {
202
- $new_file_name = basename( $new_file_name[0], '.jpg' );
203
- } else {
204
- $new_file_name = $this->instagram_api_data['id'];
205
- }
206
- } else {
207
- $new_file_name = $this->instagram_api_data['id'];
208
- }
209
-
210
- // the process is considered a success if one image is successfully resized
211
- $one_successful_image_resize = false;
212
-
213
- foreach ( $image_sizes_to_make as $res_setting => $image_size ) {
214
- if ( $account_type === 'business' ) {
215
- $file_name = SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' );
216
- } else {
217
- $file_name = isset( $image_source_set[ $image_size ] ) ? $image_source_set[ $image_size ] : SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' );
218
- }
219
- if ( ! empty( $file_name ) ) {
220
-
221
- $sizes = array(
222
- 'height' => 1,
223
- 'width' => 1
224
- );
225
-
226
-
227
- $suffix = $res_setting;
228
-
229
- $this_image_file_name = $new_file_name . $suffix . '.jpg';
230
-
231
- $image_editor = wp_get_image_editor( $file_name );
232
-
233
- // not uncommon for the image editor to not work using it this way
234
- if ( ! is_wp_error( $image_editor ) ) {
235
- $sizes = $image_editor->get_size();
236
-
237
- $image_editor->resize( $image_size, null );
238
-
239
- $full_file_name = trailingslashit( $upload_dir ) . $this_image_file_name;
240
-
241
- $saved_image = $image_editor->save( $full_file_name );
242
-
243
- if ( ! $saved_image ) {
244
- global $sb_instagram_posts_manager;
245
-
246
- $sb_instagram_posts_manager->add_error( 'image_editor_save', array(
247
- __( 'Error saving edited image.', 'instagram-feed' ),
248
- $full_file_name
249
- ) );
250
- } else {
251
- $one_successful_image_resize = true;
252
- }
253
- } else {
254
- global $sb_instagram_posts_manager;
255
-
256
- $message = __( 'Error editing image.', 'instagram-feed' );
257
- if ( isset( $image_editor ) && isset( $image_editor->errors ) ) {
258
- foreach ( $image_editor->errors as $key => $item ) {
259
- $message .= ' ' . $key . '- ' . $item[0] . ' |';
260
- }
261
- }
262
-
263
- $sb_instagram_posts_manager->add_error( 'image_editor', array( $file_name, $message ) );
264
- }
265
-
266
- }
267
-
268
-
269
- }
270
-
271
- if ( $one_successful_image_resize ) {
272
- $aspect_ratio = round( $sizes['width'] / $sizes['height'], 2 );
273
-
274
- $this->update_sbi_instagram_posts( array(
275
- 'media_id' => $new_file_name,
276
- 'sizes' => maybe_serialize( $image_sizes_to_make ),
277
- 'aspect_ratio' => $aspect_ratio,
278
- 'images_done' => 1
279
- ) );
280
-
281
- $this->add_resized_image_to_obj_array( 'id', $new_file_name );
282
- } else {
283
- // an error status means that image resizing won't be attempted again for this post
284
- $this->update_sbi_instagram_posts( array(
285
- 'media_id' => 'error',
286
- 'sizes' => maybe_serialize( $image_sizes_to_make ),
287
- 'aspect_ratio' => 1,
288
- 'images_done' => 1
289
- ) );
290
- }
291
-
292
- }
293
- }
294
-
295
- /**
296
- * Return relevant data for resized images for this post
297
- *
298
- * @return array
299
- *
300
- * @since 2.0/4.0
301
- */
302
- public function get_resized_image_array() {
303
- if ( empty( $this->resized_image_array ) ) {
304
- global $wpdb;
305
-
306
- $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
307
- $stored = $wpdb->get_results( $wpdb->prepare( "SELECT media_id, aspect_ratio FROM $posts_table_name
308
- WHERE instagram_id = %s
309
- LIMIT 1", $this->instagram_post_id ), ARRAY_A );
310
-
311
- if ( isset( $stored[0] ) ) {
312
- $return = array(
313
- 'id' => $stored[0]['media_id'],
314
- 'ratio' => $stored[0]['aspect_ratio']
315
- );
316
- $this->resized_image_array = $return;
317
- return $return;
318
- } else {
319
- return array();
320
- }
321
- } else {
322
- return $this->resized_image_array;
323
- }
324
- }
325
-
326
- /**
327
- * Controls whether or not the database record will be updated for this post.
328
- * Called after images are successfully created.
329
- *
330
- * @param bool $update_last_requested
331
- * @param bool $transient_name
332
- * @param array $image_sizes
333
- * @param string $upload_dir
334
- * @param string $upload_url
335
- * @param bool $timestamp_for_update
336
- *
337
- * @return bool
338
- *
339
- * @since 2.0/4.0
340
- */
341
- public function update_db_data( $update_last_requested = true, $transient_name = false, $image_sizes, $upload_dir, $upload_url, $timestamp_for_update = false ) {
342
-
343
- if ( empty( $this->db_id ) ) {
344
- return false;
345
- }
346
-
347
- $to_update = array(
348
- 'json_data' => wp_json_encode( $this->instagram_api_data )
349
- );
350
-
351
- if ( $update_last_requested ) {
352
- $to_update['last_requested'] = date( 'Y-m-d H:i:s' );
353
- }
354
-
355
- if ( $timestamp_for_update ) {
356
- $to_update['top_time_stamp'] = $timestamp_for_update;
357
- }
358
-
359
- if ( $transient_name ) {
360
- $this->maybe_add_feed_id( $transient_name );
361
- }
362
-
363
- if ( $this->media_id === 'pending' ) {
364
- $this->resize_and_save_image( $image_sizes, $upload_dir, $upload_url );
365
- } else {
366
- $this->update_sbi_instagram_posts( $to_update );
367
- }
368
-
369
- return true;
370
- }
371
-
372
- /**
373
- * Updates columns that need to be updated in the posts types table.
374
- * Called after images successfully resized and if any information
375
- * needs to be updated.
376
- *
377
- * @param array $to_update assoc array of columns and values to update
378
- *
379
- * @since 2.0/4.0
380
- */
381
- public function update_sbi_instagram_posts( $to_update ) {
382
- global $wpdb;
383
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
384
-
385
- foreach ( $to_update as $column => $value ) {
386
- $query = $wpdb->query( $wpdb->prepare( "UPDATE $table_name
387
- SET $column = %s
388
- WHERE id = %d;", $value, $this->db_id ) );
389
-
390
- if ( $query === false ) {
391
- global $sb_instagram_posts_manager;
392
- $error = $wpdb->last_error;
393
- $query = $wpdb->last_query;
394
-
395
- $sb_instagram_posts_manager->add_error( 'database_update_post', array( __( 'Error updating post.', 'instagram-feed' ), $error . '<br><code>' . $query . '</code>' ) );
396
- }
397
- }
398
-
399
- }
400
-
401
- /**
402
- * Checks database for matching record for post and feed ID.
403
- * There shouldn't be duplicate records
404
- *
405
- * @param string $transient_name
406
- *
407
- * @return bool
408
- *
409
- * @since 2.0/4.1
410
- */
411
- public function exists_in_feeds_posts_table( $transient_name ) {
412
- global $wpdb;
413
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
414
- $feed_id_array = explode( '#', $transient_name );
415
- $feed_id = $feed_id_array[0];
416
- $results = $wpdb->get_results( $wpdb->prepare( "SELECT feed_id FROM $table_name WHERE instagram_id = %s AND feed_id = %s LIMIT 1", $this->instagram_post_id, $feed_id ), ARRAY_A );
417
-
418
- return isset( $results[0]['feed_id'] );
419
- }
420
-
421
- /**
422
- * Add a record of this post being used for the specified transient name (feed id)
423
- *
424
- * @param string $transient_name
425
- *
426
- * @return int
427
- *
428
- * @since 2.0/4.0
429
- */
430
- public function insert_sbi_instagram_feeds_posts( $transient_name ) {
431
- global $wpdb;
432
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
433
- // the number is removed from the transient name for backwards compatibilty.
434
- $feed_id_array = explode( '#', $transient_name );
435
- $feed_id = $feed_id_array[0];
436
-
437
- if ( ! empty( $this->db_id ) ) {
438
- $entry_data = array(
439
- $this->db_id,
440
- "'" . esc_sql( $this->instagram_api_data['id'] ) . "'",
441
- "'" . esc_sql( $feed_id ) . "'"
442
- );
443
- $entry_string = implode( ',',$entry_data );
444
-
445
- $error = $wpdb->query( "INSERT INTO $table_name
446
- (id,instagram_id,feed_id) VALUES ($entry_string);" );
447
- } else {
448
- global $sb_instagram_posts_manager;
449
-
450
- $sb_instagram_posts_manager->add_error( 'database_insert_post', array( __( 'Error inserting post.', 'instagram-feed' ), __( 'No database ID.', 'instagram-feed' ) ) );
451
- return false;
452
- }
453
-
454
-
455
- if ( $error !== false ) {
456
- return $wpdb->insert_id;
457
- } else {
458
- global $sb_instagram_posts_manager;
459
- $error = $wpdb->last_error;
460
- $query = $wpdb->last_query;
461
-
462
- $sb_instagram_posts_manager->add_error( 'database_insert_post', array( __( 'Error inserting post.', 'instagram-feed' ), $error . '<br><code>' . $query . '</code>' ) );
463
- }
464
- }
465
-
466
- /**
467
- * Uses the saved json for the post to be used for updating records
468
- *
469
- * @param bool $all
470
- *
471
- * @return array
472
- *
473
- * @since 2.0/4.0
474
- */
475
- private function get_parsed_post_data( $all = true ) {
476
-
477
- $instagram_post_id = isset( $this->instagram_api_data['id'] ) ? $this->instagram_api_data['id'] : '';
478
- $comments_count = isset( $this->instagram_api_data['comments_count'] ) ? $this->instagram_api_data['comments_count'] : '';
479
- $like_count = isset( $this->instagram_api_data['like_count'] ) ? $this->instagram_api_data['like_count'] : '';
480
-
481
- $parsed_data = array(
482
- 'comments_count' => $comments_count,
483
- 'like_count' => $like_count
484
- );
485
-
486
- if ( $all ) {
487
- $caption = isset( $this->instagram_api_data['caption'] ) ? $this->instagram_api_data['caption'] : '';
488
- $media_url = isset( $this->instagram_api_data['media_url'] ) ? $this->instagram_api_data['media_url'] : '';
489
- $media_type = isset( $this->instagram_api_data['media_type'] ) ? $this->instagram_api_data['media_type'] : '';
490
-
491
- $timestamp = '';
492
- if ( isset( $this->instagram_api_data['timestamp'] ) ) {
493
- $timestamp_parts = explode( ' ', $this->instagram_api_data['timestamp'] );
494
- $timestamp = str_replace( 'T', ' ', $timestamp_parts[0] );
495
- }
496
-
497
- $username = isset( $this->instagram_api_data['username'] ) ? $this->instagram_api_data['username'] : '';
498
- $permalink = isset( $this->instagram_api_data['permalink'] ) ? $this->instagram_api_data['permalink'] : '';
499
- $children = isset( $this->instagram_api_data['children'] ) ? wp_json_encode( $this->instagram_api_data['children'] ) : '';
500
-
501
- $parsed_data['caption'] = $caption;
502
- $parsed_data['media_url'] = $media_url;
503
- $parsed_data['id'] = $instagram_post_id;
504
- $parsed_data['media_type'] = $media_type;
505
- $parsed_data['timestamp'] = $timestamp;
506
- $parsed_data['username'] = $username;
507
- $parsed_data['permalink'] = $permalink;
508
- $parsed_data['children'] = $children;
509
- }
510
-
511
- return $parsed_data;
512
- }
513
-
514
- /**
515
- * If a record hasn't been made for this transient name/feed id,
516
- * make a record
517
- *
518
- * @param string $feed_id
519
- *
520
- * @since 2.0/4.0
521
- */
522
- private function maybe_add_feed_id( $feed_id ) {
523
-
524
- if ( empty( $this->instagram_post_id ) ) {
525
- return;
526
- }
527
-
528
- global $wpdb;
529
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
530
- // the number is removed from the transient name for backwards compatibilty.
531
- $feed_id_array = explode( '#', $feed_id );
532
- $feed_id = $feed_id_array[0];
533
-
534
- $feed_id_match = $wpdb->get_col( $wpdb->prepare( "SELECT feed_id FROM $table_name WHERE feed_id = %s AND instagram_id = %s", $feed_id, $this->instagram_post_id ) );
535
-
536
- if ( ! isset( $feed_id_match[0] ) ) {
537
- $entry_data = array(
538
- $this->db_id,
539
- "'" . esc_sql( $this->instagram_post_id ) . "'",
540
- "'" . esc_sql( $feed_id ) . "'"
541
- );
542
- $entry_string = implode( ',',$entry_data );
543
- $error = $wpdb->query( "INSERT INTO $table_name
544
- (id,instagram_id,feed_id) VALUES ($entry_string);" );
545
- }
546
- }
547
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Post
4
+ *
5
+ * Primarily used for resizing and storing images, this class
6
+ * performs certain tasks with data for a single post.
7
+ *
8
+ * Currently used only by the SB_Instagram_Post_Set class
9
+ *
10
+ * @since 2.0/4.0
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ die( '-1' );
15
+ }
16
+
17
+ class SB_Instagram_Post
18
+ {
19
+ /**
20
+ * @var string
21
+ */
22
+ private $instagram_post_id;
23
+
24
+ /**
25
+ * @var array
26
+ */
27
+ private $instagram_api_data;
28
+
29
+ /**
30
+ * @var string
31
+ */
32
+ private $db_id;
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ private $media_id;
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ private $top_time_stamp;
43
+
44
+ /**
45
+ * @var bool|int
46
+ */
47
+ private $images_done;
48
+
49
+ /**
50
+ * @var array
51
+ */
52
+ private $resized_image_array;
53
+
54
+ /**
55
+ * SB_Instagram_Post constructor.
56
+ *
57
+ * @param string $instagram_post_id from the Instagram API
58
+ */
59
+ public function __construct( $instagram_post_id ) {
60
+ global $wpdb;
61
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
62
+
63
+ $feed_id_match = $wpdb->get_results( $wpdb->prepare( "SELECT id, media_id, top_time_stamp, images_done FROM $table_name WHERE instagram_id = %s LIMIT 1", $instagram_post_id ), ARRAY_A );
64
+
65
+ $this->db_id = ! empty( $feed_id_match ) ? $feed_id_match[0]['id'] : '';
66
+ $this->media_id = ! empty( $feed_id_match ) ? $feed_id_match[0]['media_id'] : '';
67
+ $this->top_time_stamp = ! empty( $feed_id_match ) && isset( $feed_id_match[0]['top_time_stamp'] ) ? $feed_id_match[0]['top_time_stamp'] : '';
68
+ $this->images_done = ! empty( $feed_id_match ) && isset( $feed_id_match[0]['images_done'] ) ? $feed_id_match[0]['images_done'] === '1' : 0;
69
+
70
+ $this->instagram_post_id = $instagram_post_id;
71
+ }
72
+
73
+ /**
74
+ * Whether or not this post has already been saved in the custom table
75
+ *
76
+ * @return bool
77
+ *
78
+ * @since 2.0/4.0
79
+ */
80
+ public function exists_in_posts_table() {
81
+ return ! empty( $this->db_id );
82
+ }
83
+
84
+ /**
85
+ * Whether or not resized image files have already been recorded as being created
86
+ * in the database table
87
+ *
88
+ * @return bool|int
89
+ *
90
+ * @since 2.0/4.0
91
+ */
92
+ public function images_done_resizing() {
93
+ return $this->images_done;
94
+ }
95
+
96
+ /**
97
+ * @param array $instagram_api_data
98
+ *
99
+ * @since 2.0/4.0
100
+ */
101
+ public function set_instagram_api_data( $instagram_api_data ) {
102
+ $this->instagram_api_data = $instagram_api_data;
103
+ }
104
+
105
+ /**
106
+ * Used for sorting top posts since they don't have a posted on date
107
+ *
108
+ * @return string
109
+ *
110
+ * @since 2.0/4.0
111
+ */
112
+ public function get_top_time_stamp() {
113
+ return $this->top_time_stamp;
114
+ }
115
+
116
+ /**
117
+ * Record newly created images so they can be returned and used right away.
118
+ *
119
+ * Not used in version 2.0/5.0 but can be used to resize and use
120
+ * images "on the fly" when the feed is being displayed.
121
+ *
122
+ * @param string $key
123
+ * @param string $val
124
+ *
125
+ * @since 2.0/4.0
126
+ */
127
+ public function add_resized_image_to_obj_array( $key, $val ) {
128
+ $this->resized_image_array[ $key ] = $val;
129
+ }
130
+
131
+ /**
132
+ * Used to save information about the post before image resizing is done to
133
+ * prevent a potentially storing multiple entries for the same post
134
+ *
135
+ * @param mixed|string|bool $transient_name (optional)
136
+ * @param null $timestamp_override (optional)
137
+ *
138
+ * @return bool
139
+ *
140
+ * @since 2.0/4.0
141
+ */
142
+ public function save_in_db( $transient_name = false, $timestamp_override = NULL ) {
143
+ global $wpdb;
144
+
145
+ $parsed_data = $this->get_parsed_post_data();
146
+
147
+ $timestamp = ! empty( $timestamp_override ) && empty( $parsed_data['timestamp'] ) ? $timestamp_override : $parsed_data['timestamp'];
148
+
149
+ $entry_data = array(
150
+ "'" . date( 'Y-m-d H:i:s' ) . "'",
151
+ "'" . esc_sql( $parsed_data['id'] ) . "'",
152
+ "'" . esc_sql( $timestamp ) . "'",
153
+ "'" . esc_sql( wp_json_encode( $this->instagram_api_data ) ) . "'",
154
+ "'pending'",
155
+ "'pending'",
156
+ 0,
157
+ "'".date( 'Y-m-d H:i:s' )."'"
158
+ );
159
+
160
+ $entry_string = implode( ',',$entry_data );
161
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
162
+
163
+ $timestamp_column = 'time_stamp';
164
+ if ( substr( $transient_name, 4, 1 ) === '+') {
165
+ $timestamp_column = 'top_time_stamp';
166
+ }
167
+
168
+ $error = $wpdb->query( "INSERT INTO $table_name
169
+ (created_on,instagram_id,$timestamp_column,json_data,media_id,sizes,images_done,last_requested) VALUES ($entry_string);" );
170
+
171
+ if ( $error !== false ) {
172
+ $this->db_id = $wpdb->insert_id;
173
+ $this->insert_sbi_instagram_feeds_posts( $transient_name );
174
+ } else {
175
+ // log error
176
+ }
177
+
178
+ return true;
179
+ }
180
+
181
+ /**
182
+ * Uses the post's data to get a relevant full size image url and resize it
183
+ *
184
+ * @param array $image_sizes
185
+ * @param string $upload_dir
186
+ * @param string $upload_url
187
+ *
188
+ * @since 2.0/4.0
189
+ * @since 2.0/5.0 loop through assoc array (res setting => desired width of image) to
190
+ * accommodate personal accounts and possible
191
+ * custom sizes in the future
192
+ */
193
+ public function resize_and_save_image( $image_sizes, $upload_dir, $upload_url ) {
194
+ if ( isset( $this->instagram_api_data['id'] ) ) {
195
+ $image_source_set = SB_Instagram_Parse::get_media_src_set( $this->instagram_api_data );
196
+ $account_type = SB_Instagram_Parse::get_account_type( $this->instagram_api_data );
197
+ $image_sizes_to_make = isset( $image_sizes[ $account_type ] ) ? $image_sizes[ $account_type ] : array();
198
+ // if it's a personal account or a weird url, the post id is used, otherwise the last part of the image url is used
199
+ if ( $account_type === 'business' ) {
200
+ $new_file_name = explode( '?', SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' ) );
201
+ if ( strlen( basename( $new_file_name[0], '.jpg' ) ) > 10 ) {
202
+ $new_file_name = basename( $new_file_name[0], '.jpg' );
203
+ } else {
204
+ $new_file_name = $this->instagram_api_data['id'];
205
+ }
206
+ } else {
207
+ $new_file_name = $this->instagram_api_data['id'];
208
+ }
209
+
210
+ // the process is considered a success if one image is successfully resized
211
+ $one_successful_image_resize = false;
212
+
213
+ foreach ( $image_sizes_to_make as $res_setting => $image_size ) {
214
+ if ( $account_type === 'business' ) {
215
+ $file_name = SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' );
216
+ } else {
217
+ $file_name = isset( $image_source_set[ $image_size ] ) ? $image_source_set[ $image_size ] : SB_Instagram_Parse::get_media_url( $this->instagram_api_data, 'lightbox' );
218
+ }
219
+ if ( ! empty( $file_name ) ) {
220
+
221
+ $sizes = array(
222
+ 'height' => 1,
223
+ 'width' => 1
224
+ );
225
+
226
+
227
+ $suffix = $res_setting;
228
+
229
+ $this_image_file_name = $new_file_name . $suffix . '.jpg';
230
+
231
+ $image_editor = wp_get_image_editor( $file_name );
232
+
233
+ // not uncommon for the image editor to not work using it this way
234
+ if ( ! is_wp_error( $image_editor ) ) {
235
+ $sizes = $image_editor->get_size();
236
+
237
+ $image_editor->resize( $image_size, null );
238
+
239
+ $full_file_name = trailingslashit( $upload_dir ) . $this_image_file_name;
240
+
241
+ $saved_image = $image_editor->save( $full_file_name );
242
+
243
+ if ( ! $saved_image ) {
244
+ global $sb_instagram_posts_manager;
245
+
246
+ $sb_instagram_posts_manager->add_error( 'image_editor_save', array(
247
+ __( 'Error saving edited image.', 'instagram-feed' ),
248
+ $full_file_name
249
+ ) );
250
+ } else {
251
+ $one_successful_image_resize = true;
252
+ }
253
+ } else {
254
+ global $sb_instagram_posts_manager;
255
+
256
+ $message = __( 'Error editing image.', 'instagram-feed' );
257
+ if ( isset( $image_editor ) && isset( $image_editor->errors ) ) {
258
+ foreach ( $image_editor->errors as $key => $item ) {
259
+ $message .= ' ' . $key . '- ' . $item[0] . ' |';
260
+ }
261
+ }
262
+
263
+ $sb_instagram_posts_manager->add_error( 'image_editor', array( $file_name, $message ) );
264
+ }
265
+
266
+ }
267
+
268
+
269
+ }
270
+
271
+ if ( $one_successful_image_resize ) {
272
+ $aspect_ratio = round( $sizes['width'] / $sizes['height'], 2 );
273
+
274
+ $this->update_sbi_instagram_posts( array(
275
+ 'media_id' => $new_file_name,
276
+ 'sizes' => maybe_serialize( $image_sizes_to_make ),
277
+ 'aspect_ratio' => $aspect_ratio,
278
+ 'images_done' => 1
279
+ ) );
280
+
281
+ $this->add_resized_image_to_obj_array( 'id', $new_file_name );
282
+ } else {
283
+ // an error status means that image resizing won't be attempted again for this post
284
+ $this->update_sbi_instagram_posts( array(
285
+ 'media_id' => 'error',
286
+ 'sizes' => maybe_serialize( $image_sizes_to_make ),
287
+ 'aspect_ratio' => 1,
288
+ 'images_done' => 1
289
+ ) );
290
+ }
291
+
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Return relevant data for resized images for this post
297
+ *
298
+ * @return array
299
+ *
300
+ * @since 2.0/4.0
301
+ */
302
+ public function get_resized_image_array() {
303
+ if ( empty( $this->resized_image_array ) ) {
304
+ global $wpdb;
305
+
306
+ $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
307
+ $stored = $wpdb->get_results( $wpdb->prepare( "SELECT media_id, aspect_ratio FROM $posts_table_name
308
+ WHERE instagram_id = %s
309
+ LIMIT 1", $this->instagram_post_id ), ARRAY_A );
310
+
311
+ if ( isset( $stored[0] ) ) {
312
+ $return = array(
313
+ 'id' => $stored[0]['media_id'],
314
+ 'ratio' => $stored[0]['aspect_ratio']
315
+ );
316
+ $this->resized_image_array = $return;
317
+ return $return;
318
+ } else {
319
+ return array();
320
+ }
321
+ } else {
322
+ return $this->resized_image_array;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Controls whether or not the database record will be updated for this post.
328
+ * Called after images are successfully created.
329
+ *
330
+ * @param bool $update_last_requested
331
+ * @param bool $transient_name
332
+ * @param array $image_sizes
333
+ * @param string $upload_dir
334
+ * @param string $upload_url
335
+ * @param bool $timestamp_for_update
336
+ *
337
+ * @return bool
338
+ *
339
+ * @since 2.0/4.0
340
+ */
341
+ public function update_db_data( $update_last_requested = true, $transient_name = false, $image_sizes, $upload_dir, $upload_url, $timestamp_for_update = false ) {
342
+
343
+ if ( empty( $this->db_id ) ) {
344
+ return false;
345
+ }
346
+
347
+ $to_update = array(
348
+ 'json_data' => wp_json_encode( $this->instagram_api_data )
349
+ );
350
+
351
+ if ( $update_last_requested ) {
352
+ $to_update['last_requested'] = date( 'Y-m-d H:i:s' );
353
+ }
354
+
355
+ if ( $timestamp_for_update ) {
356
+ $to_update['top_time_stamp'] = $timestamp_for_update;
357
+ }
358
+
359
+ if ( $transient_name ) {
360
+ $this->maybe_add_feed_id( $transient_name );
361
+ }
362
+
363
+ if ( $this->media_id === 'pending' ) {
364
+ $this->resize_and_save_image( $image_sizes, $upload_dir, $upload_url );
365
+ } else {
366
+ $this->update_sbi_instagram_posts( $to_update );
367
+ }
368
+
369
+ return true;
370
+ }
371
+
372
+ /**
373
+ * Updates columns that need to be updated in the posts types table.
374
+ * Called after images successfully resized and if any information
375
+ * needs to be updated.
376
+ *
377
+ * @param array $to_update assoc array of columns and values to update
378
+ *
379
+ * @since 2.0/4.0
380
+ */
381
+ public function update_sbi_instagram_posts( $to_update ) {
382
+ global $wpdb;
383
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
384
+
385
+ foreach ( $to_update as $column => $value ) {
386
+ $query = $wpdb->query( $wpdb->prepare( "UPDATE $table_name
387
+ SET $column = %s
388
+ WHERE id = %d;", $value, $this->db_id ) );
389
+
390
+ if ( $query === false ) {
391
+ global $sb_instagram_posts_manager;
392
+ $error = $wpdb->last_error;
393
+ $query = $wpdb->last_query;
394
+
395
+ $sb_instagram_posts_manager->add_error( 'database_update_post', array( __( 'Error updating post.', 'instagram-feed' ), $error . '<br><code>' . $query . '</code>' ) );
396
+ }
397
+ }
398
+
399
+ }
400
+
401
+ /**
402
+ * Checks database for matching record for post and feed ID.
403
+ * There shouldn't be duplicate records
404
+ *
405
+ * @param string $transient_name
406
+ *
407
+ * @return bool
408
+ *
409
+ * @since 2.0/4.1
410
+ */
411
+ public function exists_in_feeds_posts_table( $transient_name ) {
412
+ global $wpdb;
413
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
414
+ $feed_id_array = explode( '#', $transient_name );
415
+ $feed_id = $feed_id_array[0];
416
+ $results = $wpdb->get_results( $wpdb->prepare( "SELECT feed_id FROM $table_name WHERE instagram_id = %s AND feed_id = %s LIMIT 1", $this->instagram_post_id, $feed_id ), ARRAY_A );
417
+
418
+ return isset( $results[0]['feed_id'] );
419
+ }
420
+
421
+ /**
422
+ * Add a record of this post being used for the specified transient name (feed id)
423
+ *
424
+ * @param string $transient_name
425
+ *
426
+ * @return int
427
+ *
428
+ * @since 2.0/4.0
429
+ */
430
+ public function insert_sbi_instagram_feeds_posts( $transient_name ) {
431
+ global $wpdb;
432
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
433
+ // the number is removed from the transient name for backwards compatibilty.
434
+ $feed_id_array = explode( '#', $transient_name );
435
+ $feed_id = $feed_id_array[0];
436
+
437
+ if ( ! empty( $this->db_id ) ) {
438
+ $entry_data = array(
439
+ $this->db_id,
440
+ "'" . esc_sql( $this->instagram_api_data['id'] ) . "'",
441
+ "'" . esc_sql( $feed_id ) . "'"
442
+ );
443
+ $entry_string = implode( ',',$entry_data );
444
+
445
+ $error = $wpdb->query( "INSERT INTO $table_name
446
+ (id,instagram_id,feed_id) VALUES ($entry_string);" );
447
+ } else {
448
+ global $sb_instagram_posts_manager;
449
+
450
+ $sb_instagram_posts_manager->add_error( 'database_insert_post', array( __( 'Error inserting post.', 'instagram-feed' ), __( 'No database ID.', 'instagram-feed' ) ) );
451
+ return false;
452
+ }
453
+
454
+
455
+ if ( $error !== false ) {
456
+ return $wpdb->insert_id;
457
+ } else {
458
+ global $sb_instagram_posts_manager;
459
+ $error = $wpdb->last_error;
460
+ $query = $wpdb->last_query;
461
+
462
+ $sb_instagram_posts_manager->add_error( 'database_insert_post', array( __( 'Error inserting post.', 'instagram-feed' ), $error . '<br><code>' . $query . '</code>' ) );
463
+ }
464
+ }
465
+
466
+ /**
467
+ * Uses the saved json for the post to be used for updating records
468
+ *
469
+ * @param bool $all
470
+ *
471
+ * @return array
472
+ *
473
+ * @since 2.0/4.0
474
+ */
475
+ private function get_parsed_post_data( $all = true ) {
476
+
477
+ $instagram_post_id = isset( $this->instagram_api_data['id'] ) ? $this->instagram_api_data['id'] : '';
478
+ $comments_count = isset( $this->instagram_api_data['comments_count'] ) ? $this->instagram_api_data['comments_count'] : '';
479
+ $like_count = isset( $this->instagram_api_data['like_count'] ) ? $this->instagram_api_data['like_count'] : '';
480
+
481
+ $parsed_data = array(
482
+ 'comments_count' => $comments_count,
483
+ 'like_count' => $like_count
484
+ );
485
+
486
+ if ( $all ) {
487
+ $caption = isset( $this->instagram_api_data['caption'] ) ? $this->instagram_api_data['caption'] : '';
488
+ $media_url = isset( $this->instagram_api_data['media_url'] ) ? $this->instagram_api_data['media_url'] : '';
489
+ $media_type = isset( $this->instagram_api_data['media_type'] ) ? $this->instagram_api_data['media_type'] : '';
490
+
491
+ $timestamp = '';
492
+ if ( isset( $this->instagram_api_data['timestamp'] ) ) {
493
+ $timestamp_parts = explode( ' ', $this->instagram_api_data['timestamp'] );
494
+ $timestamp = str_replace( 'T', ' ', $timestamp_parts[0] );
495
+ }
496
+
497
+ $username = isset( $this->instagram_api_data['username'] ) ? $this->instagram_api_data['username'] : '';
498
+ $permalink = isset( $this->instagram_api_data['permalink'] ) ? $this->instagram_api_data['permalink'] : '';
499
+ $children = isset( $this->instagram_api_data['children'] ) ? wp_json_encode( $this->instagram_api_data['children'] ) : '';
500
+
501
+ $parsed_data['caption'] = $caption;
502
+ $parsed_data['media_url'] = $media_url;
503
+ $parsed_data['id'] = $instagram_post_id;
504
+ $parsed_data['media_type'] = $media_type;
505
+ $parsed_data['timestamp'] = $timestamp;
506
+ $parsed_data['username'] = $username;
507
+ $parsed_data['permalink'] = $permalink;
508
+ $parsed_data['children'] = $children;
509
+ }
510
+
511
+ return $parsed_data;
512
+ }
513
+
514
+ /**
515
+ * If a record hasn't been made for this transient name/feed id,
516
+ * make a record
517
+ *
518
+ * @param string $feed_id
519
+ *
520
+ * @since 2.0/4.0
521
+ */
522
+ private function maybe_add_feed_id( $feed_id ) {
523
+
524
+ if ( empty( $this->instagram_post_id ) ) {
525
+ return;
526
+ }
527
+
528
+ global $wpdb;
529
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS;
530
+ // the number is removed from the transient name for backwards compatibilty.
531
+ $feed_id_array = explode( '#', $feed_id );
532
+ $feed_id = $feed_id_array[0];
533
+
534
+ $feed_id_match = $wpdb->get_col( $wpdb->prepare( "SELECT feed_id FROM $table_name WHERE feed_id = %s AND instagram_id = %s", $feed_id, $this->instagram_post_id ) );
535
+
536
+ if ( ! isset( $feed_id_match[0] ) ) {
537
+ $entry_data = array(
538
+ $this->db_id,
539
+ "'" . esc_sql( $this->instagram_post_id ) . "'",
540
+ "'" . esc_sql( $feed_id ) . "'"
541
+ );
542
+ $entry_string = implode( ',',$entry_data );
543
+ $error = $wpdb->query( "INSERT INTO $table_name
544
+ (id,instagram_id,feed_id) VALUES ($entry_string);" );
545
+ }
546
+ }
547
  }
inc/class-sb-instagram-posts-manager.php CHANGED
@@ -1,449 +1,525 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Posts_Manager
4
- *
5
- * Set as a global object to record and report errors as well
6
- * as control aspects of image resizing
7
- *
8
- * @since 2.0/4.0
9
- */
10
-
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- die( '-1' );
13
- }
14
-
15
- class SB_Instagram_Posts_Manager
16
- {
17
- /**
18
- * @var mixed|void
19
- */
20
- var $sbi_options;
21
-
22
- /**
23
- * @var int
24
- */
25
- var $limit;
26
-
27
- /**
28
- * @var array
29
- */
30
- var $errors;
31
-
32
- /**
33
- * @var array
34
- */
35
- var $frontend_errors;
36
-
37
- /**
38
- * @var bool
39
- */
40
- var $resizing_tables_exist;
41
-
42
- /**
43
- * SB_Instagram_Posts_Manager constructor.
44
- */
45
- public function __construct() {
46
- $this->sbi_options = get_option( 'sb_instagram_settings' );
47
- $this->errors = get_option( 'sb_instagram_errors', array() );
48
- $this->ajax_status = get_option( 'sb_instagram_ajax_status', array( 'tested' => false, 'successful' => false ) );
49
- $this->frontend_errors = array();
50
- }
51
-
52
- /**
53
- * @return array
54
- *
55
- * @since 2.0/5.0
56
- */
57
- public function get_ajax_status() {
58
- return $this->ajax_status;
59
- }
60
-
61
- /**
62
- * @param $to_update
63
- *
64
- * @since 2.0/5.0
65
- */
66
- public function update_ajax_status( $to_update ) {
67
- foreach ( $to_update as $key => $value ) {
68
- $this->ajax_status[ $key ] = $value;
69
- }
70
-
71
- update_option( 'sb_instagram_ajax_status', $this->ajax_status );
72
- }
73
-
74
- /**
75
- * When the plugin is first installed and used, an AJAX call to admin-ajax.php
76
- * is made to verify that it's available
77
- *
78
- * @param bool $force_check
79
- *
80
- * @return bool
81
- *
82
- * @since 2.0/5.0
83
- */
84
- public function maybe_start_ajax_test( $force_check = false ) {
85
- if ( ! $this->ajax_status['tested'] || $force_check ) {
86
- set_transient( 'sb_instagram_doing_ajax_test', 'yes', 60*60 );
87
- $this->update_ajax_status( array( 'tested' => true ) );
88
- return true;
89
- }
90
-
91
- return false;
92
- }
93
-
94
- /**
95
- * Called if a successful admin ajax request is made
96
- *
97
- * @since 2.0/5.0
98
- */
99
- public function update_successful_ajax_test() {
100
- $this->update_ajax_status( array( 'successful' => true ) );
101
- }
102
-
103
- /**
104
- * @return bool
105
- *
106
- * @since 2.0/5.0
107
- */
108
- public function should_add_ajax_test_notice() {
109
- return ($this->ajax_status['tested'] && ! $this->ajax_status['successful'] && get_transient( 'sb_instagram_doing_ajax_test' ) !== 'yes');
110
- }
111
-
112
- /**
113
- * The plugin has a limit on how many post records can be stored and
114
- * images resized to avoid overloading servers. This function deletes the post that
115
- * has the longest time passed since it was retrieved.
116
- *
117
- * @since 2.0/4.0
118
- */
119
- public function delete_least_used_image() {
120
- global $wpdb;
121
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
122
- $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
123
-
124
- $max = isset( $this->limit ) && $this->limit > 1 ? $this->limit : 1;
125
-
126
- $oldest_posts = $wpdb->get_results( "SELECT id, media_id FROM $table_name ORDER BY last_requested ASC LIMIT $max", ARRAY_A );
127
-
128
- $upload = wp_upload_dir();
129
- $file_suffixes = array( 'thumb', 'low', 'full' );
130
-
131
- foreach ( $oldest_posts as $post ) {
132
-
133
- foreach ( $file_suffixes as $file_suffix ) {
134
- $file_name = trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $post['media_id'] . $file_suffix . '.jpg';
135
- if ( is_file( $file_name ) ) {
136
- unlink( $file_name );
137
- }
138
- }
139
-
140
- $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE id = %d", $post['id'] ) );
141
- $wpdb->query( $wpdb->prepare( "DELETE FROM $feeds_posts_table_name WHERE record_id = %d", $post['id'] ) );
142
- }
143
-
144
- }
145
-
146
- /**
147
- * Calculates how many records are in the database and whether or not it exceeds the limit
148
- *
149
- * @return bool
150
- *
151
- * @since 2.0/4.0
152
- */
153
- public function max_total_records_reached() {
154
- global $wpdb;
155
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
156
-
157
- $num_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
158
-
159
- if ( !isset( $this->limit ) && (int)$num_records > SBI_MAX_RECORDS ) {
160
- $this->limit = (int)$num_records - SBI_MAX_RECORDS;
161
- }
162
-
163
- return ((int)$num_records > SBI_MAX_RECORDS);
164
- }
165
-
166
- /**
167
- * The plugin caps how many new images are created in a 15 minute window to
168
- * avoid overloading servers
169
- *
170
- * @return bool
171
- *
172
- * @since 2.0/4.0
173
- */
174
- public function max_resizing_per_time_period_reached() {
175
- global $wpdb;
176
- $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
177
-
178
- $fifteen_minutes_ago = date( 'Y-m-d H:i:s', time() - 15 * 60 );
179
-
180
- $num_new_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE created_on > '$fifteen_minutes_ago'" );
181
-
182
- return ((int)$num_new_records > 100);
183
- }
184
-
185
- /**
186
- * @return bool
187
- *
188
- * @since 2.0/4.0
189
- */
190
- public function image_resizing_disabled() {
191
- $disable_resizing = isset( $this->sbi_options['sb_instagram_disable_resize'] ) ? $this->sbi_options['sb_instagram_disable_resize'] === 'on' || $this->sbi_options['sb_instagram_disable_resize'] === true : false;
192
-
193
- if ( ! $disable_resizing ) {
194
- $disable_resizing = isset( $this->resizing_tables_exist ) ? ! $this->resizing_tables_exist : ! $this->does_resizing_tables_exist();
195
- }
196
-
197
- return $disable_resizing;
198
- }
199
-
200
- /**
201
- * Used to skip image resizing if the tables were never successfully
202
- * created
203
- *
204
- * @return bool
205
- *
206
- * @since 2.0/5.0
207
- */
208
- public function does_resizing_tables_exist() {
209
- global $wpdb;
210
-
211
- $table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE );
212
-
213
- if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) {
214
- $this->resizing_tables_exist = false;
215
-
216
- return false;
217
- }
218
-
219
- $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
220
-
221
- if ( $wpdb->get_var( "show tables like '$feeds_posts_table_name'" ) != $feeds_posts_table_name ) {
222
- $this->resizing_tables_exist = false;
223
-
224
- return false;
225
- }
226
-
227
- return true;
228
- }
229
-
230
- /**
231
- * Resets the custom tables and deletes all image files
232
- *
233
- * @since 2.0/4.0
234
- */
235
- public function delete_all_sbi_instagram_posts() {
236
- $upload = wp_upload_dir();
237
-
238
- global $wpdb;
239
-
240
- $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
241
-
242
- $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . '*' ); // get all file names
243
- foreach ( $image_files as $file ) { // iterate files
244
- if ( is_file( $file ) ) {
245
- unlink( $file );
246
- }
247
- }
248
-
249
- $options = get_option( 'sb_instagram_settings', array() );
250
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
251
-
252
- foreach ( $connected_accounts as $account_id => $data ) {
253
-
254
- if ( isset( $data['local_avatar'] ) ) {
255
- $connected_accounts[ $account_id ]['local_avatar'] = false;
256
- }
257
-
258
- }
259
-
260
- $options['connected_accounts'] = $connected_accounts;
261
-
262
- update_option( 'sb_instagram_settings', $options );
263
-
264
- //Delete tables
265
- $wpdb->query( "DROP TABLE IF EXISTS $posts_table_name" );
266
-
267
- $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
268
- $wpdb->query( "DROP TABLE IF EXISTS $feeds_posts_table_name" );
269
-
270
- $table_name = $wpdb->prefix . "options";
271
-
272
- $wpdb->query( "
273
- DELETE
274
- FROM $table_name
275
- WHERE `option_name` LIKE ('%\_transient\_\$sbi\_%')
276
- " );
277
- $wpdb->query( "
278
- DELETE
279
- FROM $table_name
280
- WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sbi\_%')
281
- " );
282
- delete_option( 'sbi_hashtag_ids' );
283
-
284
- $upload = wp_upload_dir();
285
- $upload_dir = $upload['basedir'];
286
- $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
287
- if ( ! file_exists( $upload_dir ) ) {
288
- $created = wp_mkdir_p( $upload_dir );
289
- if ( $created ) {
290
- $this->remove_error( 'upload_dir' );
291
- } else {
292
- $this->add_error( 'upload_dir', array( __( 'There was an error creating the folder for storing resized images.', 'instagram-feed' ), $upload_dir ) );
293
- }
294
- } else {
295
- $this->remove_error( 'upload_dir' );
296
- }
297
-
298
- sbi_create_database_table();
299
- }
300
-
301
- /**
302
- * @return array
303
- *
304
- * @since 2.0/4.0
305
- */
306
- public function get_errors() {
307
- return $this->errors;
308
- }
309
-
310
- /**
311
- * @param $type
312
- * @param $message_array
313
- *
314
- * @since 2.0/4.0
315
- */
316
- public function add_error( $type, $message_array ) {
317
- $this->errors[ $type ] = $message_array;
318
-
319
- update_option( 'sb_instagram_errors', $this->errors, false );
320
- }
321
-
322
- /**
323
- * @param $type
324
- *
325
- * @since 2.0/4.0
326
- */
327
- public function remove_error( $type ) {
328
- if ( isset( $this->errors[ $type ] ) ) {
329
- unset( $this->errors[ $type ] );
330
-
331
- update_option( 'sb_instagram_errors', $this->errors, false );
332
- }
333
- }
334
-
335
- /**
336
- * @param $type
337
- * @param $message
338
- *
339
- * @since 2.0/5.0
340
- */
341
- public function add_frontend_error( $type, $message ) {
342
- $this->frontend_errors[ $type ] = $message;
343
- }
344
-
345
- public function remove_frontend_error( $type ) {
346
- if ( isset( $this->frontend_errors[ $type ] ) ) {
347
- unset( $this->frontend_errors[ $type ] );
348
- }
349
- }
350
-
351
- /**
352
- * @return array
353
- *
354
- * @since 2.0/5.0
355
- */
356
- public function get_frontend_errors() {
357
- if ( isset( $this->frontend_errors['api_delay'] ) ) {
358
- return array( 'api_delay' => $this->frontend_errors['api_delay'] );
359
- }
360
- return $this->frontend_errors;
361
- }
362
-
363
- /**
364
- * @return array
365
- *
366
- * @since 2.0/5.0
367
- */
368
- public function reset_frontend_errors() {
369
- return $this->frontend_errors = array();
370
- }
371
-
372
- public function set_status() {
373
-
374
- }
375
-
376
- public function clear_hashtag_errors() {
377
- $errors = $this->get_errors();
378
-
379
- foreach ( $errors as $error_key => $message ) {
380
- if ( strpos( $error_key, 'ig_no_posts_for_' ) !== false || strpos( $error_key, 'error_18' ) !== false ) {
381
- $this->remove_error( $error_key );
382
- }
383
- }
384
- }
385
-
386
- /**
387
- * @since 2.0/5.1.2
388
- */
389
- public function add_api_request_delay( $time_in_seconds = 300, $account_id = false ) {
390
- if ( $account_id ) {
391
- set_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $account_id, '1', $time_in_seconds );
392
- } else {
393
- set_transient( SBI_USE_BACKUP_PREFIX . 'sbi_delay_requests', '1', $time_in_seconds );
394
- }
395
- }
396
-
397
- /**
398
- * @since 2.0/5.1.2
399
- */
400
- public function are_current_api_request_delays( $account_id = false ) {
401
- $is_delay = (get_transient( SBI_USE_BACKUP_PREFIX . 'sbi_delay_requests' ) !== false);
402
-
403
- if ( $is_delay ) {
404
- $this->reset_frontend_errors();
405
- $error = '<p><b>' . sprintf( __( 'Error: API requests are being delayed.', 'instagram-feed' ) ) . ' ' . __( 'New posts will not be retrieved for at least 5 minutes.', 'instagram-feed' ) . '</b></p>';
406
- $errors = $this->get_errors();
407
- if ( ! empty( $errors ) && current_user_can( 'manage_options' ) ) {
408
- if ( isset( $errors['api'] ) ) {
409
- $error .= '<p>' . $errors['api'][1] . '</p>';
410
- } elseif ( isset( $errors['connection'] ) ) {
411
- $error .= '<p>' . $errors['connection'][1] . '</p>';
412
- }
413
- } else {
414
- $error .= '<p>' . __( 'There may be an issue with the Instagram access token that you are using. Your server might also be unable to connect to Instagram at this time.', 'instagram-feed' ) . '</p>';
415
- }
416
-
417
- foreach ( $errors as $error_key => $message ) {
418
- if ( strpos( $error_key, 'ig_no_posts_for_' ) !== false ) {
419
- if ( (int)$message[0] < (time() - 12 * 60 * 60) ) {
420
- $this->remove_error( $error_key );
421
- } else {
422
- $error .= '<p>' . $message[1] . '</p>';
423
- }
424
- } elseif ( strpos( $error_key, 'error_18' ) !== false ) {
425
- if ( (int)$message[0] < (time() - 24 * 60 * 60) ) {
426
- $this->remove_error( $error_key );
427
- } else {
428
- $error .= '<p>' . $message[1] . '</p>';
429
- }
430
- }
431
- }
432
-
433
- $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
434
- $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
435
- if ( current_user_can( $cap ) ) {
436
- $error .= '<p>' . __( 'Click <a href="https://smashballoon.com/instagram-feed/docs/errors/">here</a> to troubleshoot.', 'instagram-feed' ) . '</p>';
437
- }
438
-
439
- $this->add_frontend_error( 'api_delay', $error );
440
-
441
- }
442
-
443
- if ( ! $is_delay && $account_id ) {
444
- $is_delay = (get_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $account_id ) !== false);
445
- }
446
-
447
- return $is_delay;
448
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Posts_Manager
4
+ *
5
+ * Set as a global object to record and report errors as well
6
+ * as control aspects of image resizing
7
+ *
8
+ * @since 2.0/4.0
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ die( '-1' );
13
+ }
14
+
15
+ class SB_Instagram_Posts_Manager
16
+ {
17
+ /**
18
+ * @var mixed|void
19
+ */
20
+ var $sbi_options;
21
+
22
+ /**
23
+ * @var int
24
+ */
25
+ var $limit;
26
+
27
+ /**
28
+ * @var array
29
+ */
30
+ var $errors;
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ var $frontend_errors;
36
+
37
+ /**
38
+ * @var bool
39
+ */
40
+ var $resizing_tables_exist;
41
+
42
+ /**
43
+ * SB_Instagram_Posts_Manager constructor.
44
+ */
45
+ public function __construct() {
46
+ $this->sbi_options = get_option( 'sb_instagram_settings' );
47
+ $this->errors = get_option( 'sb_instagram_errors', array() );
48
+ $this->ajax_status = get_option( 'sb_instagram_ajax_status', array( 'tested' => false, 'successful' => false ) );
49
+ $this->frontend_errors = array();
50
+ }
51
+
52
+ /**
53
+ * @return array
54
+ *
55
+ * @since 2.0/5.0
56
+ */
57
+ public function get_ajax_status() {
58
+ return $this->ajax_status;
59
+ }
60
+
61
+ /**
62
+ * @param $to_update
63
+ *
64
+ * @since 2.0/5.0
65
+ */
66
+ public function update_ajax_status( $to_update ) {
67
+ foreach ( $to_update as $key => $value ) {
68
+ $this->ajax_status[ $key ] = $value;
69
+ }
70
+
71
+ update_option( 'sb_instagram_ajax_status', $this->ajax_status );
72
+ }
73
+
74
+ /**
75
+ * When the plugin is first installed and used, an AJAX call to admin-ajax.php
76
+ * is made to verify that it's available
77
+ *
78
+ * @param bool $force_check
79
+ *
80
+ * @return bool
81
+ *
82
+ * @since 2.0/5.0
83
+ */
84
+ public function maybe_start_ajax_test( $force_check = false ) {
85
+ if ( ! $this->ajax_status['tested'] || $force_check ) {
86
+ set_transient( 'sb_instagram_doing_ajax_test', 'yes', 60*60 );
87
+ $this->update_ajax_status( array( 'tested' => true ) );
88
+ return true;
89
+ }
90
+
91
+ return false;
92
+ }
93
+
94
+ /**
95
+ * Called if a successful admin ajax request is made
96
+ *
97
+ * @since 2.0/5.0
98
+ */
99
+ public function update_successful_ajax_test() {
100
+ $this->update_ajax_status( array( 'successful' => true ) );
101
+ }
102
+
103
+ /**
104
+ * @return bool
105
+ *
106
+ * @since 2.0/5.0
107
+ */
108
+ public function should_add_ajax_test_notice() {
109
+ return ($this->ajax_status['tested'] && ! $this->ajax_status['successful'] && get_transient( 'sb_instagram_doing_ajax_test' ) !== 'yes');
110
+ }
111
+
112
+ /**
113
+ * The plugin has a limit on how many post records can be stored and
114
+ * images resized to avoid overloading servers. This function deletes the post that
115
+ * has the longest time passed since it was retrieved.
116
+ *
117
+ * @since 2.0/4.0
118
+ */
119
+ public function delete_least_used_image() {
120
+ global $wpdb;
121
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
122
+ $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
123
+
124
+ $max = isset( $this->limit ) && $this->limit > 1 ? $this->limit : 1;
125
+
126
+ $oldest_posts = $wpdb->get_results( "SELECT id, media_id FROM $table_name ORDER BY last_requested ASC LIMIT $max", ARRAY_A );
127
+
128
+ $upload = wp_upload_dir();
129
+ $file_suffixes = array( 'thumb', 'low', 'full' );
130
+
131
+ foreach ( $oldest_posts as $post ) {
132
+
133
+ foreach ( $file_suffixes as $file_suffix ) {
134
+ $file_name = trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . $post['media_id'] . $file_suffix . '.jpg';
135
+ if ( is_file( $file_name ) ) {
136
+ unlink( $file_name );
137
+ }
138
+ }
139
+
140
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE id = %d", $post['id'] ) );
141
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $feeds_posts_table_name WHERE record_id = %d", $post['id'] ) );
142
+ }
143
+
144
+ }
145
+
146
+ /**
147
+ * Calculates how many records are in the database and whether or not it exceeds the limit
148
+ *
149
+ * @return bool
150
+ *
151
+ * @since 2.0/4.0
152
+ */
153
+ public function max_total_records_reached() {
154
+ global $wpdb;
155
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
156
+
157
+ $num_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
158
+
159
+ if ( !isset( $this->limit ) && (int)$num_records > SBI_MAX_RECORDS ) {
160
+ $this->limit = (int)$num_records - SBI_MAX_RECORDS;
161
+ }
162
+
163
+ return ((int)$num_records > SBI_MAX_RECORDS);
164
+ }
165
+
166
+ /**
167
+ * The plugin caps how many new images are created in a 15 minute window to
168
+ * avoid overloading servers
169
+ *
170
+ * @return bool
171
+ *
172
+ * @since 2.0/4.0
173
+ */
174
+ public function max_resizing_per_time_period_reached() {
175
+ global $wpdb;
176
+ $table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
177
+
178
+ $fifteen_minutes_ago = date( 'Y-m-d H:i:s', time() - 15 * 60 );
179
+
180
+ $num_new_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE created_on > '$fifteen_minutes_ago'" );
181
+
182
+ return ((int)$num_new_records > 100);
183
+ }
184
+
185
+ /**
186
+ * @return bool
187
+ *
188
+ * @since 2.0/4.0
189
+ */
190
+ public function image_resizing_disabled() {
191
+ $disable_resizing = isset( $this->sbi_options['sb_instagram_disable_resize'] ) ? $this->sbi_options['sb_instagram_disable_resize'] === 'on' || $this->sbi_options['sb_instagram_disable_resize'] === true : false;
192
+
193
+ if ( ! $disable_resizing ) {
194
+ $disable_resizing = isset( $this->resizing_tables_exist ) ? ! $this->resizing_tables_exist : ! $this->does_resizing_tables_exist();
195
+ }
196
+
197
+ return $disable_resizing;
198
+ }
199
+
200
+ /**
201
+ * Used to skip image resizing if the tables were never successfully
202
+ * created
203
+ *
204
+ * @return bool
205
+ *
206
+ * @since 2.0/5.0
207
+ */
208
+ public function does_resizing_tables_exist() {
209
+ global $wpdb;
210
+
211
+ $table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE );
212
+
213
+ if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) {
214
+ $this->resizing_tables_exist = false;
215
+
216
+ return false;
217
+ }
218
+
219
+ $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
220
+
221
+ if ( $wpdb->get_var( "show tables like '$feeds_posts_table_name'" ) != $feeds_posts_table_name ) {
222
+ $this->resizing_tables_exist = false;
223
+
224
+ return false;
225
+ }
226
+
227
+ return true;
228
+ }
229
+
230
+ /**
231
+ * Resets the custom tables and deletes all image files
232
+ *
233
+ * @since 2.0/4.0
234
+ */
235
+ public function delete_all_sbi_instagram_posts() {
236
+ $upload = wp_upload_dir();
237
+
238
+ global $wpdb;
239
+
240
+ $posts_table_name = $wpdb->prefix . SBI_INSTAGRAM_POSTS_TYPE;
241
+
242
+ $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBI_UPLOADS_NAME ) . '*' ); // get all file names
243
+ foreach ( $image_files as $file ) { // iterate files
244
+ if ( is_file( $file ) ) {
245
+ unlink( $file );
246
+ }
247
+ }
248
+
249
+ $options = get_option( 'sb_instagram_settings', array() );
250
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
251
+
252
+ foreach ( $connected_accounts as $account_id => $data ) {
253
+
254
+ if ( isset( $data['local_avatar'] ) ) {
255
+ $connected_accounts[ $account_id ]['local_avatar'] = false;
256
+ }
257
+
258
+ }
259
+
260
+ $options['connected_accounts'] = $connected_accounts;
261
+
262
+ update_option( 'sb_instagram_settings', $options );
263
+
264
+ //Delete tables
265
+ $wpdb->query( "DROP TABLE IF EXISTS $posts_table_name" );
266
+
267
+ $feeds_posts_table_name = esc_sql( $wpdb->prefix . SBI_INSTAGRAM_FEEDS_POSTS );
268
+ $wpdb->query( "DROP TABLE IF EXISTS $feeds_posts_table_name" );
269
+
270
+ $table_name = $wpdb->prefix . "options";
271
+
272
+ $wpdb->query( "
273
+ DELETE
274
+ FROM $table_name
275
+ WHERE `option_name` LIKE ('%\_transient\_\$sbi\_%')
276
+ " );
277
+ $wpdb->query( "
278
+ DELETE
279
+ FROM $table_name
280
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sbi\_%')
281
+ " );
282
+ delete_option( 'sbi_hashtag_ids' );
283
+
284
+ $upload = wp_upload_dir();
285
+ $upload_dir = $upload['basedir'];
286
+ $upload_dir = trailingslashit( $upload_dir ) . SBI_UPLOADS_NAME;
287
+ if ( ! file_exists( $upload_dir ) ) {
288
+ $created = wp_mkdir_p( $upload_dir );
289
+ if ( $created ) {
290
+ $this->remove_error( 'upload_dir' );
291
+ } else {
292
+ $this->add_error( 'upload_dir', array( __( 'There was an error creating the folder for storing resized images.', 'instagram-feed' ), $upload_dir ) );
293
+ }
294
+ } else {
295
+ $this->remove_error( 'upload_dir' );
296
+ }
297
+
298
+ sbi_create_database_table();
299
+ }
300
+
301
+ /**
302
+ * @return array
303
+ *
304
+ * @since 2.0/4.0
305
+ */
306
+ public function get_errors() {
307
+ return $this->errors;
308
+ }
309
+
310
+ /**
311
+ * @param $type
312
+ * @param $message_array
313
+ *
314
+ * @since 2.0/4.0
315
+ */
316
+ public function add_error( $type, $message_array ) {
317
+ $this->errors[ $type ] = $message_array;
318
+
319
+ update_option( 'sb_instagram_errors', $this->errors, false );
320
+ }
321
+
322
+ /**
323
+ * @param $type
324
+ *
325
+ * @since 2.0/4.0
326
+ */
327
+ public function remove_error( $type ) {
328
+ if ( isset( $this->errors[ $type ] ) ) {
329
+ unset( $this->errors[ $type ] );
330
+
331
+ update_option( 'sb_instagram_errors', $this->errors, false );
332
+ }
333
+ }
334
+
335
+ public function remove_all_errors() {
336
+ delete_option( 'sb_instagram_errors' );
337
+ delete_option( 'sb_instagram_error_page' );
338
+ sb_instagram_cron_clear_cache();
339
+ }
340
+
341
+ public function update_error_page( $id ) {
342
+ if ( $id !== 0 ) {
343
+ update_option( 'sb_instagram_error_page', $id, false );
344
+ }
345
+ }
346
+
347
+ public function get_error_page() {
348
+ return get_option( 'sb_instagram_error_page', false );
349
+ }
350
+
351
+ /**
352
+ * @param $type
353
+ * @param $message
354
+ *
355
+ * @since 2.0/5.0
356
+ */
357
+ public function add_frontend_error( $type, $message ) {
358
+ $this->frontend_errors = array();
359
+ $this->frontend_errors[ $type ] = $message;
360
+ }
361
+
362
+ public function remove_frontend_error( $type ) {
363
+ if ( isset( $this->frontend_errors[ $type ] ) ) {
364
+ unset( $this->frontend_errors[ $type ] );
365
+ }
366
+ }
367
+
368
+ /**
369
+ * @return array
370
+ *
371
+ * @since 2.0/5.0
372
+ */
373
+ public function get_frontend_errors() {
374
+ if ( isset( $this->frontend_errors['api_delay'] ) ) {
375
+ return array( 'api_delay' => $this->frontend_errors['api_delay'] );
376
+ }
377
+ return $this->frontend_errors;
378
+ }
379
+
380
+ public function get_critical_errors() {
381
+ $errors = $this->get_errors();
382
+ $error = '';
383
+ $error_100_found = false;
384
+ $reconnect_instructions_needed = false;
385
+ $cap = current_user_can( 'manage_instagram_feed_options' ) ? 'manage_instagram_feed_options' : 'manage_options';
386
+ $cap = apply_filters( 'sbi_settings_pages_capability', $cap );
387
+ $hash = '';
388
+ if ( ! empty( $errors ) && current_user_can( $cap ) ) {
389
+ if ( isset( $errors['api'] ) ) {
390
+ $error .= '<p>' . $errors['api'][1] . '</p>';
391
+ if ( isset( $errors['api'][2] ) ) {
392
+ $hash = '#' . $errors['api'][2];
393
+ }
394
+ } elseif ( isset( $errors['connection'] ) ) {
395
+ $error .= '<p>' . $errors['connection'][1] . '</p>';
396
+ if ( isset( $errors['connection'][2] ) ) {
397
+ $hash = '#' . $errors['connection'][2];
398
+ }
399
+ } else {
400
+ foreach ( $errors as $key => $value ) {
401
+ if ( strpos( $key, 'at_' ) !== false ) {
402
+ $reconnect_instructions_needed = true;
403
+
404
+ $error = '<p>' . $value[1] . '</p>';
405
+ if ( strpos( $key, 'at_100' ) !== false ) {
406
+ $error_100_found = true;
407
+ }
408
+ }
409
+ if ( isset( $value[2] ) ) {
410
+ $hash = '#' . $value[2];
411
+ }
412
+ }
413
+ }
414
+ } else {
415
+ return '';
416
+ }
417
+
418
+ foreach ( $errors as $error_key => $message ) {
419
+ if ( strpos( $error_key, 'ig_no_posts_for_' ) !== false ) {
420
+ if ( (int)$message[0] < (time() - 12 * 60 * 60) ) {
421
+ $this->remove_error( $error_key );
422
+ } else {
423
+ $error .= '<p>' . $message[1] . '</p>';
424
+ }
425
+ } elseif ( strpos( $error_key, 'error_18' ) !== false ) {
426
+ if ( (int)$message[0] < (time() - 24 * 60 * 60) ) {
427
+ $this->remove_error( $error_key );
428
+ } else {
429
+ $error .= '<p>' . $message[1] . '</p>';
430
+ }
431
+ }
432
+ }
433
+
434
+
435
+ if ( current_user_can( $cap ) ) {
436
+ if ( $reconnect_instructions_needed && ! $error_100_found ) {
437
+ $on_configure_page = (is_admin() && (! isset( $_GET['tab']) || $_GET['tab'] === 'configure'));
438
+ if ( $on_configure_page ) {
439
+ $error .= '<p class="sbi-error-directions sbi-reconnect"><a href="https://smashballoon.com/instagram-feed/docs/errors/' . $hash . '" target="_blank" rel="noopener">' . __( 'Reconnect Account and Refresh Token', 'instagram-feed' ) . '</a></p>';
440
+ } else {
441
+ $link = admin_url( '?page=sb-instagram-feed' );
442
+ $error .= '<p class="sbi-error-directions sbi-reconnect"><a href="'. esc_url( $link ).'" target="_blank" rel="noopener">' . __( 'Reconnect Your Account in the Admin Area', 'instagram-feed' ) . '</a></p>';
443
+ }
444
+ } else {
445
+ $error .= '<p class="sbi-error-directions"><a href="https://smashballoon.com/instagram-feed/docs/errors/' . $hash . '" target="_blank" rel="noopener">' . __( 'Directions on How to Resolve This Issue', 'instagram-feed' ) . '</a></p>';
446
+ }
447
+ }
448
+
449
+ // remove link to FB docs
450
+ $error = str_replace( 'Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api', '', $error );
451
+
452
+ return $error;
453
+ }
454
+
455
+ /**
456
+ * @return array
457
+ *
458
+ * @since 2.0/5.0
459
+ */
460
+ public function reset_frontend_errors() {
461
+ return $this->frontend_errors = array();
462
+ }
463
+
464
+
465
+ public function clear_hashtag_errors() {
466
+ $errors = $this->get_errors();
467
+
468
+ foreach ( $errors as $error_key => $message ) {
469
+ if ( strpos( $error_key, 'ig_no_posts_for_' ) !== false || strpos( $error_key, 'error_18' ) !== false ) {
470
+ $this->remove_error( $error_key );
471
+ }
472
+ }
473
+ }
474
+
475
+ /**
476
+ * @since 2.0/5.1.2
477
+ */
478
+ public function add_api_request_delay( $time_in_seconds = 300, $account_id = false ) {
479
+ if ( $account_id ) {
480
+ set_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $account_id, '1', $time_in_seconds );
481
+ } else {
482
+ set_transient( SBI_USE_BACKUP_PREFIX . 'sbi_delay_requests', '1', $time_in_seconds );
483
+ }
484
+ }
485
+
486
+ /**
487
+ * @since 2.0/5.1.2
488
+ */
489
+ public function are_current_api_request_delays( $account_id = false ) {
490
+ $is_delay = (get_transient( SBI_USE_BACKUP_PREFIX . 'sbi_delay_requests' ) !== false);
491
+
492
+ if ( $is_delay ) {
493
+ $this->reset_frontend_errors();
494
+ $error = '<p><b>' . sprintf( __( 'Error: API requests are being delayed.', 'instagram-feed' ) ) . ' ' . __( 'New posts will not be retrieved for at least 5 minutes.', 'instagram-feed' ) . '</b></p>';
495
+ $error .= $this->get_critical_errors();
496
+
497
+ $this->add_frontend_error( 'api_delay', $error );
498
+
499
+ }
500
+
501
+ if ( ! $is_delay && $account_id ) {
502
+ $is_delay = (get_transient( SBI_USE_BACKUP_PREFIX . 'sbi_' . $account_id ) !== false);
503
+ }
504
+
505
+ return $is_delay;
506
+ }
507
+
508
+ public function are_critical_errors() {
509
+ $errors = $this->get_errors();
510
+
511
+ $are_errors = false;
512
+
513
+ foreach ( $errors as $error_key => $message ) {
514
+ if ( strpos( $error_key, 'connection' ) !== false ) {
515
+ $are_errors = true;
516
+ } elseif ( strpos( $error_key, 'api' ) !== false ) {
517
+ $are_errors = true;
518
+ } elseif ( strpos( $error_key, 'at_' ) !== false ) {
519
+ $are_errors = true;
520
+ }
521
+ }
522
+
523
+ return $are_errors;
524
+ }
525
  }
inc/class-sb-instagram-settings.php CHANGED
@@ -1,598 +1,604 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Settings
4
- *
5
- * Creates organized settings from shortcode settings and settings
6
- * from the options table.
7
- *
8
- * Also responsible for creating transient names/feed ids based on
9
- * feed settings
10
- *
11
- * @since 2.0/5.0
12
- */
13
-
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- die( '-1' );
16
- }
17
-
18
- class SB_Instagram_Settings {
19
- /**
20
- * @var array
21
- */
22
- protected $atts;
23
-
24
- /**
25
- * @var array
26
- */
27
- protected $db;
28
-
29
- /**
30
- * @var array
31
- */
32
- protected $settings;
33
-
34
- /**
35
- * @var array
36
- */
37
- protected $feed_type_and_terms;
38
-
39
- /**
40
- * @var array
41
- */
42
- protected $connected_accounts;
43
-
44
- /**
45
- * @var array
46
- */
47
- protected $connected_accounts_in_feed;
48
-
49
- /**
50
- * @var string
51
- */
52
- protected $transient_name;
53
-
54
- /**
55
- * SB_Instagram_Settings constructor.
56
- *
57
- * Overwritten in the Pro version.
58
- *
59
- * @param array $atts shortcode settings
60
- * @param array $db settings from the wp_options table
61
- */
62
- public function __construct( $atts, $db ) {
63
- $this->atts = $atts;
64
- $this->db = $db;
65
-
66
- $this->connected_accounts = isset( $db['connected_accounts'] ) ? $db['connected_accounts'] : array();
67
-
68
- $this->settings = shortcode_atts(
69
- array(
70
- 'id' => isset( $db['sb_instagram_user_id'] ) ? $db['sb_instagram_user_id'] : '',
71
- 'width' => isset( $db['sb_instagram_width'] ) ? $db['sb_instagram_width'] : '',
72
- 'widthunit' => isset( $db['sb_instagram_width_unit'] ) ? $db['sb_instagram_width_unit'] : '',
73
- 'widthresp' => isset( $db['sb_instagram_feed_width_resp'] ) ? $db['sb_instagram_feed_width_resp'] : '',
74
- 'height' => isset( $db['sb_instagram_height'] ) ? $db['sb_instagram_height'] : '',
75
- 'heightunit' => isset( $db['sb_instagram_height_unit'] ) ? $db['sb_instagram_height_unit'] : '',
76
- 'sortby' => isset( $db['sb_instagram_sort'] ) ? $db['sb_instagram_sort'] : '',
77
- 'num' => isset( $db['sb_instagram_num'] ) ? $db['sb_instagram_num'] : '',
78
- 'apinum' => isset( $db['sb_instagram_minnum'] ) ? $db['sb_instagram_minnum'] : '',
79
- 'nummobile' => isset($db[ 'sb_instagram_nummobile' ]) ? $db[ 'sb_instagram_nummobile' ] : '',
80
- 'cols' => isset( $db['sb_instagram_cols'] ) ? $db['sb_instagram_cols'] : '',
81
- 'disablemobile' => isset( $db['sb_instagram_disable_mobile'] ) ? $db['sb_instagram_disable_mobile'] : '',
82
- 'imagepadding' => isset( $db['sb_instagram_image_padding'] ) ? $db['sb_instagram_image_padding'] : '',
83
- 'imagepaddingunit' => isset( $db['sb_instagram_image_padding_unit'] ) ? $db['sb_instagram_image_padding_unit'] : '',
84
- 'background' => isset( $db['sb_instagram_background'] ) ? $db['sb_instagram_background'] : '',
85
- 'showbutton' => isset( $db['sb_instagram_show_btn'] ) ? $db['sb_instagram_show_btn'] : '',
86
- 'buttoncolor' => isset( $db['sb_instagram_btn_background'] ) ? $db['sb_instagram_btn_background'] : '',
87
- 'buttontextcolor' => isset( $db['sb_instagram_btn_text_color'] ) ? $db['sb_instagram_btn_text_color'] : '',
88
- 'buttontext' => isset( $db['sb_instagram_btn_text'] ) ? $db['sb_instagram_btn_text'] : '',
89
- 'imageres' => isset( $db['sb_instagram_image_res'] ) ? $db['sb_instagram_image_res'] : '',
90
- 'showfollow' => isset( $db['sb_instagram_show_follow_btn'] ) ? $db['sb_instagram_show_follow_btn'] : '',
91
- 'followcolor' => isset( $db['sb_instagram_folow_btn_background'] ) ? $db['sb_instagram_folow_btn_background'] : '',
92
- 'followtextcolor' => isset( $db['sb_instagram_follow_btn_text_color'] ) ? $db['sb_instagram_follow_btn_text_color'] : '',
93
- 'followtext' => isset( $db['sb_instagram_follow_btn_text'] ) ? $db['sb_instagram_follow_btn_text'] : '',
94
- 'showheader' => isset( $db['sb_instagram_show_header'] ) ? $db['sb_instagram_show_header'] : '',
95
- 'headersize' => isset( $db['sb_instagram_header_size'] ) ? $db['sb_instagram_header_size'] : '',
96
- 'showbio' => isset( $db['sb_instagram_show_bio'] ) ? $db['sb_instagram_show_bio'] : '',
97
- 'custombio' => isset($db[ 'sb_instagram_custom_bio' ]) ? $db[ 'sb_instagram_custom_bio' ] : '',
98
- 'customavatar' => isset($db[ 'sb_instagram_custom_avatar' ]) ? $db[ 'sb_instagram_custom_avatar' ] : '',
99
- 'headercolor' => isset( $db['sb_instagram_header_color'] ) ? $db['sb_instagram_header_color'] : '',
100
- 'class' => '',
101
- 'ajaxtheme' => isset( $db['sb_instagram_ajax_theme'] ) ? $db['sb_instagram_ajax_theme'] : '',
102
- 'cachetime' => isset( $db['sb_instagram_cache_time'] ) ? $db['sb_instagram_cache_time'] : '',
103
- 'media' => isset( $db['sb_instagram_media_type'] ) ? $db['sb_instagram_media_type'] : '',
104
- 'headeroutside' => isset($db[ 'sb_instagram_outside_scrollable' ]) ? $db[ 'sb_instagram_outside_scrollable' ] : '',
105
- 'accesstoken' => '',
106
- 'user' => isset( $db['sb_instagram_user'] ) ? $db['sb_instagram_user'] : false,
107
- 'feedid' => isset( $db['sb_instagram_feed_id'] ) ? $db['sb_instagram_feed_id'] : false,
108
- 'resizeprocess' => isset( $db['sb_instagram_resizeprocess'] ) ? $db['sb_instagram_resizeprocess'] : 'background',
109
- 'customtemplates' => isset( $db['custom_template'] ) ? $db['custom_template'] : '',
110
-
111
- ), $atts );
112
-
113
- $this->settings['customtemplates'] = $this->settings['customtemplates'] === 'true' || $this->settings['customtemplates'] === 'on';
114
- if ( isset( $_GET['sbi_debug'] ) ) {
115
- $this->settings['customtemplates'] = false;
116
- }
117
- $this->settings['minnum'] = max( (int)$this->settings['num'], (int)$this->settings['nummobile'] );
118
- $this->settings['showbio'] = $this->settings['showbio'] === 'true' || $this->settings['showbio'] === 'on' || $this->settings['showbio'] === true;
119
- if ( isset( $atts['showbio'] ) && $atts['showbio'] === 'false' ) {
120
- $this->settings['showbio'] = false;
121
- }
122
- if ( isset( $atts['showheader'] ) && $atts['showheader'] === 'false' ) {
123
- $this->settings['showheader'] = false;
124
- }
125
- $this->settings['disable_resize'] = isset( $db['sb_instagram_disable_resize'] ) && ($db['sb_instagram_disable_resize'] === 'on');
126
- $this->settings['favor_local'] = isset( $db['sb_instagram_favor_local'] ) && ($db['sb_instagram_favor_local'] === 'on');
127
- $this->settings['backup_cache_enabled'] = ! isset( $db['sb_instagram_backup'] ) || ($db['sb_instagram_backup'] === 'on');
128
- $this->settings['font_method'] = isset( $db['sbi_font_method'] ) ? $db['sbi_font_method'] : 'svg';
129
- $this->settings['headeroutside'] = ($this->settings['headeroutside'] === true || $this->settings['headeroutside'] === 'on' || $this->settings['headeroutside'] === 'true');
130
- $this->settings['disable_js_image_loading'] = isset( $db['disable_js_image_loading'] ) && ($db['disable_js_image_loading'] === 'on');
131
- $this->settings['ajax_post_load'] = isset( $db['sb_ajax_initial'] ) && ($db['sb_ajax_initial'] === 'on');
132
-
133
- switch ( $db['sbi_cache_cron_interval'] ) {
134
- case '30mins' :
135
- $this->settings['sbi_cache_cron_interval'] = 60*30;
136
- break;
137
- case '1hour' :
138
- $this->settings['sbi_cache_cron_interval'] = 60*60;
139
- break;
140
- default :
141
- $this->settings['sbi_cache_cron_interval'] = 60*60*12;
142
- }
143
-
144
- $this->settings['sb_instagram_cache_time'] = isset( $this->db['sb_instagram_cache_time'] ) ? $this->db['sb_instagram_cache_time'] : 1;
145
- $this->settings['sb_instagram_cache_time_unit'] = isset( $this->db['sb_instagram_cache_time_unit'] ) ? $this->db['sb_instagram_cache_time_unit'] : 'hours';
146
-
147
- global $sb_instagram_posts_manager;
148
-
149
- if ( $sb_instagram_posts_manager->are_current_api_request_delays() ) {
150
- $this->settings['alwaysUseBackup'] = true;
151
- }
152
- }
153
-
154
- /**
155
- * @return array
156
- *
157
- * @since 2.0/5.0
158
- */
159
- public function get_settings() {
160
- return $this->settings;
161
- }
162
-
163
- /**
164
- * The plugin will output settings on the frontend for debugging purposes.
165
- * Safe settings to display are added here.
166
- *
167
- * Overwritten in the Pro version.
168
- *
169
- * @return array
170
- *
171
- * @since 2.0/5.0
172
- */
173
- public static function get_public_db_settings_keys() {
174
- $public = array(
175
- 'sb_instagram_user_id',
176
- 'sb_instagram_cache_time',
177
- 'sb_instagram_cache_time_unit',
178
- 'sbi_caching_type',
179
- 'sbi_cache_cron_interval',
180
- 'sbi_cache_cron_time',
181
- 'sbi_cache_cron_am_pm',
182
- 'sb_instagram_width',
183
- 'sb_instagram_width_unit',
184
- 'sb_instagram_feed_width_resp',
185
- 'sb_instagram_height',
186
- 'sb_instagram_num',
187
- 'sb_instagram_height_unit',
188
- 'sb_instagram_cols',
189
- 'sb_instagram_disable_mobile',
190
- 'sb_instagram_image_padding',
191
- 'sb_instagram_image_padding_unit',
192
- 'sb_instagram_sort',
193
- 'sb_instagram_background',
194
- 'sb_instagram_show_btn',
195
- 'sb_instagram_btn_background',
196
- 'sb_instagram_btn_text_color',
197
- 'sb_instagram_btn_text',
198
- 'sb_instagram_image_res',
199
- //Header
200
- 'sb_instagram_show_header',
201
- 'sb_instagram_header_size',
202
- 'sb_instagram_header_color',
203
- //Follow button
204
- 'sb_instagram_show_follow_btn',
205
- 'sb_instagram_folow_btn_background',
206
- 'sb_instagram_follow_btn_text_color',
207
- 'sb_instagram_follow_btn_text',
208
- //Misc
209
- 'sb_instagram_cron',
210
- 'sb_instagram_backup',
211
- 'sb_instagram_ajax_theme',
212
- 'sb_instagram_disable_resize',
213
- 'disable_js_image_loading',
214
- 'enqueue_js_in_head',
215
- 'sbi_font_method',
216
- 'sb_instagram_disable_awesome',
217
- 'sb_ajax_initial',
218
- 'use_custom'
219
- );
220
-
221
- return $public;
222
- }
223
-
224
- /**
225
- * @return array
226
- *
227
- * @since 2.0/5.0
228
- */
229
- public function get_connected_accounts() {
230
- return $this->connected_accounts;
231
- }
232
-
233
- /**
234
- * @return array|bool
235
- *
236
- * @since 2.0/5.0
237
- */
238
- public function get_connected_accounts_in_feed() {
239
- if ( isset( $this->connected_accounts_in_feed ) ) {
240
- return $this->connected_accounts_in_feed;
241
- } else {
242
- return false;
243
- }
244
- }
245
-
246
- /**
247
- * @return bool|string
248
- *
249
- * @since 2.0/5.0
250
- */
251
- public function get_transient_name() {
252
- if ( isset( $this->transient_name ) ) {
253
- return $this->transient_name;
254
- } else {
255
- return false;
256
- }
257
- }
258
-
259
- /**
260
- * Uses the feed types and terms as well as as some
261
- * settings to create a semi-unique feed id used for
262
- * caching and other features.
263
- *
264
- * Overwritten in the Pro version.
265
- *
266
- * @param string $transient_name
267
- *
268
- * @since 2.0/5.0
269
- */
270
- public function set_transient_name( $transient_name = '' ) {
271
-
272
- if ( ! empty( $transient_name ) ) {
273
- $this->transient_name = $transient_name;
274
- } elseif ( ! empty( $this->settings['feedid'] ) ) {
275
- $this->transient_name = 'sbi_' . $this->settings['feedid'];
276
- } else {
277
- $feed_type_and_terms = $this->feed_type_and_terms;
278
-
279
- $sbi_transient_name = 'sbi_';
280
-
281
- if ( isset( $feed_type_and_terms['users'] ) ) {
282
- foreach ( $feed_type_and_terms['users'] as $term_and_params ) {
283
- $user = $term_and_params['term'];
284
- $connected_account = $this->connected_accounts_in_feed[ $user ];
285
- if ( isset( $connected_account['type'] ) && $connected_account['type'] === 'business' ) {
286
- $sbi_transient_name .= $connected_account['username'];
287
- } else {
288
- $sbi_transient_name .= $user;
289
- }
290
- }
291
- }
292
-
293
- $num = $this->settings['num'];
294
-
295
- $num_length = strlen( $num ) + 1;
296
-
297
- //Add both parts of the caching string together and make sure it doesn't exceed 45
298
- $sbi_transient_name = substr( $sbi_transient_name, 0, 45 - $num_length );
299
-
300
- $sbi_transient_name .= '#' . $num;
301
-
302
- $this->transient_name = $sbi_transient_name;
303
- }
304
-
305
- }
306
-
307
- /**
308
- * @return array|bool
309
- *
310
- * @since 2.0/5.0
311
- */
312
- public function get_feed_type_and_terms() {
313
- if ( isset( $this->feed_type_and_terms ) ) {
314
- return $this->feed_type_and_terms;
315
- } else {
316
- return false;
317
- }
318
- }
319
-
320
- /**
321
- * Based on the settings related to retrieving post data from the API,
322
- * this setting is used to make sure all endpoints needed for the feed are
323
- * connected and stored for easily looping through when adding posts
324
- *
325
- * Overwritten in the Pro version.
326
- *
327
- * @since 2.0/5.0
328
- */
329
- public function set_feed_type_and_terms() {
330
- global $sb_instagram_posts_manager;
331
-
332
- $connected_accounts_in_feed = array();
333
- $feed_type_and_terms = array(
334
- 'users' => array()
335
- );
336
- $usernames_included = array();
337
- $is_after_deprecation_deadline = sbi_is_after_deprecation_deadline();
338
- $is_using_access_token_in_shortcode = ! empty( $this->atts['accesstoken'] ) && strpos( $this->atts['accesstoken'], '.' ) !== false;
339
- $users_connected_to_old_api_only = array();
340
- $settings_link = '<a href="'.get_admin_url().'?page=sb-instagram-feed" target="_blank">' . __( 'plugin Settings page', 'instagram-feed' ) . '</a>';
341
-
342
- // if using an access token in the shortcode and after the deadline, try to use a connected account by collecting the user IDs
343
- if ( $is_after_deprecation_deadline && $is_using_access_token_in_shortcode ) {
344
- $error = '<p><b>' . __( 'Error: Cannot add access token directly to the shortcode.', 'instagram-feed' ) . '</b><br>' . sprintf( __( 'Due to recent Instagram platform changes, it\'s no longer possible to create a feed by adding the access token to the shortcode. Remove the access token from the shortcode and connect an account on the %s instead.', 'instagram-feed' ), $settings_link );
345
-
346
- $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
347
-
348
- $this->settings['id'] = array();
349
- $access_tokens = explode( ',', str_replace( ' ', '', $this->atts['accesstoken'] ) );
350
-
351
- foreach ( $access_tokens as $access_token ) {
352
- $split_token = explode( '.', $access_token );
353
- $this->settings['id'][] = $split_token[0];
354
- }
355
- }
356
-
357
- if ( ! $is_after_deprecation_deadline && $is_using_access_token_in_shortcode ) {
358
- $error = '<p><b>' . __( 'Warning: Cannot add access token directly to the shortcode.', 'instagram-feed' ) . '</b><br>' . sprintf( __( 'Due to upcoming Instagram platform changes on March 31, 2020, it will no longer be possible for feeds to use access tokens directly in the shortcode. Remove the access token from the shortcode and connect an account on the %s instead.', 'instagram-feed' ), $settings_link );
359
-
360
- $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
361
- $access_tokens = explode( ',', str_replace( ' ', '', $this->atts['accesstoken'] ) );
362
-
363
- foreach ( $access_tokens as $access_token ) {
364
- $split_token = explode( '.', $access_token );
365
- $connected_accounts_in_feed[ $split_token[0] ] = array(
366
- 'access_token' => $access_token,
367
- 'user_id' => $split_token[0]
368
- );
369
- $feed_type_and_terms['users'][] = array(
370
- 'term' => $split_token[0],
371
- 'params' => array()
372
- );
373
- }
374
-
375
- } elseif ( ! empty( $this->settings['user'] ) ) {
376
- $user_array = is_array( $this->settings['user'] ) ? $this->settings['user'] : explode( ',', str_replace( ' ', '', $this->settings['user'] ) );
377
- foreach ( $user_array as $user ) {
378
- $user_found = false;
379
- $user_for_deprecated_personal_account_only_found = false;
380
- $term_for_this_user = array();
381
- $username_to_match = $user;
382
-
383
- if ( isset( $this->connected_accounts[ $user ] ) ) {
384
- if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
385
- $term_for_this_user = array(
386
- 'term' => $this->connected_accounts[ $user ]['user_id'],
387
- 'params' => array()
388
- );
389
- $connected_accounts_in_feed[ $this->connected_accounts[ $user ]['user_id'] ] = $this->connected_accounts[ $user ];
390
- $usernames_included[] = $this->connected_accounts[ $user ]['username'];
391
- $username_to_match = $this->connected_accounts[ $user ]['username'];
392
- $user_found = true;
393
- if ( ! isset( $this->connected_accounts[ $user ]['type'] ) || $this->connected_accounts[ $user ]['type'] === 'personal' ) {
394
- $user_for_deprecated_personal_account_only_found = true;
395
- }
396
- }
397
- }
398
-
399
- if ( ! $user_found || $user_for_deprecated_personal_account_only_found ) {
400
- foreach ( $this->connected_accounts as $connected_account ) {
401
- $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
402
- if ( strtolower( $username_to_match ) === strtolower( $connected_account['username'] ) ) {
403
- if ( $user_for_deprecated_personal_account_only_found || ! in_array( $connected_account['username'], $usernames_included, true ) ) {
404
- if ( $account_type !== 'personal' ) {
405
- $term_for_this_user = array(
406
- 'term' => $user,
407
- 'params' => array()
408
- );
409
- $connected_accounts_in_feed[ $user ] = $connected_account;
410
- $user_for_deprecated_personal_account_only_found = false;
411
- } else {
412
- $term_for_this_user = array(
413
- 'term' => $connected_account['user_id'],
414
- 'params' => array()
415
- );
416
- $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
417
- }
418
- $usernames_included[] = $connected_account['username'];
419
- $user_found = true;
420
- }
421
- }
422
- }
423
- }
424
-
425
- if ( ! empty( $term_for_this_user ) ) {
426
- $feed_type_and_terms['users'][] = $term_for_this_user;
427
- }
428
-
429
- if ( ! $user_found ) {
430
- $error = '<p><b>' . sprintf( __( 'Error: There is no connected account for the user %s.', 'instagram-feed' ), $user ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b>';
431
-
432
- $sb_instagram_posts_manager->add_frontend_error( 'no_connection_' . $user, $error );
433
- }
434
-
435
- if ( $user_for_deprecated_personal_account_only_found
436
- && ! in_array( $user, $users_connected_to_old_api_only, true ) ) {
437
- $users_connected_to_old_api_only[] = $connected_accounts_in_feed[ $user ]['username'];
438
- }
439
-
440
- }
441
-
442
- } elseif ( ! empty( $this->settings['id'] ) ) {
443
- $user_id_array = is_array( $this->settings['id'] ) ? $this->settings['id'] : explode( ',', str_replace( ' ', '', $this->settings['id'] ) );
444
-
445
- foreach ( $user_id_array as $user ) {
446
- $user_found = false;
447
- $user_for_deprecated_personal_account_only_found = false;
448
- $term_for_this_user = array();
449
- $username_to_match = '';
450
-
451
- if ( isset( $this->connected_accounts[ $user ] ) ) {
452
- if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
453
- $term_for_this_user = array(
454
- 'term' => $this->connected_accounts[ $user ]['user_id'],
455
- 'params' => array()
456
- );
457
- $connected_accounts_in_feed[ $this->connected_accounts[ $user ]['user_id'] ] = $this->connected_accounts[ $user ];
458
- if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
459
- $usernames_included[] = $this->connected_accounts[ $user ]['username'];
460
- }
461
- $username_to_match = $this->connected_accounts[ $user ]['username'];
462
- $user_found = true;
463
- if ( ! isset( $this->connected_accounts[ $user ]['type'] ) || $this->connected_accounts[ $user ]['type'] === 'personal' ) {
464
- $user_for_deprecated_personal_account_only_found = true;
465
- }
466
- }
467
-
468
- }
469
-
470
- if ( ! $user_found || $user_for_deprecated_personal_account_only_found ) {
471
-
472
- foreach ( $this->connected_accounts as $connected_account ) {
473
- $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
474
- $old_id_matches = ($account_type === 'basic' && isset( $connected_account['old_user_id'] ) && (string)$connected_account['old_user_id'] === (string)$user);
475
- if ( $old_id_matches
476
- || (strtolower( $username_to_match ) === strtolower( $connected_account['username'] )) ) {
477
- if ( $user_for_deprecated_personal_account_only_found || ! in_array( $connected_account['username'], $usernames_included, true ) ) {
478
- if ( $account_type !== 'personal' ) {
479
- $term_for_this_user = array(
480
- 'term' => $user,
481
- 'params' => array()
482
- );
483
- $connected_accounts_in_feed[ $user ] = $connected_account;
484
- $user_for_deprecated_personal_account_only_found = false;
485
- } else {
486
- $term_for_this_user = array(
487
- 'term' => $connected_account['user_id'],
488
- 'params' => array()
489
- );
490
- $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
491
- }
492
- if ( ! in_array( $connected_account['username'], $usernames_included, true ) ) {
493
- $usernames_included[] = $connected_account['username'];
494
- }
495
- $user_found = true;
496
- }
497
- }
498
- }
499
-
500
- }
501
-
502
- if ( ! empty( $term_for_this_user ) ) {
503
- $feed_type_and_terms['users'][] = $term_for_this_user;
504
- }
505
-
506
- if ( ! $user_found ) {
507
- $error = '<p><b>' . sprintf( __( 'Error: There is no connected account for the user %s', 'instagram-feed' ), $user ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b>';
508
-
509
- $sb_instagram_posts_manager->add_frontend_error( 'no_connection_' . $user, $error );
510
- }
511
-
512
- if ( $user_for_deprecated_personal_account_only_found
513
- && ! in_array( $user, $users_connected_to_old_api_only, true ) ) {
514
- $users_connected_to_old_api_only[] = $connected_accounts_in_feed[ $user ]['username'];
515
- }
516
-
517
- }
518
-
519
- } else {
520
- foreach ( $this->connected_accounts as $connected_account ) {
521
- $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
522
-
523
- if ( empty( $feed_type_and_terms['users'] ) ) {
524
- if ( $account_type !== 'personal' ) {
525
- $feed_type_and_terms['users'][] = array(
526
- 'term' => $connected_account['username'],
527
- 'params' => array()
528
- );
529
- $connected_accounts_in_feed[ $connected_account['username'] ] = $connected_account;
530
- } elseif ( ! $is_after_deprecation_deadline ) {
531
- $feed_type_and_terms['users'][] = array(
532
- 'term' => $connected_account['user_id'],
533
- 'params' => array()
534
- );
535
- $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
536
- }
537
- }
538
-
539
- }
540
- }
541
-
542
- if ( ! empty( $users_connected_to_old_api_only ) ) {
543
- $total = count( $users_connected_to_old_api_only );
544
- if ( $total > 1 ) {
545
- $user_string = '';
546
- $i = 0;
547
-
548
- foreach ( $users_connected_to_old_api_only as $username ) {
549
- if ( ($i + 1) === $total ) {
550
- $user_string .= ' and ' . $username;
551
- } else {
552
- if ( $i !== 0 ) {
553
- $user_string .= ', ' . $username;
554
- } else {
555
- $user_string .= $username;
556
- }
557
- }
558
- $i++;
559
- }
560
- } else {
561
- $user_string = $users_connected_to_old_api_only[0];
562
- }
563
-
564
- if ( $is_after_deprecation_deadline ) {
565
- $error = '<p><b>' . sprintf( __( 'Error: The account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to recent Instagram platform changes this Instagram account needs to be reconnected in order to continue updating.', 'instagram-feed' ) . '<a href="'.get_admin_url().'?page=sb-instagram-feed" class="sb_frontend_btn"><i class="fa fa-cog" aria-hidden="true"></i> ' . __( 'Reconnect on plugin Settings page', 'instagram-feed' ) . '</a>';
566
- } else {
567
- $error = '<p><b>' . sprintf( __( 'Warning: The account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to Instagram platform changes on March 31, 2020, this Instagram account needs to be reconnected to allow the feed to continue updating.', 'instagram-feed' ) . '<a href="'.get_admin_url().'?page=sb-instagram-feed" class="sb_frontend_btn"><i class="fa fa-cog" aria-hidden="true"></i> ' . __( 'Reconnect on plugin Settings page', 'instagram-feed' ) . '</a>';
568
- }
569
-
570
- $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
571
- }
572
-
573
- $this->connected_accounts_in_feed = $connected_accounts_in_feed;
574
- $this->feed_type_and_terms = $feed_type_and_terms;
575
- }
576
-
577
- /**
578
- * @return float|int
579
- *
580
- * @since 2.0/5.0
581
- */
582
- public function get_cache_time_in_seconds() {
583
- if ( $this->db['sbi_caching_type'] === 'background' ) {
584
- return SBI_CRON_UPDATE_CACHE_TIME;
585
- } else {
586
- //If the caching time doesn't exist in the database then set it to be 1 hour
587
- $cache_time = isset( $this->settings['sb_instagram_cache_time'] ) ? (int)$this->settings['sb_instagram_cache_time'] : 1;
588
- $cache_time_unit = isset( $this->settings['sb_instagram_cache_time_unit'] ) ? $this->settings['sb_instagram_cache_time_unit'] : 'hours';
589
-
590
- //Calculate the cache time in seconds
591
- if ( $cache_time_unit == 'minutes' ) $cache_time_unit = 60;
592
- if ( $cache_time_unit == 'hours' ) $cache_time_unit = 60*60;
593
- if ( $cache_time_unit == 'days' ) $cache_time_unit = 60*60*24;
594
-
595
- return $cache_time * $cache_time_unit;
596
- }
597
- }
 
 
 
 
 
 
598
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Settings
4
+ *
5
+ * Creates organized settings from shortcode settings and settings
6
+ * from the options table.
7
+ *
8
+ * Also responsible for creating transient names/feed ids based on
9
+ * feed settings
10
+ *
11
+ * @since 2.0/5.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ die( '-1' );
16
+ }
17
+
18
+ class SB_Instagram_Settings {
19
+ /**
20
+ * @var array
21
+ */
22
+ protected $atts;
23
+
24
+ /**
25
+ * @var array
26
+ */
27
+ protected $db;
28
+
29
+ /**
30
+ * @var array
31
+ */
32
+ protected $settings;
33
+
34
+ /**
35
+ * @var array
36
+ */
37
+ protected $feed_type_and_terms;
38
+
39
+ /**
40
+ * @var array
41
+ */
42
+ protected $connected_accounts;
43
+
44
+ /**
45
+ * @var array
46
+ */
47
+ protected $connected_accounts_in_feed;
48
+
49
+ /**
50
+ * @var string
51
+ */
52
+ protected $transient_name;
53
+
54
+ /**
55
+ * SB_Instagram_Settings constructor.
56
+ *
57
+ * Overwritten in the Pro version.
58
+ *
59
+ * @param array $atts shortcode settings
60
+ * @param array $db settings from the wp_options table
61
+ */
62
+ public function __construct( $atts, $db ) {
63
+ $this->atts = $atts;
64
+ $this->db = $db;
65
+
66
+ $this->connected_accounts = isset( $db['connected_accounts'] ) ? $db['connected_accounts'] : array();
67
+
68
+ $this->settings = shortcode_atts(
69
+ array(
70
+ 'id' => isset( $db['sb_instagram_user_id'] ) ? $db['sb_instagram_user_id'] : '',
71
+ 'width' => isset( $db['sb_instagram_width'] ) ? $db['sb_instagram_width'] : '',
72
+ 'widthunit' => isset( $db['sb_instagram_width_unit'] ) ? $db['sb_instagram_width_unit'] : '',
73
+ 'widthresp' => isset( $db['sb_instagram_feed_width_resp'] ) ? $db['sb_instagram_feed_width_resp'] : '',
74
+ 'height' => isset( $db['sb_instagram_height'] ) ? $db['sb_instagram_height'] : '',
75
+ 'heightunit' => isset( $db['sb_instagram_height_unit'] ) ? $db['sb_instagram_height_unit'] : '',
76
+ 'sortby' => isset( $db['sb_instagram_sort'] ) ? $db['sb_instagram_sort'] : '',
77
+ 'num' => isset( $db['sb_instagram_num'] ) ? $db['sb_instagram_num'] : '',
78
+ 'apinum' => isset( $db['sb_instagram_minnum'] ) ? $db['sb_instagram_minnum'] : '',
79
+ 'nummobile' => isset($db[ 'sb_instagram_nummobile' ]) ? $db[ 'sb_instagram_nummobile' ] : '',
80
+ 'cols' => isset( $db['sb_instagram_cols'] ) ? $db['sb_instagram_cols'] : '',
81
+ 'disablemobile' => isset( $db['sb_instagram_disable_mobile'] ) ? $db['sb_instagram_disable_mobile'] : '',
82
+ 'imagepadding' => isset( $db['sb_instagram_image_padding'] ) ? $db['sb_instagram_image_padding'] : '',
83
+ 'imagepaddingunit' => isset( $db['sb_instagram_image_padding_unit'] ) ? $db['sb_instagram_image_padding_unit'] : '',
84
+ 'background' => isset( $db['sb_instagram_background'] ) ? $db['sb_instagram_background'] : '',
85
+ 'showbutton' => isset( $db['sb_instagram_show_btn'] ) ? $db['sb_instagram_show_btn'] : '',
86
+ 'buttoncolor' => isset( $db['sb_instagram_btn_background'] ) ? $db['sb_instagram_btn_background'] : '',
87
+ 'buttontextcolor' => isset( $db['sb_instagram_btn_text_color'] ) ? $db['sb_instagram_btn_text_color'] : '',
88
+ 'buttontext' => isset( $db['sb_instagram_btn_text'] ) ? $db['sb_instagram_btn_text'] : '',
89
+ 'imageres' => isset( $db['sb_instagram_image_res'] ) ? $db['sb_instagram_image_res'] : '',
90
+ 'showfollow' => isset( $db['sb_instagram_show_follow_btn'] ) ? $db['sb_instagram_show_follow_btn'] : '',
91
+ 'followcolor' => isset( $db['sb_instagram_folow_btn_background'] ) ? $db['sb_instagram_folow_btn_background'] : '',
92
+ 'followtextcolor' => isset( $db['sb_instagram_follow_btn_text_color'] ) ? $db['sb_instagram_follow_btn_text_color'] : '',
93
+ 'followtext' => isset( $db['sb_instagram_follow_btn_text'] ) ? $db['sb_instagram_follow_btn_text'] : '',
94
+ 'showheader' => isset( $db['sb_instagram_show_header'] ) ? $db['sb_instagram_show_header'] : '',
95
+ 'headersize' => isset( $db['sb_instagram_header_size'] ) ? $db['sb_instagram_header_size'] : '',
96
+ 'showbio' => isset( $db['sb_instagram_show_bio'] ) ? $db['sb_instagram_show_bio'] : '',
97
+ 'custombio' => isset($db[ 'sb_instagram_custom_bio' ]) ? $db[ 'sb_instagram_custom_bio' ] : '',
98
+ 'customavatar' => isset($db[ 'sb_instagram_custom_avatar' ]) ? $db[ 'sb_instagram_custom_avatar' ] : '',
99
+ 'headercolor' => isset( $db['sb_instagram_header_color'] ) ? $db['sb_instagram_header_color'] : '',
100
+ 'class' => '',
101
+ 'ajaxtheme' => isset( $db['sb_instagram_ajax_theme'] ) ? $db['sb_instagram_ajax_theme'] : '',
102
+ 'cachetime' => isset( $db['sb_instagram_cache_time'] ) ? $db['sb_instagram_cache_time'] : '',
103
+ 'media' => isset( $db['sb_instagram_media_type'] ) ? $db['sb_instagram_media_type'] : '',
104
+ 'headeroutside' => isset($db[ 'sb_instagram_outside_scrollable' ]) ? $db[ 'sb_instagram_outside_scrollable' ] : '',
105
+ 'accesstoken' => '',
106
+ 'user' => isset( $db['sb_instagram_user'] ) ? $db['sb_instagram_user'] : false,
107
+ 'feedid' => isset( $db['sb_instagram_feed_id'] ) ? $db['sb_instagram_feed_id'] : false,
108
+ 'resizeprocess' => isset( $db['sb_instagram_resizeprocess'] ) ? $db['sb_instagram_resizeprocess'] : 'background',
109
+ 'customtemplates' => isset( $db['custom_template'] ) ? $db['custom_template'] : '',
110
+
111
+ ), $atts );
112
+
113
+ $this->settings['customtemplates'] = $this->settings['customtemplates'] === 'true' || $this->settings['customtemplates'] === 'on';
114
+ if ( isset( $_GET['sbi_debug'] ) ) {
115
+ $this->settings['customtemplates'] = false;
116
+ }
117
+ $this->settings['minnum'] = max( (int)$this->settings['num'], (int)$this->settings['nummobile'] );
118
+ $this->settings['showbio'] = $this->settings['showbio'] === 'true' || $this->settings['showbio'] === 'on' || $this->settings['showbio'] === true;
119
+ if ( isset( $atts['showbio'] ) && $atts['showbio'] === 'false' ) {
120
+ $this->settings['showbio'] = false;
121
+ }
122
+ if ( isset( $atts['showheader'] ) && $atts['showheader'] === 'false' ) {
123
+ $this->settings['showheader'] = false;
124
+ }
125
+ $this->settings['disable_resize'] = isset( $db['sb_instagram_disable_resize'] ) && ($db['sb_instagram_disable_resize'] === 'on');
126
+ $this->settings['favor_local'] = isset( $db['sb_instagram_favor_local'] ) && ($db['sb_instagram_favor_local'] === 'on');
127
+ $this->settings['backup_cache_enabled'] = ! isset( $db['sb_instagram_backup'] ) || ($db['sb_instagram_backup'] === 'on');
128
+ $this->settings['font_method'] = isset( $db['sbi_font_method'] ) ? $db['sbi_font_method'] : 'svg';
129
+ $this->settings['headeroutside'] = ($this->settings['headeroutside'] === true || $this->settings['headeroutside'] === 'on' || $this->settings['headeroutside'] === 'true');
130
+ $this->settings['disable_js_image_loading'] = isset( $db['disable_js_image_loading'] ) && ($db['disable_js_image_loading'] === 'on');
131
+ $this->settings['ajax_post_load'] = isset( $db['sb_ajax_initial'] ) && ($db['sb_ajax_initial'] === 'on');
132
+
133
+ switch ( $db['sbi_cache_cron_interval'] ) {
134
+ case '30mins' :
135
+ $this->settings['sbi_cache_cron_interval'] = 60*30;
136
+ break;
137
+ case '1hour' :
138
+ $this->settings['sbi_cache_cron_interval'] = 60*60;
139
+ break;
140
+ default :
141
+ $this->settings['sbi_cache_cron_interval'] = 60*60*12;
142
+ }
143
+
144
+ $this->settings['sb_instagram_cache_time'] = isset( $this->db['sb_instagram_cache_time'] ) ? $this->db['sb_instagram_cache_time'] : 1;
145
+ $this->settings['sb_instagram_cache_time_unit'] = isset( $this->db['sb_instagram_cache_time_unit'] ) ? $this->db['sb_instagram_cache_time_unit'] : 'hours';
146
+
147
+ global $sb_instagram_posts_manager;
148
+
149
+ if ( $sb_instagram_posts_manager->are_current_api_request_delays() ) {
150
+ $this->settings['alwaysUseBackup'] = true;
151
+ }
152
+
153
+ $this->settings['isgutenberg'] = SB_Instagram_Blocks::is_gb_editor();
154
+ if ( $this->settings['isgutenberg'] ) {
155
+ $this->settings['ajax_post_load'] = false;
156
+ $this->settings['disable_js_image_loading'] = true;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * @return array
162
+ *
163
+ * @since 2.0/5.0
164
+ */
165
+ public function get_settings() {
166
+ return $this->settings;
167
+ }
168
+
169
+ /**
170
+ * The plugin will output settings on the frontend for debugging purposes.
171
+ * Safe settings to display are added here.
172
+ *
173
+ * Overwritten in the Pro version.
174
+ *
175
+ * @return array
176
+ *
177
+ * @since 2.0/5.0
178
+ */
179
+ public static function get_public_db_settings_keys() {
180
+ $public = array(
181
+ 'sb_instagram_user_id',
182
+ 'sb_instagram_cache_time',
183
+ 'sb_instagram_cache_time_unit',
184
+ 'sbi_caching_type',
185
+ 'sbi_cache_cron_interval',
186
+ 'sbi_cache_cron_time',
187
+ 'sbi_cache_cron_am_pm',
188
+ 'sb_instagram_width',
189
+ 'sb_instagram_width_unit',
190
+ 'sb_instagram_feed_width_resp',
191
+ 'sb_instagram_height',
192
+ 'sb_instagram_num',
193
+ 'sb_instagram_height_unit',
194
+ 'sb_instagram_cols',
195
+ 'sb_instagram_disable_mobile',
196
+ 'sb_instagram_image_padding',
197
+ 'sb_instagram_image_padding_unit',
198
+ 'sb_instagram_sort',
199
+ 'sb_instagram_background',
200
+ 'sb_instagram_show_btn',
201
+ 'sb_instagram_btn_background',
202
+ 'sb_instagram_btn_text_color',
203
+ 'sb_instagram_btn_text',
204
+ 'sb_instagram_image_res',
205
+ //Header
206
+ 'sb_instagram_show_header',
207
+ 'sb_instagram_header_size',
208
+ 'sb_instagram_header_color',
209
+ //Follow button
210
+ 'sb_instagram_show_follow_btn',
211
+ 'sb_instagram_folow_btn_background',
212
+ 'sb_instagram_follow_btn_text_color',
213
+ 'sb_instagram_follow_btn_text',
214
+ //Misc
215
+ 'sb_instagram_cron',
216
+ 'sb_instagram_backup',
217
+ 'sb_instagram_ajax_theme',
218
+ 'sb_instagram_disable_resize',
219
+ 'disable_js_image_loading',
220
+ 'enqueue_js_in_head',
221
+ 'sbi_font_method',
222
+ 'sb_instagram_disable_awesome',
223
+ 'sb_ajax_initial',
224
+ 'use_custom'
225
+ );
226
+
227
+ return $public;
228
+ }
229
+
230
+ /**
231
+ * @return array
232
+ *
233
+ * @since 2.0/5.0
234
+ */
235
+ public function get_connected_accounts() {
236
+ return $this->connected_accounts;
237
+ }
238
+
239
+ /**
240
+ * @return array|bool
241
+ *
242
+ * @since 2.0/5.0
243
+ */
244
+ public function get_connected_accounts_in_feed() {
245
+ if ( isset( $this->connected_accounts_in_feed ) ) {
246
+ return $this->connected_accounts_in_feed;
247
+ } else {
248
+ return false;
249
+ }
250
+ }
251
+
252
+ /**
253
+ * @return bool|string
254
+ *
255
+ * @since 2.0/5.0
256
+ */
257
+ public function get_transient_name() {
258
+ if ( isset( $this->transient_name ) ) {
259
+ return $this->transient_name;
260
+ } else {
261
+ return false;
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Uses the feed types and terms as well as as some
267
+ * settings to create a semi-unique feed id used for
268
+ * caching and other features.
269
+ *
270
+ * Overwritten in the Pro version.
271
+ *
272
+ * @param string $transient_name
273
+ *
274
+ * @since 2.0/5.0
275
+ */
276
+ public function set_transient_name( $transient_name = '' ) {
277
+
278
+ if ( ! empty( $transient_name ) ) {
279
+ $this->transient_name = $transient_name;
280
+ } elseif ( ! empty( $this->settings['feedid'] ) ) {
281
+ $this->transient_name = 'sbi_' . $this->settings['feedid'];
282
+ } else {
283
+ $feed_type_and_terms = $this->feed_type_and_terms;
284
+
285
+ $sbi_transient_name = 'sbi_';
286
+
287
+ if ( isset( $feed_type_and_terms['users'] ) ) {
288
+ foreach ( $feed_type_and_terms['users'] as $term_and_params ) {
289
+ $user = $term_and_params['term'];
290
+ $connected_account = $this->connected_accounts_in_feed[ $user ];
291
+ if ( isset( $connected_account['type'] ) && $connected_account['type'] === 'business' ) {
292
+ $sbi_transient_name .= $connected_account['username'];
293
+ } else {
294
+ $sbi_transient_name .= $user;
295
+ }
296
+ }
297
+ }
298
+
299
+ $num = $this->settings['num'];
300
+
301
+ $num_length = strlen( $num ) + 1;
302
+
303
+ //Add both parts of the caching string together and make sure it doesn't exceed 45
304
+ $sbi_transient_name = substr( $sbi_transient_name, 0, 45 - $num_length );
305
+
306
+ $sbi_transient_name .= '#' . $num;
307
+
308
+ $this->transient_name = $sbi_transient_name;
309
+ }
310
+
311
+ }
312
+
313
+ /**
314
+ * @return array|bool
315
+ *
316
+ * @since 2.0/5.0
317
+ */
318
+ public function get_feed_type_and_terms() {
319
+ if ( isset( $this->feed_type_and_terms ) ) {
320
+ return $this->feed_type_and_terms;
321
+ } else {
322
+ return false;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Based on the settings related to retrieving post data from the API,
328
+ * this setting is used to make sure all endpoints needed for the feed are
329
+ * connected and stored for easily looping through when adding posts
330
+ *
331
+ * Overwritten in the Pro version.
332
+ *
333
+ * @since 2.0/5.0
334
+ */
335
+ public function set_feed_type_and_terms() {
336
+ global $sb_instagram_posts_manager;
337
+
338
+ $connected_accounts_in_feed = array();
339
+ $feed_type_and_terms = array(
340
+ 'users' => array()
341
+ );
342
+ $usernames_included = array();
343
+ $is_after_deprecation_deadline = sbi_is_after_deprecation_deadline();
344
+ $is_using_access_token_in_shortcode = ! empty( $this->atts['accesstoken'] ) && strpos( $this->atts['accesstoken'], '.' ) !== false;
345
+ $users_connected_to_old_api_only = array();
346
+ $settings_link = '<a href="'.get_admin_url().'?page=sb-instagram-feed" target="_blank">' . __( 'plugin Settings page', 'instagram-feed' ) . '</a>';
347
+
348
+ // if using an access token in the shortcode and after the deadline, try to use a connected account by collecting the user IDs
349
+ if ( $is_after_deprecation_deadline && $is_using_access_token_in_shortcode ) {
350
+ $error = '<p><b>' . __( 'Error: Cannot add access token directly to the shortcode.', 'instagram-feed' ) . '</b><br>' . sprintf( __( 'Due to recent Instagram platform changes, it\'s no longer possible to create a feed by adding the access token to the shortcode. Remove the access token from the shortcode and connect an account on the %s instead.', 'instagram-feed' ), $settings_link );
351
+
352
+ $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
353
+
354
+ $this->settings['id'] = array();
355
+ $access_tokens = explode( ',', str_replace( ' ', '', $this->atts['accesstoken'] ) );
356
+
357
+ foreach ( $access_tokens as $access_token ) {
358
+ $split_token = explode( '.', $access_token );
359
+ $this->settings['id'][] = $split_token[0];
360
+ }
361
+ }
362
+
363
+ if ( ! $is_after_deprecation_deadline && $is_using_access_token_in_shortcode ) {
364
+ $error = '<p><b>' . __( 'Warning: Cannot add access token directly to the shortcode.', 'instagram-feed' ) . '</b><br>' . sprintf( __( 'Due to upcoming Instagram platform changes on March 31, 2020, it will no longer be possible for feeds to use access tokens directly in the shortcode. Remove the access token from the shortcode and connect an account on the %s instead.', 'instagram-feed' ), $settings_link );
365
+
366
+ $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
367
+ $access_tokens = explode( ',', str_replace( ' ', '', $this->atts['accesstoken'] ) );
368
+
369
+ foreach ( $access_tokens as $access_token ) {
370
+ $split_token = explode( '.', $access_token );
371
+ $connected_accounts_in_feed[ $split_token[0] ] = array(
372
+ 'access_token' => $access_token,
373
+ 'user_id' => $split_token[0]
374
+ );
375
+ $feed_type_and_terms['users'][] = array(
376
+ 'term' => $split_token[0],
377
+ 'params' => array()
378
+ );
379
+ }
380
+
381
+ } elseif ( ! empty( $this->settings['user'] ) ) {
382
+ $user_array = is_array( $this->settings['user'] ) ? $this->settings['user'] : explode( ',', str_replace( ' ', '', $this->settings['user'] ) );
383
+ foreach ( $user_array as $user ) {
384
+ $user_found = false;
385
+ $user_for_deprecated_personal_account_only_found = false;
386
+ $term_for_this_user = array();
387
+ $username_to_match = $user;
388
+
389
+ if ( isset( $this->connected_accounts[ $user ] ) ) {
390
+ if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
391
+ $term_for_this_user = array(
392
+ 'term' => $this->connected_accounts[ $user ]['user_id'],
393
+ 'params' => array()
394
+ );
395
+ $connected_accounts_in_feed[ $this->connected_accounts[ $user ]['user_id'] ] = $this->connected_accounts[ $user ];
396
+ $usernames_included[] = $this->connected_accounts[ $user ]['username'];
397
+ $username_to_match = $this->connected_accounts[ $user ]['username'];
398
+ $user_found = true;
399
+ if ( ! isset( $this->connected_accounts[ $user ]['type'] ) || $this->connected_accounts[ $user ]['type'] === 'personal' ) {
400
+ $user_for_deprecated_personal_account_only_found = true;
401
+ }
402
+ }
403
+ }
404
+
405
+ if ( ! $user_found || $user_for_deprecated_personal_account_only_found ) {
406
+ foreach ( $this->connected_accounts as $connected_account ) {
407
+ $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
408
+ if ( strtolower( $username_to_match ) === strtolower( $connected_account['username'] ) ) {
409
+ if ( $user_for_deprecated_personal_account_only_found || ! in_array( $connected_account['username'], $usernames_included, true ) ) {
410
+ if ( $account_type !== 'personal' ) {
411
+ $term_for_this_user = array(
412
+ 'term' => $user,
413
+ 'params' => array()
414
+ );
415
+ $connected_accounts_in_feed[ $user ] = $connected_account;
416
+ $user_for_deprecated_personal_account_only_found = false;
417
+ } else {
418
+ $term_for_this_user = array(
419
+ 'term' => $connected_account['user_id'],
420
+ 'params' => array()
421
+ );
422
+ $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
423
+ }
424
+ $usernames_included[] = $connected_account['username'];
425
+ $user_found = true;
426
+ }
427
+ }
428
+ }
429
+ }
430
+
431
+ if ( ! empty( $term_for_this_user ) ) {
432
+ $feed_type_and_terms['users'][] = $term_for_this_user;
433
+ }
434
+
435
+ if ( ! $user_found ) {
436
+ $error = '<p><b>' . sprintf( __( 'Error: There is no connected account for the user %s.', 'instagram-feed' ), $user ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b>';
437
+
438
+ $sb_instagram_posts_manager->add_frontend_error( 'no_connection_' . $user, $error );
439
+ }
440
+
441
+ if ( $user_for_deprecated_personal_account_only_found
442
+ && ! in_array( $user, $users_connected_to_old_api_only, true ) ) {
443
+ $users_connected_to_old_api_only[] = $connected_accounts_in_feed[ $user ]['username'];
444
+ }
445
+
446
+ }
447
+
448
+ } elseif ( ! empty( $this->settings['id'] ) ) {
449
+ $user_id_array = is_array( $this->settings['id'] ) ? $this->settings['id'] : explode( ',', str_replace( ' ', '', $this->settings['id'] ) );
450
+
451
+ foreach ( $user_id_array as $user ) {
452
+ $user_found = false;
453
+ $user_for_deprecated_personal_account_only_found = false;
454
+ $term_for_this_user = array();
455
+ $username_to_match = '';
456
+
457
+ if ( isset( $this->connected_accounts[ $user ] ) ) {
458
+ if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
459
+ $term_for_this_user = array(
460
+ 'term' => $this->connected_accounts[ $user ]['user_id'],
461
+ 'params' => array()
462
+ );
463
+ $connected_accounts_in_feed[ $this->connected_accounts[ $user ]['user_id'] ] = $this->connected_accounts[ $user ];
464
+ if ( ! in_array( $this->connected_accounts[ $user ]['username'], $usernames_included, true ) ) {
465
+ $usernames_included[] = $this->connected_accounts[ $user ]['username'];
466
+ }
467
+ $username_to_match = $this->connected_accounts[ $user ]['username'];
468
+ $user_found = true;
469
+ if ( ! isset( $this->connected_accounts[ $user ]['type'] ) || $this->connected_accounts[ $user ]['type'] === 'personal' ) {
470
+ $user_for_deprecated_personal_account_only_found = true;
471
+ }
472
+ }
473
+
474
+ }
475
+
476
+ if ( ! $user_found || $user_for_deprecated_personal_account_only_found ) {
477
+
478
+ foreach ( $this->connected_accounts as $connected_account ) {
479
+ $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
480
+ $old_id_matches = ($account_type === 'basic' && isset( $connected_account['old_user_id'] ) && (string)$connected_account['old_user_id'] === (string)$user);
481
+ if ( $old_id_matches
482
+ || (strtolower( $username_to_match ) === strtolower( $connected_account['username'] )) ) {
483
+ if ( $user_for_deprecated_personal_account_only_found || ! in_array( $connected_account['username'], $usernames_included, true ) ) {
484
+ if ( $account_type !== 'personal' ) {
485
+ $term_for_this_user = array(
486
+ 'term' => $user,
487
+ 'params' => array()
488
+ );
489
+ $connected_accounts_in_feed[ $user ] = $connected_account;
490
+ $user_for_deprecated_personal_account_only_found = false;
491
+ } else {
492
+ $term_for_this_user = array(
493
+ 'term' => $connected_account['user_id'],
494
+ 'params' => array()
495
+ );
496
+ $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
497
+ }
498
+ if ( ! in_array( $connected_account['username'], $usernames_included, true ) ) {
499
+ $usernames_included[] = $connected_account['username'];
500
+ }
501
+ $user_found = true;
502
+ }
503
+ }
504
+ }
505
+
506
+ }
507
+
508
+ if ( ! empty( $term_for_this_user ) ) {
509
+ $feed_type_and_terms['users'][] = $term_for_this_user;
510
+ }
511
+
512
+ if ( ! $user_found ) {
513
+ $error = '<p><b>' . sprintf( __( 'Error: There is no connected account for the user %s', 'instagram-feed' ), $user ) . ' ' . __( 'Feed will not update.', 'instagram-feed' ) . '</b>';
514
+
515
+ $sb_instagram_posts_manager->add_frontend_error( 'no_connection_' . $user, $error );
516
+ }
517
+
518
+ if ( $user_for_deprecated_personal_account_only_found
519
+ && ! in_array( $user, $users_connected_to_old_api_only, true ) ) {
520
+ $users_connected_to_old_api_only[] = $connected_accounts_in_feed[ $user ]['username'];
521
+ }
522
+
523
+ }
524
+
525
+ } else {
526
+ foreach ( $this->connected_accounts as $connected_account ) {
527
+ $account_type = isset( $connected_account['type'] ) ? $connected_account['type'] : 'personal';
528
+
529
+ if ( empty( $feed_type_and_terms['users'] ) ) {
530
+ if ( $account_type !== 'personal' ) {
531
+ $feed_type_and_terms['users'][] = array(
532
+ 'term' => $connected_account['username'],
533
+ 'params' => array()
534
+ );
535
+ $connected_accounts_in_feed[ $connected_account['username'] ] = $connected_account;
536
+ } elseif ( ! $is_after_deprecation_deadline ) {
537
+ $feed_type_and_terms['users'][] = array(
538
+ 'term' => $connected_account['user_id'],
539
+ 'params' => array()
540
+ );
541
+ $connected_accounts_in_feed[ $connected_account['user_id'] ] = $connected_account;
542
+ }
543
+ }
544
+
545
+ }
546
+ }
547
+
548
+ if ( ! empty( $users_connected_to_old_api_only ) ) {
549
+ $total = count( $users_connected_to_old_api_only );
550
+ if ( $total > 1 ) {
551
+ $user_string = '';
552
+ $i = 0;
553
+
554
+ foreach ( $users_connected_to_old_api_only as $username ) {
555
+ if ( ($i + 1) === $total ) {
556
+ $user_string .= ' and ' . $username;
557
+ } else {
558
+ if ( $i !== 0 ) {
559
+ $user_string .= ', ' . $username;
560
+ } else {
561
+ $user_string .= $username;
562
+ }
563
+ }
564
+ $i++;
565
+ }
566
+ } else {
567
+ $user_string = $users_connected_to_old_api_only[0];
568
+ }
569
+
570
+ if ( $is_after_deprecation_deadline ) {
571
+ $error = '<p><b>' . sprintf( __( 'Error: The account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to recent Instagram platform changes this Instagram account needs to be reconnected in order to continue updating.', 'instagram-feed' ) . '<a href="'.get_admin_url().'?page=sb-instagram-feed" class="sb_frontend_btn"><i class="fa fa-cog" aria-hidden="true"></i> ' . __( 'Reconnect on plugin Settings page', 'instagram-feed' ) . '</a>';
572
+ } else {
573
+ $error = '<p><b>' . sprintf( __( 'Warning: The account for %s needs to be reconnected.', 'instagram-feed' ), '<em>'.$user_string.'</em>' ) . '</b><br>' . __( 'Due to Instagram platform changes on March 31, 2020, this Instagram account needs to be reconnected to allow the feed to continue updating.', 'instagram-feed' ) . '<a href="'.get_admin_url().'?page=sb-instagram-feed" class="sb_frontend_btn"><i class="fa fa-cog" aria-hidden="true"></i> ' . __( 'Reconnect on plugin Settings page', 'instagram-feed' ) . '</a>';
574
+ }
575
+
576
+ $sb_instagram_posts_manager->add_frontend_error( 'deprecation_warning', $error );
577
+ }
578
+
579
+ $this->connected_accounts_in_feed = $connected_accounts_in_feed;
580
+ $this->feed_type_and_terms = $feed_type_and_terms;
581
+ }
582
+
583
+ /**
584
+ * @return float|int
585
+ *
586
+ * @since 2.0/5.0
587
+ */
588
+ public function get_cache_time_in_seconds() {
589
+ if ( $this->db['sbi_caching_type'] === 'background' ) {
590
+ return SBI_CRON_UPDATE_CACHE_TIME;
591
+ } else {
592
+ //If the caching time doesn't exist in the database then set it to be 1 hour
593
+ $cache_time = isset( $this->settings['sb_instagram_cache_time'] ) ? (int)$this->settings['sb_instagram_cache_time'] : 1;
594
+ $cache_time_unit = isset( $this->settings['sb_instagram_cache_time_unit'] ) ? $this->settings['sb_instagram_cache_time_unit'] : 'hours';
595
+
596
+ //Calculate the cache time in seconds
597
+ if ( $cache_time_unit == 'minutes' ) $cache_time_unit = 60;
598
+ if ( $cache_time_unit == 'hours' ) $cache_time_unit = 60*60;
599
+ if ( $cache_time_unit == 'days' ) $cache_time_unit = 60*60*24;
600
+
601
+ return $cache_time * $cache_time_unit;
602
+ }
603
+ }
604
  }
inc/class-sb-instagram-token-refresher.php CHANGED
@@ -1,176 +1,176 @@
1
- <?php
2
- /**
3
- * Class SB_Instagram_Token_Refresher
4
- *
5
- * Various methods for efficiently refreshing basic display access
6
- * tokens which expire every 60 days if not refreshed.
7
- *
8
- * @since 2.2/5.3
9
- */
10
-
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- die( '-1' );
13
- }
14
-
15
- class SB_Instagram_Token_Refresher
16
- {
17
-
18
- /**
19
- * @var array
20
- */
21
- private $connected_account;
22
-
23
- /**
24
- * @var array
25
- */
26
- private $report;
27
-
28
- public function __construct( $connected_account ) {
29
- $this->connected_account = $connected_account;
30
- $this->report = array();
31
- }
32
-
33
- public function get_report() {
34
- return $this->report;
35
- }
36
-
37
- /**
38
- * The plugin will attempt to refresh the token well
39
- * before it expires. This function determines if the
40
- * minimum amount of time has passed before the token
41
- * can be refreshed
42
- *
43
- * @param $connected_account
44
- *
45
- * @return bool
46
- */
47
- public static function refresh_time_has_passed_threshold( $connected_account ) {
48
- $expiration_timestamp = isset( $connected_account['expires_timestamp'] ) ? $connected_account['expires_timestamp'] : time();
49
- $current_time = sbi_get_current_timestamp();
50
-
51
- $refresh_threshold = $expiration_timestamp - SBI_REFRESH_THRESHOLD_OFFSET;
52
-
53
- if ( $refresh_threshold < $current_time ) {
54
- return true;
55
- }
56
- return false;
57
- }
58
-
59
- /**
60
- * Instagram will automatically reject API calls if
61
- * done too frequently. This method returns true if
62
- * there has been a minimum amount of time since the last
63
- * API connection was attemplted
64
- *
65
- * @param $connected_account
66
- *
67
- * @return bool
68
- */
69
- public static function minimum_time_interval_since_last_attempt_has_passed( $connected_account ) {
70
- $last_attempt = isset( $connected_account['last_refresh_attempt'] ) ? (int)$connected_account['last_refresh_attempt'] : 0;
71
- $current_time = sbi_get_current_timestamp();
72
-
73
- if ( $current_time > $last_attempt + SBI_MINIMUM_INTERVAL ) {
74
- return true;
75
- }
76
- return false;
77
- }
78
-
79
- /**
80
- * Returns true if the minimum time has passed since the last
81
- * successfull access token refresh and the minimum time has passed
82
- * since the last attempt.
83
- *
84
- * @return bool
85
- */
86
- public function should_attempt_refresh() {
87
- if ( SB_Instagram_Token_Refresher::refresh_time_has_passed_threshold( $this->connected_account ) ) {
88
-
89
- if ( SB_Instagram_Token_Refresher::minimum_time_interval_since_last_attempt_has_passed( $this->connected_account ) ) {
90
- $this->report['should_do_update'] = true;
91
- $this->report['reason'] = '';
92
- return true;
93
- } else {
94
- $this->report['should_do_update'] = false;
95
- $this->report['reason'] = 'has not been enough time since last attempt';
96
- }
97
-
98
- } else {
99
- $this->report['should_do_update'] = false;
100
- $this->report['reason'] = 'token expiration date not close enough';
101
- }
102
-
103
- return false;
104
- }
105
-
106
- /**
107
- * Attempts to refresh the token by connecting to the
108
- * Instagram API. Logs information about the error if unsuccessful.
109
- *
110
- * @return bool
111
- */
112
- public function attempt_token_refresh() {
113
- $this->update_last_attempt_timestamp();
114
-
115
- $connection = new SB_Instagram_API_Connect( $this->connected_account, 'access_token', array() );
116
-
117
- $connection->connect();
118
-
119
- if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
120
- $access_token_data = $connection->get_data();
121
-
122
- if ( ! empty( $access_token_data ) ) {
123
- $this->report['did_update'] = true;
124
- $this->add_renewal_data( $access_token_data );
125
-
126
- return true;
127
- } else {
128
- $this->report['did_update'] = false;
129
- $this->report['reason'] = 'successful connection but no data returned';
130
- }
131
- } else {
132
- $this->report['did_update'] = false;
133
- $this->report['reason'] = 'could not connect to Instagram';
134
- $this->report['error_log'] = $connection;
135
- }
136
-
137
- return false;
138
- }
139
-
140
- /**
141
- * Updates data related to when the last attempt was made to refresh
142
- * the access token for a connected account and saves it in the database.
143
- */
144
- public function update_last_attempt_timestamp() {
145
- $options = get_option( 'sb_instagram_settings', array() );
146
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
147
-
148
- $connected_accounts[ $this->connected_account['user_id'] ]['last_refresh_attempt'] = time();
149
-
150
- $options['connected_accounts'] = $connected_accounts;
151
-
152
- update_option( 'sb_instagram_settings', $options );
153
- }
154
-
155
- /**
156
- * Updates data related to the renewed access token
157
- * for a connected account and saves it in the database.
158
- *
159
- * @param $token_data
160
- */
161
- private function add_renewal_data( $token_data ) {
162
- $options = get_option( 'sb_instagram_settings', array() );
163
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
164
-
165
- $expires_in = $token_data['expires_in'];
166
- $expires_timestamp = sbi_get_current_timestamp() + $expires_in;
167
-
168
- $connected_accounts[ $this->connected_account['user_id'] ]['expires_timestamp'] = $expires_timestamp;
169
- $connected_accounts[ $this->connected_account['user_id'] ]['access_token'] = $token_data['access_token'];
170
-
171
- $options['connected_accounts'] = $connected_accounts;
172
-
173
- update_option( 'sb_instagram_settings', $options );
174
- }
175
-
176
  }
1
+ <?php
2
+ /**
3
+ * Class SB_Instagram_Token_Refresher
4
+ *
5
+ * Various methods for efficiently refreshing basic display access
6
+ * tokens which expire every 60 days if not refreshed.
7
+ *
8
+ * @since 2.2/5.3
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ die( '-1' );
13
+ }
14
+
15
+ class SB_Instagram_Token_Refresher
16
+ {
17
+
18
+ /**
19
+ * @var array
20
+ */
21
+ private $connected_account;
22
+
23
+ /**
24
+ * @var array
25
+ */
26
+ private $report;
27
+
28
+ public function __construct( $connected_account ) {
29
+ $this->connected_account = $connected_account;
30
+ $this->report = array();
31
+ }
32
+
33
+ public function get_report() {
34
+ return $this->report;
35
+ }
36
+
37
+ /**
38
+ * The plugin will attempt to refresh the token well
39
+ * before it expires. This function determines if the
40
+ * minimum amount of time has passed before the token
41
+ * can be refreshed
42
+ *
43
+ * @param $connected_account
44
+ *
45
+ * @return bool
46
+ */
47
+ public static function refresh_time_has_passed_threshold( $connected_account ) {
48
+ $expiration_timestamp = isset( $connected_account['expires_timestamp'] ) ? $connected_account['expires_timestamp'] : time();
49
+ $current_time = sbi_get_current_timestamp();
50
+
51
+ $refresh_threshold = $expiration_timestamp - SBI_REFRESH_THRESHOLD_OFFSET;
52
+
53
+ if ( $refresh_threshold < $current_time ) {
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+
59
+ /**
60
+ * Instagram will automatically reject API calls if
61
+ * done too frequently. This method returns true if
62
+ * there has been a minimum amount of time since the last
63
+ * API connection was attemplted
64
+ *
65
+ * @param $connected_account
66
+ *
67
+ * @return bool
68
+ */
69
+ public static function minimum_time_interval_since_last_attempt_has_passed( $connected_account ) {
70
+ $last_attempt = isset( $connected_account['last_refresh_attempt'] ) ? (int)$connected_account['last_refresh_attempt'] : 0;
71
+ $current_time = sbi_get_current_timestamp();
72
+
73
+ if ( $current_time > $last_attempt + SBI_MINIMUM_INTERVAL ) {
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+
79
+ /**
80
+ * Returns true if the minimum time has passed since the last
81
+ * successfull access token refresh and the minimum time has passed
82
+ * since the last attempt.
83
+ *
84
+ * @return bool
85
+ */
86
+ public function should_attempt_refresh() {
87
+ if ( SB_Instagram_Token_Refresher::refresh_time_has_passed_threshold( $this->connected_account ) ) {
88
+
89
+ if ( SB_Instagram_Token_Refresher::minimum_time_interval_since_last_attempt_has_passed( $this->connected_account ) ) {
90
+ $this->report['should_do_update'] = true;
91
+ $this->report['reason'] = '';
92
+ return true;
93
+ } else {
94
+ $this->report['should_do_update'] = false;
95
+ $this->report['reason'] = 'has not been enough time since last attempt';
96
+ }
97
+
98
+ } else {
99
+ $this->report['should_do_update'] = false;
100
+ $this->report['reason'] = 'token expiration date not close enough';
101
+ }
102
+
103
+ return false;
104
+ }
105
+
106
+ /**
107
+ * Attempts to refresh the token by connecting to the
108
+ * Instagram API. Logs information about the error if unsuccessful.
109
+ *
110
+ * @return bool
111
+ */
112
+ public function attempt_token_refresh() {
113
+ $this->update_last_attempt_timestamp();
114
+
115
+ $connection = new SB_Instagram_API_Connect( $this->connected_account, 'access_token', array() );
116
+
117
+ $connection->connect();
118
+
119
+ if ( ! $connection->is_wp_error() && ! $connection->is_instagram_error() ) {
120
+ $access_token_data = $connection->get_data();
121
+
122
+ if ( ! empty( $access_token_data ) ) {
123
+ $this->report['did_update'] = true;
124
+ $this->add_renewal_data( $access_token_data );
125
+
126
+ return true;
127
+ } else {
128
+ $this->report['did_update'] = false;
129
+ $this->report['reason'] = 'successful connection but no data returned';
130
+ }
131
+ } else {
132
+ $this->report['did_update'] = false;
133
+ $this->report['reason'] = 'could not connect to Instagram';
134
+ $this->report['error_log'] = $connection;
135
+ }
136
+
137
+ return false;
138
+ }
139
+
140
+ /**
141
+ * Updates data related to when the last attempt was made to refresh
142
+ * the access token for a connected account and saves it in the database.
143
+ */
144
+ public function update_last_attempt_timestamp() {
145
+ $options = get_option( 'sb_instagram_settings', array() );
146
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
147
+
148
+ $connected_accounts[ $this->connected_account['user_id'] ]['last_refresh_attempt'] = time();
149
+
150
+ $options['connected_accounts'] = $connected_accounts;
151
+
152
+ update_option( 'sb_instagram_settings', $options );
153
+ }
154
+
155
+ /**
156
+ * Updates data related to the renewed access token
157
+ * for a connected account and saves it in the database.
158
+ *
159
+ * @param $token_data
160
+ */
161
+ private function add_renewal_data( $token_data ) {
162
+ $options = get_option( 'sb_instagram_settings', array() );
163
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
164
+
165
+ $expires_in = $token_data['expires_in'];
166
+ $expires_timestamp = sbi_get_current_timestamp() + $expires_in;
167
+
168
+ $connected_accounts[ $this->connected_account['user_id'] ]['expires_timestamp'] = $expires_timestamp;
169
+ $connected_accounts[ $this->connected_account['user_id'] ]['access_token'] = $token_data['access_token'];
170
+
171
+ $options['connected_accounts'] = $connected_accounts;
172
+
173
+ update_option( 'sb_instagram_settings', $options );
174
+ }
175
+
176
  }
inc/email.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Email header template.
4
+ */
5
+
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ exit;
8
+ }
9
+
10
+ ?>
11
+
12
+ <!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
16
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
17
+ <meta name="viewport" content="width=device-width">
18
+ <title><?php echo esc_html( $title ); ?></title>
19
+ </head>
20
+ <body>
21
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" style="border-collapse:collapse;border-spacing:0px;vertical-align:top;min-width:100%;box-sizing:border-box;background-color:rgb(233,234,236);color:rgb(68,68,68);font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;padding:0px;margin:0px;text-align:left;font-size:14px;line-height:140%;height:100%;width:100%"><tbody><tr style="padding:0px;vertical-align:top;text-align:left">
22
+ <td align="center" valign="top" style="vertical-align:top;color:rgb(68,68,68);font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;padding:0px;margin:0px;font-size:14px;line-height:140%;text-align:center;border-collapse:collapse">
23
+ <table border="0" cellpadding="0" cellspacing="0" style="border-collapse:collapse;border-spacing:0px;padding:0px;vertical-align:top;width:600px;margin:0px auto;text-align:inherit">
24
+ <tbody><tr style="padding:0px;vertical-align:top;text-align:left">
25
+ <td align="center" valign="middle" style="vertical-align:top;color:rgb(68,68,68);font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;margin:0px;font-size:14px;line-height:140%;text-align:center;padding:30px 30px 22px;border-collapse:collapse">
26
+ <?php if ( ! empty( $header_image ) ) : ?>
27
+ <img src="<?php echo esc_url( $header_image ); ?>" alt="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?>" />
28
+ <?php endif; ?>
29
+ </td>
30
+ </tr>
31
+ <tr style="padding:0px;vertical-align:top;text-align:left">
32
+ <td align="left" valign="top" style="vertical-align:top;color:rgb(68,68,68);font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;margin:0px;text-align:left;font-size:14px;line-height:140%;background-color:rgb(255,255,255);padding:60px 75px 45px;border-width:3px 1px 1px;border-style:solid;border-color:rgb(227, 71, 22) rgb(221,221,221) rgb(221,221,221);border-collapse:collapse">
33
+
34
+ <table style="border-collapse:collapse;border-spacing:0px;padding:0px;vertical-align:top;text-align:left;width:100%"><tbody><tr style="padding:0px;vertical-align:top;text-align:left">
35
+ <td style="vertical-align:top;font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;padding:0px;margin:0px;text-align:left;font-size:14px;line-height:140%;color:rgb(119,119,119);border-collapse:collapse">
36
+ <?php echo $message_content; ?>
37
+
38
+ <table class="summary-info-table" style="border-collapse: collapse; border-spacing: 0; padding: 0; vertical-align: top; text-align: left; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin: 38px 0 0 0; Margin: 38px 0 0 0; font-size: 15px; border: 1px solid #dddddd; border-radius: 6px; display: block;">
39
+ <tbody><tr style="padding: 0; vertical-align: top; text-align: left;">
40
+ <td class="summary-info-content" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; margin: 0; Margin: 0; text-align: left; font-size: 14px; mso-line-height-rule: exactly; line-height: 140%; color: #777777; padding: 25px 30px 30px 30px;">
41
+ <table style="border-collapse: collapse; border-spacing: 0; padding: 0; vertical-align: top; text-align: left; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
42
+ <tbody><tr style="padding: 0; vertical-align: top; text-align: left;">
43
+ <td class="text-center" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; padding: 0; margin: 0; Margin: 0; font-size: 14px; mso-line-height-rule: exactly; line-height: 140%; text-align: center; color: #777777;">
44
+ <h6 style="padding: 0; word-wrap: normal; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: bold; mso-line-height-rule: exactly; line-height: 130%; font-size: 16px; color: #444444; text-align: inherit; margin: 0 0 20px 0;"><?php echo esc_html( $dyk_message['title'] ); ?></h6>
45
+ </td>
46
+ </tr>
47
+ <tr style="padding: 0; vertical-align: top; text-align: left;">
48
+ <td class="text-center" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; padding: 0; margin: 0; Margin: 0; font-size: 14px; mso-line-height-rule: exactly; line-height: 140%; text-align: center; color: #777777;">
49
+ <?php echo esc_html( $dyk_message['content'] ); ?>
50
+ </td>
51
+ </tr>
52
+ </tbody></table>
53
+ </td>
54
+ </tr>
55
+ <tr style="padding: 0; vertical-align: top; text-align: left;">
56
+ <td class="summary-info-content button-container" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; margin: 0; Margin: 0; text-align: left; font-size: 14px; mso-line-height-rule: exactly; line-height: 140%; color: #777777; padding: 0 30px 30px 30px;">
57
+ <center style="width: 100%;">
58
+ <table class="button rounded-button" style="border-collapse: collapse; border-spacing: 0; padding: 0; vertical-align: top; text-align: left; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; width: auto; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; overflow: hidden;margin: auto;Margin: auto;"><tbody><tr style="padding: 0; vertical-align: top; text-align: left;">
59
+ <td style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; padding: 0; margin: 0; Margin: 0; text-align: left; font-size: 14px; mso-line-height-rule: exactly; line-height: 100%; color: #777777;">
60
+ <table style="border-collapse: collapse; border-spacing: 0; padding: 0; vertical-align: top; text-align: left; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;"><tbody><tr style="padding: 0; vertical-align: top; text-align: left;">
61
+ <td style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: normal; padding: 0; margin: 0; Margin: 0; font-size: 14px; text-align: center; color: #ffffff; background: rgb(227, 71, 22); border: 1px solid #c45e1b; border-bottom: 3px solid #c45e1b; mso-line-height-rule: exactly; line-height: 100%;">
62
+ <a href="<?php echo esc_url( $dyk_message['more'] ); ?>" rel="noopener noreferrer" target="_blank" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin: 0; Margin: 0; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; color: #ffffff; text-decoration: none; text-align: center; display: inline-block; border: 0 solid #c45e1b; mso-line-height-rule: exactly; line-height: 100%; padding: 17px 30px 15px 30px;">
63
+ <?php echo esc_html( __( 'Learn More', 'instagram-feed' ) ); ?>
64
+ </a>
65
+ </td>
66
+ </tr></tbody></table>
67
+ </td>
68
+ </tr></tbody></table>
69
+ </center>
70
+ </td>
71
+ </tr>
72
+ </tbody>
73
+ </table>
74
+ </td>
75
+ </tr></tbody></table>
76
+ </td>
77
+ </tr>
78
+ <tr style="padding:0px;vertical-align:top;text-align:left">
79
+ <td align="center" valign="top" style="vertical-align:top;font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;margin:0px;line-height:140%;padding:30px;color:rgb(114,119,124);font-size:12px;text-align:center;border-collapse:collapse">
80
+ <?php
81
+ /* translators: %s - link to a site. */
82
+ esc_html_e( 'This is a courtesy email sent from the Smash Balloon Instagram Feed plugin on your website to alert you when there is an issue with one of your Instagram feeds.', 'instagram-feed' );
83
+ ?>
84
+ </td>
85
+ </tr>
86
+ <tr style="padding:0px;vertical-align:top;text-align:left">
87
+ <td align="center" valign="top" style="vertical-align:top;font-family:&quot;Helvetica Neue&quot;,Helvetica,Arial,sans-serif;font-weight:normal;margin:0px;line-height:140%;padding:30px;color:rgb(114,119,124);font-size:12px;text-align:center;border-collapse:collapse">
88
+ <?php
89
+ printf( esc_html__( 'Sent from %s', 'instagram-feed' ), '<a href="' . esc_url( home_url() ) . '">' . esc_html( wp_specialchars_decode( get_bloginfo( 'name' ) ) ) . '</a>' );
90
+ ?>
91
+ <span>&#8226;</span>
92
+ <?php
93
+ printf( esc_html__( '%sLog in and disable these emails%s', 'instagram-feed' ), '<a href="' . esc_url( $footer_link ) . '">', '</a>' );
94
+ ?>
95
+ </td>
96
+ </tr>
97
+ </tbody>
98
+ </table>
99
+ </td>
100
+ </tr></tbody></table>
101
+ </body>
102
+ </html>
inc/if-functions.php CHANGED
@@ -1,1022 +1,1280 @@
1
- <?php
2
- /**
3
- * Contains functions used primarily on the frontend but some also used in the
4
- * admin area.
5
- *
6
- * - Function for the shortcode that displays the feed
7
- * - AJAX call for pagination
8
- * - All AJAX calls for image resizing triggering
9
- * - Clearing page caches for caching plugins
10
- * - Starting cron caching
11
- * - Getting settings from the database
12
- * - Displaying frontend errors
13
- * - Enqueueing CSS and JS files for the feed
14
- *
15
- */
16
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
-
18
- add_filter( 'widget_text', 'do_shortcode' );
19
-
20
- /**
21
- * The main function the creates the feed from a shortcode.
22
- * Can be safely added directly to templates using
23
- * 'echo do_shortcode( "[instagram-feed]" );'
24
- */
25
- add_shortcode('instagram-feed', 'display_instagram');
26
- function display_instagram( $atts = array() ) {
27
-
28
- $database_settings = sbi_get_database_settings();
29
-
30
- if ( $database_settings['sb_instagram_ajax_theme'] !== 'on' && $database_settings['sb_instagram_ajax_theme'] !== 'true' ) {
31
- wp_enqueue_script( 'sb_instagram_scripts' );
32
- }
33
-
34
- if ( $database_settings['enqueue_css_in_shortcode'] === 'on' || $database_settings['enqueue_css_in_shortcode'] === 'true' ) {
35
- wp_enqueue_style( 'sb_instagram_styles' );
36
- }
37
- $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
38
-
39
- if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
40
- $style = current_user_can( 'manage_instagram_feed_options' ) ? ' style="display: block;"' : '';
41
- ob_start(); ?>
42
- <div id="sbi_mod_error" <?php echo $style; ?>>
43
- <span><?php _e('This error message is only visible to WordPress admins', 'instagram-feed' ); ?></span><br />
44
- <p><b><?php _e( 'Error: No connected account.', 'instagram-feed' ); ?></b>
45
- <p><?php _e( 'Please go to the Instagram Feed settings page to connect an account.', 'instagram-feed' ); ?></p>
46
- </div>
47
- <?php
48
- $html = ob_get_contents();
49
- ob_get_clean();
50
- return $html;
51
- }
52
-
53
- $instagram_feed_settings->set_feed_type_and_terms();
54
- $instagram_feed_settings->set_transient_name();
55
- $transient_name = $instagram_feed_settings->get_transient_name();
56
- $settings = $instagram_feed_settings->get_settings();
57
- $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
58
-
59
- $instagram_feed = new SB_Instagram_Feed( $transient_name );
60
-
61
- if ( $database_settings['sbi_caching_type'] === 'background' ) {
62
- $instagram_feed->add_report( 'background caching used' );
63
- if ( $instagram_feed->regular_cache_exists() ) {
64
- $instagram_feed->add_report( 'setting posts from cache' );
65
- $instagram_feed->set_post_data_from_cache();
66
- }
67
-
68
- if ( $instagram_feed->need_to_start_cron_job() ) {
69
- $instagram_feed->add_report( 'setting up feed for cron cache' );
70
- $to_cache = array(
71
- 'atts' => $atts,
72
- 'last_requested' => time(),
73
- );
74
-
75
- $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds() );
76
-
77
- SB_Instagram_Cron_Updater::do_single_feed_cron_update( $instagram_feed_settings, $to_cache, $atts, false );
78
-
79
- $instagram_feed->set_post_data_from_cache();
80
-
81
- } elseif ( $instagram_feed->should_update_last_requested() ) {
82
- $instagram_feed->add_report( 'updating last requested' );
83
- $to_cache = array(
84
- 'last_requested' => time(),
85
- );
86
-
87
- $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
88
- }
89
-
90
- } elseif ( $instagram_feed->regular_cache_exists() ) {
91
- $instagram_feed->add_report( 'page load caching used and regular cache exists' );
92
- $instagram_feed->set_post_data_from_cache();
93
-
94
- if ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
95
- while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
96
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
97
- }
98
- $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
99
- }
100
-
101
- } else {
102
- $instagram_feed->add_report( 'no feed cache found' );
103
-
104
- while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
105
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
106
- }
107
-
108
- if ( ! $instagram_feed->should_use_backup() ) {
109
- $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
110
- }
111
-
112
- }
113
-
114
- if ( $instagram_feed->should_use_backup() ) {
115
- $instagram_feed->add_report( 'trying to use backup' );
116
- $instagram_feed->maybe_set_post_data_from_backup();
117
- $instagram_feed->maybe_set_header_data_from_backup();
118
- }
119
-
120
-
121
- // if need a header
122
- if ( $instagram_feed->need_header( $settings, $feed_type_and_terms ) ) {
123
- if ( $instagram_feed->should_use_backup() && $settings['minnum'] > 0 ) {
124
- $instagram_feed->add_report( 'trying to set header from backup' );
125
- $header_cache_success = $instagram_feed->maybe_set_header_data_from_backup();
126
- } elseif ( $database_settings['sbi_caching_type'] === 'background' ) {
127
- $instagram_feed->add_report( 'background header caching used' );
128
- $instagram_feed->set_header_data_from_cache();
129
- } elseif ( $instagram_feed->regular_header_cache_exists() ) {
130
- // set_post_data_from_cache
131
- $instagram_feed->add_report( 'page load caching used and regular header cache exists' );
132
- $instagram_feed->set_header_data_from_cache();
133
- } else {
134
- $instagram_feed->add_report( 'no header cache exists' );
135
- $instagram_feed->set_remote_header_data( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
136
- $instagram_feed->cache_header_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
137
- }
138
- } else {
139
- $instagram_feed->add_report( 'no header needed' );
140
- }
141
-
142
- if ( $settings['resizeprocess'] === 'page' ) {
143
- $instagram_feed->add_report( 'resizing images for post set' );
144
- $post_data = $instagram_feed->get_post_data();
145
- $post_data = array_slice( $post_data, 0, $settings['num'] );
146
-
147
- $post_set = new SB_Instagram_Post_Set( $post_data, $transient_name );
148
-
149
- $post_set->maybe_save_update_and_resize_images_for_posts();
150
- }
151
-
152
- if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
153
- global $sb_instagram_posts_manager;
154
- $post_data = $instagram_feed->get_post_data();
155
-
156
- if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
157
- $image_ids = array();
158
- foreach ( $post_data as $post ) {
159
- $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
160
- }
161
- $resized_images = SB_Instagram_Feed::get_resized_images_source_set( $image_ids, 0, $transient_name );
162
-
163
- $instagram_feed->set_resized_images( $resized_images );
164
- }
165
- }
166
-
167
- return $instagram_feed->get_the_feed_html( $settings, $atts, $instagram_feed_settings->get_feed_type_and_terms(), $instagram_feed_settings->get_connected_accounts_in_feed() );
168
- }
169
-
170
- /**
171
- * For efficiency, local versions of image files available for the images actually displayed on the page
172
- * are added at the end of the feed.
173
- *
174
- * @param object $instagram_feed
175
- * @param string $feed_id
176
- */
177
- function sbi_add_resized_image_data( $instagram_feed, $feed_id ) {
178
- global $sb_instagram_posts_manager;
179
-
180
- if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
181
- SB_Instagram_Feed::update_last_requested( $instagram_feed->get_image_ids_post_set() );
182
- }
183
- ?>
184
- <span class="sbi_resized_image_data" data-feed-id="<?php echo esc_attr( $feed_id ); ?>" data-resized="<?php echo esc_attr( wp_json_encode( SB_Instagram_Feed::get_resized_images_source_set( $instagram_feed->get_image_ids_post_set(), 0, $feed_id ) ) ); ?>">
185
- </span>
186
- <?php
187
- }
188
- add_action( 'sbi_before_feed_end', 'sbi_add_resized_image_data', 10, 2 );
189
-
190
- /**
191
- * Called after the load more button is clicked using admin-ajax.php.
192
- * Resembles "display_instagram"
193
- */
194
- function sbi_get_next_post_set() {
195
- if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
196
- die( 'invalid feed ID');
197
- }
198
-
199
- $feed_id = sanitize_text_field( $_POST['feed_id'] );
200
- $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
201
- if ( is_array( $atts_raw ) ) {
202
- array_map( 'sanitize_text_field', $atts_raw );
203
- } else {
204
- $atts_raw = array();
205
- }
206
- $atts = $atts_raw; // now sanitized
207
-
208
- $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
209
-
210
- $database_settings = sbi_get_database_settings();
211
- $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
212
-
213
- if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
214
- die( 'error no connected account' );
215
- }
216
-
217
- $instagram_feed_settings->set_feed_type_and_terms();
218
- $instagram_feed_settings->set_transient_name();
219
- $transient_name = $instagram_feed_settings->get_transient_name();
220
-
221
- if ( $transient_name !== $feed_id ) {
222
- die( 'id does not match' );
223
- }
224
-
225
- $settings = $instagram_feed_settings->get_settings();
226
- $current_image_resolution = isset( $_POST['current_resolution'] ) ? (int)$_POST['current_resolution'] : 640;
227
-
228
- switch ( $current_image_resolution ) {
229
- case 150 :
230
- $settings['imageres'] = 'thumb';
231
- break;
232
- case 320 :
233
- $settings['imageres'] = 'medium';
234
- break;
235
- default :
236
- $settings['imageres'] = 'full';
237
- }
238
-
239
- $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
240
-
241
- $instagram_feed = new SB_Instagram_Feed( $transient_name );
242
- if ( $database_settings['sbi_caching_type'] === 'background' ) {
243
- $instagram_feed->add_report( 'background caching used' );
244
- if ( $instagram_feed->regular_cache_exists() ) {
245
- $instagram_feed->add_report( 'setting posts from cache' );
246
- $instagram_feed->set_post_data_from_cache();
247
- }
248
-
249
- if ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
250
- while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
251
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
252
- }
253
-
254
- if ( $instagram_feed->need_to_start_cron_job() ) {
255
- $instagram_feed->add_report( 'needed to start cron job' );
256
- $to_cache = array(
257
- 'atts' => $atts,
258
- 'last_requested' => time(),
259
- );
260
-
261
- $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds() );
262
-
263
- } else {
264
- $instagram_feed->add_report( 'updating last requested and adding to cache' );
265
- $to_cache = array(
266
- 'last_requested' => time(),
267
- );
268
-
269
- $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
270
- }
271
- }
272
-
273
- } elseif ( $instagram_feed->regular_cache_exists() ) {
274
- $instagram_feed->add_report( 'regular cache exists' );
275
- $instagram_feed->set_post_data_from_cache();
276
-
277
- if ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
278
- while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
279
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
280
- }
281
-
282
- $instagram_feed->add_report( 'adding to cache' );
283
- $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
284
- }
285
-
286
-
287
- } else {
288
- $instagram_feed->add_report( 'no feed cache found' );
289
-
290
- while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
291
- $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
292
- }
293
-
294
- if ( $instagram_feed->should_use_backup() ) {
295
- $instagram_feed->add_report( 'trying to use a backup cache' );
296
- $instagram_feed->maybe_set_post_data_from_backup();
297
- } else {
298
- $instagram_feed->add_report( 'transient gone, adding to cache' );
299
- $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
300
- }
301
-
302
- }
303
-
304
- if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
305
- global $sb_instagram_posts_manager;
306
- $post_data = array_slice( $instagram_feed->get_post_data(), $offset, $settings['minnum'] );
307
-
308
- if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
309
- $image_ids = array();
310
- foreach ( $post_data as $post ) {
311
- $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
312
- }
313
- $resized_images = SB_Instagram_Feed::get_resized_images_source_set( $image_ids, 0, $feed_id );
314
-
315
- $instagram_feed->set_resized_images( $resized_images );
316
- }
317
- }
318
-
319
- $feed_status = array( 'shouldPaginate' => $instagram_feed->should_use_pagination( $settings, $offset ) );
320
-
321
- $return = array(
322
- 'html' => $instagram_feed->get_the_items_html( $settings, $offset, $instagram_feed_settings->get_feed_type_and_terms(), $instagram_feed_settings->get_connected_accounts_in_feed() ),
323
- 'feedStatus' => $feed_status,
324
- 'report' => $instagram_feed->get_report(),
325
- 'resizedImages' => SB_Instagram_Feed::get_resized_images_source_set( $instagram_feed->get_image_ids_post_set(), 0, $feed_id )
326
- );
327
-
328
- echo wp_json_encode( $return );
329
-
330
- global $sb_instagram_posts_manager;
331
-
332
- $sb_instagram_posts_manager->update_successful_ajax_test();
333
-
334
- die();
335
- }
336
- add_action( 'wp_ajax_sbi_load_more_clicked', 'sbi_get_next_post_set' );
337
- add_action( 'wp_ajax_nopriv_sbi_load_more_clicked', 'sbi_get_next_post_set' );
338
-
339
- /**
340
- * Posts that need resized images are processed after being sent to the server
341
- * using AJAX
342
- *
343
- * @return string
344
- */
345
- function sbi_process_submitted_resize_ids() {
346
- if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
347
- die( 'invalid feed ID');
348
- }
349
-
350
- $feed_id = sanitize_text_field( $_POST['feed_id'] );
351
- $images_need_resizing_raw = isset( $_POST['needs_resizing'] ) ? $_POST['needs_resizing'] : array();
352
- if ( is_array( $images_need_resizing_raw ) ) {
353
- array_map( 'sanitize_text_field', $images_need_resizing_raw );
354
- } else {
355
- $images_need_resizing_raw = array();
356
- }
357
- $images_need_resizing = $images_need_resizing_raw;
358
-
359
- $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
360
- if ( is_array( $atts_raw ) ) {
361
- array_map( 'sanitize_text_field', $atts_raw );
362
- } else {
363
- $atts_raw = array();
364
- }
365
- $atts = $atts_raw; // now sanitized
366
-
367
- $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
368
-
369
- $database_settings = sbi_get_database_settings();
370
- $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
371
-
372
- if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
373
- return '<div class="sb_instagram_error"><p>' . __( 'Please connect an account on the Instagram Feed plugin Settings page.', 'instagram-feed' ) . '</p></div>';
374
- }
375
-
376
- $instagram_feed_settings->set_feed_type_and_terms();
377
- $instagram_feed_settings->set_transient_name();
378
- $transient_name = $instagram_feed_settings->get_transient_name();
379
-
380
- if ( $transient_name !== $feed_id ) {
381
- die( 'id does not match' );
382
- }
383
-
384
- sbi_resize_posts_by_id( $images_need_resizing, $transient_name, $instagram_feed_settings->get_settings() );
385
-
386
- global $sb_instagram_posts_manager;
387
-
388
- $sb_instagram_posts_manager->update_successful_ajax_test();
389
-
390
- die();
391
- }
392
- add_action( 'wp_ajax_sbi_resized_images_submit', 'sbi_process_submitted_resize_ids' );
393
- add_action( 'wp_ajax_nopriv_sbi_resized_images_submit', 'sbi_process_submitted_resize_ids' );
394
-
395
- /**
396
- * Used for testing if admin-ajax.php can be successfully reached using
397
- * AJAX in the frontend
398
- */
399
- function sbi_update_successful_ajax() {
400
-
401
- global $sb_instagram_posts_manager;
402
-
403
- delete_transient( 'sb_instagram_doing_ajax_test' );
404
-
405
- $sb_instagram_posts_manager->update_successful_ajax_test();
406
-
407
- die();
408
- }
409
- add_action( 'wp_ajax_sbi_on_ajax_test_trigger', 'sbi_update_successful_ajax' );
410
- add_action( 'wp_ajax_nopriv_sbi_on_ajax_test_trigger', 'sbi_update_successful_ajax' );
411
-
412
- /**
413
- * Outputs an organized error report for the front end.
414
- * This hooks into the end of the feed before the closing div
415
- *
416
- * @param object $instagram_feed
417
- * @param string $feed_id
418
- */
419
- function sbi_error_report( $instagram_feed, $feed_id ) {
420
- global $sb_instagram_posts_manager;
421
-
422
- $style = current_user_can( 'manage_instagram_feed_options' ) ? ' style="display: block;"' : '';
423
-
424
- $error_messages = $sb_instagram_posts_manager->get_frontend_errors();
425
- if ( ! empty( $error_messages ) ) {?>
426
- <div id="sbi_mod_error"<?php echo $style; ?>>
427
- <span><?php _e('This error message is only visible to WordPress admins', 'instagram-feed' ); ?></span><br />
428
- <?php foreach ( $error_messages as $error_message ) {
429
- echo $error_message;
430
- } ?>
431
- </div>
432
- <?php
433
- }
434
-
435
- $sb_instagram_posts_manager->reset_frontend_errors();
436
- }
437
- add_action( 'sbi_before_feed_end', 'sbi_error_report', 10, 2 );
438
-
439
- /**
440
- * Debug report added at the end of the feed when sbi_debug query arg is added to a page
441
- * that has the feed on it.
442
- *
443
- * @param object $instagram_feed
444
- * @param string $feed_id
445
- */
446
- function sbi_debug_report( $instagram_feed, $feed_id ) {
447
-
448
- if ( ! isset( $_GET['sbi_debug'] ) ) {
449
- return;
450
- }
451
-
452
- ?>
453
- <p>Status</p>
454
- <ul>
455
- <li>Time: <?php echo date( "Y-m-d H:i:s", time() ); ?></li>
456
- <?php foreach ( $instagram_feed->get_report() as $item ) : ?>
457
- <li><?php echo esc_html( $item ); ?></li>
458
- <?php endforeach; ?>
459
-
460
- </ul>
461
-
462
- <?php
463
- $database_settings = sbi_get_database_settings();
464
-
465
- $public_settings_keys = SB_Instagram_Settings::get_public_db_settings_keys();
466
- ?>
467
- <p>Settings</p>
468
- <ul>
469
- <?php foreach ( $public_settings_keys as $key ) : if ( isset( $database_settings[ $key ] ) ) : ?>
470
- <li>
471
- <small><?php echo esc_html( $key ); ?>:</small>
472
- <?php if ( ! is_array( $database_settings[ $key ] ) ) :
473
- echo $database_settings[ $key ];
474
- else : ?>
475
- <pre>
476
- <?php var_export( $database_settings[ $key ] ); ?>
477
- </pre>
478
- <?php endif; ?>
479
- </li>
480
-
481
- <?php endif; endforeach; ?>
482
- </ul>
483
- <?php
484
- }
485
- add_action( 'sbi_before_feed_end', 'sbi_debug_report', 11, 2 );
486
-
487
- /**
488
- * Uses post IDs to process images that may need resizing
489
- *
490
- * @param array $ids
491
- * @param string $transient_name
492
- * @param array $settings
493
- * @param int $offset
494
- */
495
- function sbi_resize_posts_by_id( $ids, $transient_name, $settings, $offset = 0 ) {
496
- $instagram_feed = new SB_Instagram_Feed( $transient_name );
497
-
498
- if ( $instagram_feed->regular_cache_exists() ) {
499
- // set_post_data_from_cache
500
- $instagram_feed->set_post_data_from_cache();
501
-
502
- $cached_post_data = $instagram_feed->get_post_data();
503
-
504
- $num_ids = count( $ids );
505
- $found_posts = array();
506
- $i = 0;
507
- while ( count( $found_posts) < $num_ids && isset( $cached_post_data[ $i ] ) ) {
508
- if ( ! empty( $cached_post_data[ $i ]['id'] ) && in_array( $cached_post_data[ $i ]['id'], $ids, true ) ) {
509
- $found_posts[] = $cached_post_data[ $i ];
510
- }
511
- $i++;
512
- }
513
-
514
- $fill_in_timestamp = date( 'Y-m-d H:i:s', time() + 120 );
515
-
516
- if ( $offset !== 0 ) {
517
- $fill_in_timestamp = date( 'Y-m-d H:i:s', strtotime( $instagram_feed->get_earliest_time_stamp() ) - 120 );
518
- }
519
-
520
- $post_set = new SB_Instagram_Post_Set( $found_posts, $transient_name, $fill_in_timestamp );
521
-
522
- $post_set->maybe_save_update_and_resize_images_for_posts();
523
- }
524
- }
525
-
526
- /**
527
- * Get the settings in the database with defaults
528
- *
529
- * @return array
530
- */
531
- function sbi_get_database_settings() {
532
- $defaults = array(
533
- 'sb_instagram_at' => '',
534
- 'sb_instagram_user_id' => '',
535
- 'sb_instagram_preserve_settings' => '',
536
- 'sb_instagram_ajax_theme' => false,
537
- 'sb_instagram_disable_resize' => false,
538
- 'sb_instagram_cache_time' => 1,
539
- 'sb_instagram_cache_time_unit' => 'hours',
540
- 'sbi_caching_type' => 'page',
541
- 'sbi_cache_cron_interval' => '12hours',
542
- 'sbi_cache_cron_time' => '1',
543
- 'sbi_cache_cron_am_pm' => 'am',
544
- 'sb_instagram_width' => '100',
545
- 'sb_instagram_width_unit' => '%',
546
- 'sb_instagram_feed_width_resp' => false,
547
- 'sb_instagram_height' => '',
548
- 'sb_instagram_num' => '20',
549
- 'sb_instagram_height_unit' => '',
550
- 'sb_instagram_cols' => '4',
551
- 'sb_instagram_disable_mobile' => false,
552
- 'sb_instagram_image_padding' => '5',
553
- 'sb_instagram_image_padding_unit' => 'px',
554
- 'sb_instagram_sort' => 'none',
555
- 'sb_instagram_background' => '',
556
- 'sb_instagram_show_btn' => true,
557
- 'sb_instagram_btn_background' => '',
558
- 'sb_instagram_btn_text_color' => '',
559
- 'sb_instagram_btn_text' => __( 'Load More...', 'instagram-feed' ),
560
- 'sb_instagram_image_res' => 'auto',
561
- //Header
562
- 'sb_instagram_show_header' => true,
563
- 'sb_instagram_header_size' => 'small',
564
- 'sb_instagram_header_color' => '',
565
- //Follow button
566
- 'sb_instagram_show_follow_btn' => true,
567
- 'sb_instagram_folow_btn_background' => '',
568
- 'sb_instagram_follow_btn_text_color' => '',
569
- 'sb_instagram_follow_btn_text' => __( 'Follow on Instagram', 'instagram-feed' ),
570
- //Misc
571
- 'sb_instagram_custom_css' => '',
572
- 'sb_instagram_custom_js' => '',
573
- 'sb_instagram_cron' => 'no',
574
- 'sb_instagram_backup' => true,
575
- 'sb_ajax_initial' => false,
576
- 'enqueue_css_in_shortcode' => false,
577
- 'sb_instagram_disable_mob_swipe' => false,
578
- 'sbi_font_method' => 'svg',
579
- 'sb_instagram_disable_awesome' => false
580
- );
581
- $sbi_settings = get_option( 'sb_instagram_settings', array() );
582
-
583
- return array_merge( $defaults, $sbi_settings );
584
- }
585
-
586
- /**
587
- * May include support for templates in theme folders in the future
588
- *
589
- * @since 2.1 custom templates supported
590
- */
591
- function sbi_get_feed_template_part( $part, $settings = array() ) {
592
- $file = '';
593
-
594
- $using_custom_templates_in_theme = apply_filters( 'sbi_use_theme_templates', $settings['customtemplates'] );
595
- $generic_path = trailingslashit( SBI_PLUGIN_DIR ) . 'templates/';
596
-
597
- if ( $using_custom_templates_in_theme ) {
598
- $custom_header_template = locate_template( 'sbi/header.php', false, false );
599
- $custom_item_template = locate_template( 'sbi/item.php', false, false );
600
- $custom_footer_template = locate_template( 'sbi/footer.php', false, false );
601
- $custom_feed_template = locate_template( 'sbi/feed.php', false, false );
602
- } else {
603
- $custom_header_template = false;
604
- $custom_item_template = false;
605
- $custom_footer_template = false;
606
- $custom_feed_template = false;
607
- }
608
-
609
- if ( $part === 'header' ) {
610
- if ( $custom_header_template ) {
611
- $file = $custom_header_template;
612
- } else {
613
- $file = $generic_path . 'header.php';
614
- }
615
- } elseif ( $part === 'item' ) {
616
- if ( $custom_item_template ) {
617
- $file = $custom_item_template;
618
- } else {
619
- $file = $generic_path . 'item.php';
620
- }
621
- } elseif ( $part === 'footer' ) {
622
- if ( $custom_footer_template ) {
623
- $file = $custom_footer_template;
624
- } else {
625
- $file = $generic_path . 'footer.php';
626
- }
627
- } elseif ( $part === 'feed' ) {
628
- if ( $custom_feed_template ) {
629
- $file = $custom_feed_template;
630
- } else {
631
- $file = $generic_path . 'feed.php';
632
- }
633
- }
634
-
635
- return $file;
636
- }
637
-
638
- /**
639
- * Triggered by a cron event to update feeds
640
- */
641
- function sbi_cron_updater() {
642
- $sbi_settings = sbi_get_database_settings();
643
-
644
- if ( $sbi_settings['sbi_caching_type'] === 'background' ) {
645
- $cron_updater = new SB_Instagram_Cron_Updater();
646
-
647
- $cron_updater->do_feed_updates();
648
- }
649
-
650
- }
651
- add_action( 'sbi_feed_update', 'sbi_cron_updater' );
652
-
653
- /**
654
- * @param $maybe_dirty
655
- *
656
- * @return string
657
- */
658
- function sbi_maybe_clean( $maybe_dirty ) {
659
- if ( substr_count ( $maybe_dirty , '.' ) < 3 ) {
660
- return str_replace( '634hgdf83hjdj2', '', $maybe_dirty );
661
- }
662
-
663
- $parts = explode( '.', trim( $maybe_dirty ) );
664
- $last_part = $parts[2] . $parts[3];
665
- $cleaned = $parts[0] . '.' . base64_decode( $parts[1] ) . '.' . base64_decode( $last_part );
666
-
667
- return $cleaned;
668
- }
669
-
670
- /**
671
- * @param $whole
672
- *
673
- * @return string
674
- */
675
- function sbi_get_parts( $whole ) {
676
- if ( substr_count ( $whole , '.' ) !== 2 ) {
677
- return $whole;
678
- }
679
-
680
- $parts = explode( '.', trim( $whole ) );
681
- $return = $parts[0] . '.' . base64_encode( $parts[1] ). '.' . base64_encode( $parts[2] );
682
-
683
- return substr( $return, 0, 40 ) . '.' . substr( $return, 40, 100 );
684
- }
685
-
686
- /**
687
- * @param $a
688
- * @param $b
689
- *
690
- * @return false|int
691
- */
692
- function sbi_date_sort( $a, $b ) {
693
- $time_stamp_a = SB_Instagram_Parse::get_timestamp( $a );
694
- $time_stamp_b = SB_Instagram_Parse::get_timestamp( $b );
695
-
696
- if ( isset( $time_stamp_a ) ) {
697
- return $time_stamp_b - $time_stamp_a;
698
- } else {
699
- return rand ( -1, 1 );
700
- }
701
- }
702
-
703
- function sbi_code_check( $code ) {
704
- if ( strpos( $code, '634hgdf83hjdj2') !== false ) {
705
- return true;
706
- }
707
- return false;
708
- }
709
-
710
- function sbi_fixer( $code ) {
711
- if ( strpos( $code, '634hgdf83hjdj2') !== false ) {
712
- return $code;
713
- } else {
714
- return substr_replace( $code , '634hgdf83hjdj2', 15, 0 );
715
- }
716
- }
717
-
718
- /**
719
- * @param $a
720
- * @param $b
721
- *
722
- * @return false|int
723
- */
724
- function sbi_rand_sort( $a, $b ) {
725
- return rand ( -1, 1 );
726
- }
727
-
728
- /**
729
- * @return string
730
- *
731
- * @since 2.1.1
732
- */
733
- function sbi_get_resized_uploads_url() {
734
- $upload = wp_upload_dir();
735
-
736
- return trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
737
- }
738
-
739
- /**
740
- * Converts a hex code to RGB so opacity can be
741
- * applied more easily
742
- *
743
- * @param $hex
744
- *
745
- * @return string
746
- */
747
- function sbi_hextorgb( $hex ) {
748
- // allows someone to use rgb in shortcode
749
- if ( strpos( $hex, ',' ) !== false ) {
750
- return $hex;
751
- }
752
-
753
- $hex = str_replace( '#', '', $hex );
754
-
755
- if ( strlen( $hex ) === 3 ) {
756
- $r = hexdec( substr( $hex,0,1 ).substr( $hex,0,1 ) );
757
- $g = hexdec( substr( $hex,1,1 ).substr( $hex,1,1 ) );
758
- $b = hexdec( substr( $hex,2,1 ).substr( $hex,2,1 ) );
759
- } else {
760
- $r = hexdec( substr( $hex,0,2 ) );
761
- $g = hexdec( substr( $hex,2,2 ) );
762
- $b = hexdec( substr( $hex,4,2 ) );
763
- }
764
- $rgb = array( $r, $g, $b );
765
-
766
- return implode( ',', $rgb ); // returns the rgb values separated by commas
767
- }
768
-
769
-
770
- /**
771
- * Added to workaround MySQL tables that don't use utf8mb4 character sets
772
- *
773
- * @since 2.2.1/5.3.1
774
- */
775
- function sbi_sanitize_emoji( $string ) {
776
- $encoded = array(
777
- 'jsonencoded' => $string
778
- );
779
- return wp_json_encode( $encoded );
780
- }
781
-
782
- /**
783
- * Added to workaround MySQL tables that don't use utf8mb4 character sets
784
- *
785
- * @since 2.2.1/5.3.1
786
- */
787
- function sbi_decode_emoji( $string ) {
788
- if ( strpos( $string, '{"' ) !== false ) {
789
- $decoded = json_decode( $string, true );
790
- return $decoded['jsonencoded'];
791
- }
792
- return $string;
793
- }
794
-
795
- /**
796
- * @return int
797
- */
798
- function sbi_get_utc_offset() {
799
- return get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS;
800
- }
801
-
802
- function sbi_get_current_timestamp() {
803
- $current_time = time();
804
-
805
- //$current_time = strtotime( 'November 25, 2022' ) + 1;
806
-
807
- return $current_time;
808
- }
809
-
810
- function sbi_is_after_deprecation_deadline() {
811
- $current_time = sbi_get_current_timestamp();
812
-
813
- return $current_time > strtotime( 'March 3, 2020' );
814
- }
815
-
816
- /**
817
- * Used to clear caches when transients aren't working
818
- * properly
819
- */
820
- function sb_instagram_cron_clear_cache() {
821
- //Delete all transients
822
- global $wpdb;
823
- $table_name = $wpdb->prefix . "options";
824
- $wpdb->query( "
825
- DELETE
826
- FROM $table_name
827
- WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
828
- " );
829
- $wpdb->query( "
830
- DELETE
831
- FROM $table_name
832
- WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
833
- " );
834
- $wpdb->query( "
835
- DELETE
836
- FROM $table_name
837
- WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
838
- " );
839
- $wpdb->query( "
840
- DELETE
841
- FROM $table_name
842
- WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
843
- " );
844
- $wpdb->query( "
845
- DELETE
846
- FROM $table_name
847
- WHERE `option_name` LIKE ('%\_transient\_\$sbi\_%')
848
- " );
849
- $wpdb->query( "
850
- DELETE
851
- FROM $table_name
852
- WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sbi\_%')
853
- " );
854
-
855
- sb_instagram_clear_page_caches();
856
- }
857
-
858
- /**
859
- * When certain events occur, page caches need to
860
- * clear or errors occur or changes will not be seen
861
- */
862
- function sb_instagram_clear_page_caches() {
863
- if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ){
864
- /* Clear WP fastest cache*/
865
- $GLOBALS['wp_fastest_cache']->deleteCache();
866
- }
867
-
868
- if ( function_exists( 'wp_cache_clear_cache' ) ) {
869
- wp_cache_clear_cache();
870
- }
871
-
872
- if ( class_exists('W3_Plugin_TotalCacheAdmin') ) {
873
- $plugin_totalcacheadmin = & w3_instance('W3_Plugin_TotalCacheAdmin');
874
-
875
- $plugin_totalcacheadmin->flush_all();
876
- }
877
-
878
- if ( function_exists( 'rocket_clean_domain' ) ) {
879
- rocket_clean_domain();
880
- }
881
-
882
- if ( class_exists( 'autoptimizeCache' ) ) {
883
- /* Clear autoptimize */
884
- autoptimizeCache::clearall();
885
- }
886
-
887
- // Litespeed Cache
888
- if ( method_exists( 'LiteSpeed_Cache_API', 'purge' ) ) {
889
- LiteSpeed_Cache_API::purge( 'esi.instagram-feed' );
890
- }
891
- }
892
-
893
- /**
894
- * Makes the JavaScript file available and enqueues the stylesheet
895
- * for the plugin
896
- */
897
- function sb_instagram_scripts_enqueue() {
898
- //Register the script to make it available
899
-
900
- //Options to pass to JS file
901
- $sb_instagram_settings = get_option( 'sb_instagram_settings' );
902
-
903
- $js_file = 'js/sb-instagram-2-2.min.js';
904
- if ( isset( $_GET['sbi_debug'] ) ) {
905
- $js_file = 'js/sb-instagram.js';
906
- }
907
-
908
- if ( isset( $sb_instagram_settings['enqueue_js_in_head'] ) && $sb_instagram_settings['enqueue_js_in_head'] ) {
909
- wp_enqueue_script( 'sb_instagram_scripts', trailingslashit( SBI_PLUGIN_URL ) . $js_file, array('jquery'), SBIVER, false );
910
- } else {
911
- wp_register_script( 'sb_instagram_scripts', trailingslashit( SBI_PLUGIN_URL ) . $js_file, array('jquery'), SBIVER, true );
912
- }
913
-
914
- if ( isset( $sb_instagram_settings['enqueue_css_in_shortcode'] ) && $sb_instagram_settings['enqueue_css_in_shortcode'] ) {
915
- wp_register_style( 'sb_instagram_styles', trailingslashit( SBI_PLUGIN_URL ) . 'css/sb-instagram-2-2.min.css', array(), SBIVER );
916
- } else {
917
- wp_enqueue_style( 'sb_instagram_styles', trailingslashit( SBI_PLUGIN_URL ) . 'css/sb-instagram-2-2.min.css', array(), SBIVER );
918
- }
919
-
920
- $font_method = isset( $sb_instagram_settings['sbi_font_method'] ) ? $sb_instagram_settings['sbi_font_method'] : 'svg';
921
-
922
- if ( isset( $sb_instagram_settings['sb_instagram_disable_awesome'] ) ) {
923
- $disable_font_awesome = isset( $sb_instagram_settings['sb_instagram_disable_awesome'] ) ? $sb_instagram_settings['sb_instagram_disable_awesome'] === 'on' : false;
924
- } else {
925
- $disable_font_awesome = isset( $sb_instagram_settings['sb_instagram_disable_font'] ) ? $sb_instagram_settings['sb_instagram_disable_font'] === 'on' : false;
926
- }
927
-
928
- if ( $font_method === 'fontfile' && ! $disable_font_awesome ) {
929
- wp_enqueue_style( 'sb-font-awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' );
930
- }
931
-
932
- $data = array(
933
- 'font_method' => $font_method,
934
- 'resized_url' => sbi_get_resized_uploads_url(),
935
- 'placeholder' => trailingslashit( SBI_PLUGIN_URL ) . 'img/placeholder.png'
936
- );
937
- //Pass option to JS file
938
- wp_localize_script('sb_instagram_scripts', 'sb_instagram_js_options', $data );
939
- }
940
- add_action( 'wp_enqueue_scripts', 'sb_instagram_scripts_enqueue', 2 );
941
-
942
- /**
943
- * Adds the ajax url and custom JavaScript to the page
944
- */
945
- function sb_instagram_custom_js() {
946
- $options = get_option('sb_instagram_settings');
947
- isset($options[ 'sb_instagram_custom_js' ]) ? $sb_instagram_custom_js = trim($options['sb_instagram_custom_js']) : $sb_instagram_custom_js = '';
948
-
949
- echo '<!-- Instagram Feed JS -->';
950
- echo "\r\n";
951
- echo '<script type="text/javascript">';
952
- echo "\r\n";
953
- echo 'var sbiajaxurl = "' . admin_url('admin-ajax.php') . '";';
954
-
955
- if ( !empty( $sb_instagram_custom_js ) ) {
956
- echo "\r\n";
957
- echo "jQuery( document ).ready(function($) {";
958
- echo "\r\n";
959
- echo "window.sbi_custom_js = function(){";
960
- echo "\r\n";
961
- echo stripslashes($sb_instagram_custom_js);
962
- echo "\r\n";
963
- echo "}";
964
- echo "\r\n";
965
- echo "});";
966
- }
967
-
968
- echo "\r\n";
969
- echo '</script>';
970
- echo "\r\n";
971
- }
972
- add_action( 'wp_footer', 'sb_instagram_custom_js' );
973
-
974
- //Custom CSS
975
- add_action( 'wp_head', 'sb_instagram_custom_css' );
976
- function sb_instagram_custom_css() {
977
- $options = get_option('sb_instagram_settings');
978
-
979
- isset($options[ 'sb_instagram_custom_css' ]) ? $sb_instagram_custom_css = trim($options['sb_instagram_custom_css']) : $sb_instagram_custom_css = '';
980
-
981
- //Show CSS if an admin (so can see Hide Photos link), if including Custom CSS or if hiding some photos
982
- ( current_user_can( 'edit_posts' ) || !empty($sb_instagram_custom_css) || !empty($sb_instagram_hide_photos) ) ? $sbi_show_css = true : $sbi_show_css = false;
983
-
984
- if( $sbi_show_css ) echo '<!-- Instagram Feed CSS -->';
985
- if( $sbi_show_css ) echo "\r\n";
986
- if( $sbi_show_css ) echo '<style type="text/css">';
987
-
988
- if( !empty($sb_instagram_custom_css) ){
989
- echo "\r\n";
990
- echo stripslashes($sb_instagram_custom_css);
991
- }
992
-
993
- if( current_user_can( 'edit_posts' ) ){
994
- echo "\r\n";
995
- echo "#sbi_mod_link, #sbi_mod_error{ display: block !important; width: 100%; float: left; box-sizing: border-box; }";
996
- }
997
-
998
- if( $sbi_show_css ) echo "\r\n";
999
- if( $sbi_show_css ) echo '</style>';
1000
- if( $sbi_show_css ) echo "\r\n";
1001
- }
1002
-
1003
- /**
1004
- * Used to change the number of posts in the api request. Useful for filtered posts
1005
- * or special caching situations.
1006
- *
1007
- * @param int $num
1008
- * @param array $settings
1009
- *
1010
- * @return int
1011
- */
1012
- function sbi_raise_num_in_request( $num, $settings ) {
1013
- if ( $settings['sortby'] === 'random' ) {
1014
- if ( $num > 5 ) {
1015
- return min( $num * 4, 100 );
1016
- } else {
1017
- return 20;
1018
- }
1019
- }
1020
- return $num;
1021
- }
1022
- add_filter( 'sbi_num_in_request', 'sbi_raise_num_in_request', 5, 2 );
1
+ <?php
2
+ /**
3
+ * Contains functions used primarily on the frontend but some also used in the
4
+ * admin area.
5
+ *
6
+ * - Function for the shortcode that displays the feed
7
+ * - AJAX call for pagination
8
+ * - All AJAX calls for image resizing triggering
9
+ * - Clearing page caches for caching plugins
10
+ * - Starting cron caching
11
+ * - Getting settings from the database
12
+ * - Displaying frontend errors
13
+ * - Enqueueing CSS and JS files for the feed
14
+ *
15
+ */
16
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
+
18
+ add_filter( 'widget_text', 'do_shortcode' );
19
+
20
+ /**
21
+ * The main function the creates the feed from a shortcode.
22
+ * Can be safely added directly to templates using
23
+ * 'echo do_shortcode( "[instagram-feed]" );'
24
+ */
25
+ add_shortcode('instagram-feed', 'display_instagram');
26
+ function display_instagram( $atts = array() ) {
27
+
28
+ $database_settings = sbi_get_database_settings();
29
+
30
+ if ( $database_settings['sb_instagram_ajax_theme'] !== 'on' && $database_settings['sb_instagram_ajax_theme'] !== 'true' ) {
31
+ wp_enqueue_script( 'sb_instagram_scripts' );
32
+ }
33
+
34
+ if ( $database_settings['enqueue_css_in_shortcode'] === 'on' || $database_settings['enqueue_css_in_shortcode'] === 'true' ) {
35
+ wp_enqueue_style( 'sb_instagram_styles' );
36
+ }
37
+ $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
38
+
39
+ if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
40
+ $style = current_user_can( 'manage_instagram_feed_options' ) ? ' style="display: block;"' : '';
41
+ ob_start(); ?>
42
+ <div id="sbi_mod_error" <?php echo $style; ?>>
43
+ <span><?php _e('This error message is only visible to WordPress admins', 'instagram-feed' ); ?></span><br />
44
+ <p><b><?php _e( 'Error: No connected account.', 'instagram-feed' ); ?></b>
45
+ <p><?php _e( 'Please go to the Instagram Feed settings page to connect an account.', 'instagram-feed' ); ?></p>
46
+ </div>
47
+ <?php
48
+ $html = ob_get_contents();
49
+ ob_get_clean();
50
+ return $html;
51
+ }
52
+
53
+ $instagram_feed_settings->set_feed_type_and_terms();
54
+ $instagram_feed_settings->set_transient_name();
55
+ $transient_name = $instagram_feed_settings->get_transient_name();
56
+ $settings = $instagram_feed_settings->get_settings();
57
+ $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
58
+
59
+ $instagram_feed = new SB_Instagram_Feed( $transient_name );
60
+
61
+ if ( $database_settings['sbi_caching_type'] === 'background' ) {
62
+ $instagram_feed->add_report( 'background caching used' );
63
+ if ( $instagram_feed->regular_cache_exists() ) {
64
+ $instagram_feed->add_report( 'setting posts from cache' );
65
+ $instagram_feed->set_post_data_from_cache();
66
+ }
67
+
68
+ if ( $instagram_feed->need_to_start_cron_job() ) {
69
+ $instagram_feed->add_report( 'setting up feed for cron cache' );
70
+ $to_cache = array(
71
+ 'atts' => $atts,
72
+ 'last_requested' => time(),
73
+ );
74
+
75
+ $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds() );
76
+
77
+ SB_Instagram_Cron_Updater::do_single_feed_cron_update( $instagram_feed_settings, $to_cache, $atts, false );
78
+
79
+ $instagram_feed->set_post_data_from_cache();
80
+
81
+ } elseif ( $instagram_feed->should_update_last_requested() ) {
82
+ $instagram_feed->add_report( 'updating last requested' );
83
+ $to_cache = array(
84
+ 'last_requested' => time(),
85
+ );
86
+
87
+ $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
88
+ }
89
+
90
+ } elseif ( $instagram_feed->regular_cache_exists() ) {
91
+ $instagram_feed->add_report( 'page load caching used and regular cache exists' );
92
+ $instagram_feed->set_post_data_from_cache();
93
+
94
+ if ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
95
+ while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
96
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
97
+ }
98
+ $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
99
+ }
100
+
101
+ } else {
102
+ $instagram_feed->add_report( 'no feed cache found' );
103
+
104
+ while ( $instagram_feed->need_posts( $settings['num'] ) && $instagram_feed->can_get_more_posts() ) {
105
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
106
+ }
107
+
108
+ if ( ! $instagram_feed->should_use_backup() ) {
109
+ $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
110
+ }
111
+
112
+ }
113
+
114
+ if ( $instagram_feed->should_use_backup() ) {
115
+ $instagram_feed->add_report( 'trying to use backup' );
116
+ $instagram_feed->maybe_set_post_data_from_backup();
117
+ $instagram_feed->maybe_set_header_data_from_backup();
118
+ }
119
+
120
+
121
+ // if need a header
122
+ if ( $instagram_feed->need_header( $settings, $feed_type_and_terms ) ) {
123
+ if ( $instagram_feed->should_use_backup() && $settings['minnum'] > 0 ) {
124
+ $instagram_feed->add_report( 'trying to set header from backup' );
125
+ $header_cache_success = $instagram_feed->maybe_set_header_data_from_backup();
126
+ } elseif ( $database_settings['sbi_caching_type'] === 'background' ) {
127
+ $instagram_feed->add_report( 'background header caching used' );
128
+ $instagram_feed->set_header_data_from_cache();
129
+ } elseif ( $instagram_feed->regular_header_cache_exists() ) {
130
+ // set_post_data_from_cache
131
+ $instagram_feed->add_report( 'page load caching used and regular header cache exists' );
132
+ $instagram_feed->set_header_data_from_cache();
133
+ } else {
134
+ $instagram_feed->add_report( 'no header cache exists' );
135
+ $instagram_feed->set_remote_header_data( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
136
+ $instagram_feed->cache_header_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
137
+ }
138
+ } else {
139
+ $instagram_feed->add_report( 'no header needed' );
140
+ }
141
+
142
+ if ( $settings['resizeprocess'] === 'page' ) {
143
+ $instagram_feed->add_report( 'resizing images for post set' );
144
+ $post_data = $instagram_feed->get_post_data();
145
+ $post_data = array_slice( $post_data, 0, $settings['num'] );
146
+
147
+ $post_set = new SB_Instagram_Post_Set( $post_data, $transient_name );
148
+
149
+ $post_set->maybe_save_update_and_resize_images_for_posts();
150
+ }
151
+
152
+ if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
153
+ global $sb_instagram_posts_manager;
154
+ $post_data = $instagram_feed->get_post_data();
155
+
156
+ if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
157
+ $image_ids = array();
158
+ foreach ( $post_data as $post ) {
159
+ $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
160
+ }
161
+ $resized_images = SB_Instagram_Feed::get_resized_images_source_set( $image_ids, 0, $transient_name );
162
+
163
+ $instagram_feed->set_resized_images( $resized_images );
164
+ }
165
+ }
166
+
167
+ return $instagram_feed->get_the_feed_html( $settings, $atts, $instagram_feed_settings->get_feed_type_and_terms(), $instagram_feed_settings->get_connected_accounts_in_feed() );
168
+ }
169
+
170
+ /**
171
+ * For efficiency, local versions of image files available for the images actually displayed on the page
172
+ * are added at the end of the feed.
173
+ *
174
+ * @param object $instagram_feed
175
+ * @param string $feed_id
176
+ */
177
+ function sbi_add_resized_image_data( $instagram_feed, $feed_id ) {
178
+ global $sb_instagram_posts_manager;
179
+
180
+ if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
181
+ SB_Instagram_Feed::update_last_requested( $instagram_feed->get_image_ids_post_set() );
182
+ }
183
+ ?>
184
+ <span class="sbi_resized_image_data" data-feed-id="<?php echo esc_attr( $feed_id ); ?>" data-resized="<?php echo esc_attr( wp_json_encode( SB_Instagram_Feed::get_resized_images_source_set( $instagram_feed->get_image_ids_post_set(), 0, $feed_id ) ) ); ?>">
185
+ </span>
186
+ <?php
187
+ }
188
+ add_action( 'sbi_before_feed_end', 'sbi_add_resized_image_data', 10, 2 );
189
+
190
+ /**
191
+ * Called after the load more button is clicked using admin-ajax.php.
192
+ * Resembles "display_instagram"
193
+ */
194
+ function sbi_get_next_post_set() {
195
+ if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
196
+ die( 'invalid feed ID');
197
+ }
198
+
199
+ $feed_id = sanitize_text_field( $_POST['feed_id'] );
200
+ $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
201
+ if ( is_array( $atts_raw ) ) {
202
+ array_map( 'sanitize_text_field', $atts_raw );
203
+ } else {
204
+ $atts_raw = array();
205
+ }
206
+ $atts = $atts_raw; // now sanitized
207
+
208
+ $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
209
+
210
+ $database_settings = sbi_get_database_settings();
211
+ $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
212
+
213
+ if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
214
+ die( 'error no connected account' );
215
+ }
216
+
217
+ $instagram_feed_settings->set_feed_type_and_terms();
218
+ $instagram_feed_settings->set_transient_name();
219
+ $transient_name = $instagram_feed_settings->get_transient_name();
220
+
221
+ if ( $transient_name !== $feed_id ) {
222
+ die( 'id does not match' );
223
+ }
224
+
225
+ $settings = $instagram_feed_settings->get_settings();
226
+ $current_image_resolution = isset( $_POST['current_resolution'] ) ? (int)$_POST['current_resolution'] : 640;
227
+
228
+ switch ( $current_image_resolution ) {
229
+ case 150 :
230
+ $settings['imageres'] = 'thumb';
231
+ break;
232
+ case 320 :
233
+ $settings['imageres'] = 'medium';
234
+ break;
235
+ default :
236
+ $settings['imageres'] = 'full';
237
+ }
238
+
239
+ $feed_type_and_terms = $instagram_feed_settings->get_feed_type_and_terms();
240
+
241
+ $instagram_feed = new SB_Instagram_Feed( $transient_name );
242
+ if ( $database_settings['sbi_caching_type'] === 'background' ) {
243
+ $instagram_feed->add_report( 'background caching used' );
244
+ if ( $instagram_feed->regular_cache_exists() ) {
245
+ $instagram_feed->add_report( 'setting posts from cache' );
246
+ $instagram_feed->set_post_data_from_cache();
247
+ }
248
+
249
+ if ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
250
+ while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
251
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
252
+ }
253
+
254
+ if ( $instagram_feed->need_to_start_cron_job() ) {
255
+ $instagram_feed->add_report( 'needed to start cron job' );
256
+ $to_cache = array(
257
+ 'atts' => $atts,
258
+ 'last_requested' => time(),
259
+ );
260
+
261
+ $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds() );
262
+
263
+ } else {
264
+ $instagram_feed->add_report( 'updating last requested and adding to cache' );
265
+ $to_cache = array(
266
+ 'last_requested' => time(),
267
+ );
268
+
269
+ $instagram_feed->set_cron_cache( $to_cache, $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
270
+ }
271
+ }
272
+
273
+ } elseif ( $instagram_feed->regular_cache_exists() ) {
274
+ $instagram_feed->add_report( 'regular cache exists' );
275
+ $instagram_feed->set_post_data_from_cache();
276
+
277
+ if ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
278
+ while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
279
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
280
+ }
281
+
282
+ $instagram_feed->add_report( 'adding to cache' );
283
+ $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
284
+ }
285
+
286
+
287
+ } else {
288
+ $instagram_feed->add_report( 'no feed cache found' );
289
+
290
+ while ( $instagram_feed->need_posts( $settings['num'], $offset ) && $instagram_feed->can_get_more_posts() ) {
291
+ $instagram_feed->add_remote_posts( $settings, $feed_type_and_terms, $instagram_feed_settings->get_connected_accounts_in_feed() );
292
+ }
293
+
294
+ if ( $instagram_feed->should_use_backup() ) {
295
+ $instagram_feed->add_report( 'trying to use a backup cache' );
296
+ $instagram_feed->maybe_set_post_data_from_backup();
297
+ } else {
298
+ $instagram_feed->add_report( 'transient gone, adding to cache' );
299
+ $instagram_feed->cache_feed_data( $instagram_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
300
+ }
301
+
302
+ }
303
+
304
+ if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
305
+ global $sb_instagram_posts_manager;
306
+ $post_data = array_slice( $instagram_feed->get_post_data(), $offset, $settings['minnum'] );
307
+
308
+ if ( ! $sb_instagram_posts_manager->image_resizing_disabled() ) {
309
+ $image_ids = array();
310
+ foreach ( $post_data as $post ) {
311
+ $image_ids[] = SB_Instagram_Parse::get_post_id( $post );
312
+ }
313
+ $resized_images = SB_Instagram_Feed::get_resized_images_source_set( $image_ids, 0, $feed_id );
314
+
315
+ $instagram_feed->set_resized_images( $resized_images );
316
+ }
317
+ }
318
+
319
+ $feed_status = array( 'shouldPaginate' => $instagram_feed->should_use_pagination( $settings, $offset ) );
320
+
321
+ $return = array(
322
+ 'html' => $instagram_feed->get_the_items_html( $settings, $offset, $instagram_feed_settings->get_feed_type_and_terms(), $instagram_feed_settings->get_connected_accounts_in_feed() ),
323
+ 'feedStatus' => $feed_status,
324
+ 'report' => $instagram_feed->get_report(),
325
+ 'resizedImages' => SB_Instagram_Feed::get_resized_images_source_set( $instagram_feed->get_image_ids_post_set(), 0, $feed_id )
326
+ );
327
+
328
+ echo wp_json_encode( $return );
329
+
330
+ global $sb_instagram_posts_manager;
331
+
332
+ $sb_instagram_posts_manager->update_successful_ajax_test();
333
+
334
+ die();
335
+ }
336
+ add_action( 'wp_ajax_sbi_load_more_clicked', 'sbi_get_next_post_set' );
337
+ add_action( 'wp_ajax_nopriv_sbi_load_more_clicked', 'sbi_get_next_post_set' );
338
+
339
+ /**
340
+ * Posts that need resized images are processed after being sent to the server
341
+ * using AJAX
342
+ *
343
+ * @return string
344
+ */
345
+ function sbi_process_submitted_resize_ids() {
346
+ if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
347
+ die( 'invalid feed ID');
348
+ }
349
+
350
+ $feed_id = sanitize_text_field( $_POST['feed_id'] );
351
+ $images_need_resizing_raw = isset( $_POST['needs_resizing'] ) ? $_POST['needs_resizing'] : array();
352
+ if ( is_array( $images_need_resizing_raw ) ) {
353
+ array_map( 'sanitize_text_field', $images_need_resizing_raw );
354
+ } else {
355
+ $images_need_resizing_raw = array();
356
+ }
357
+ $images_need_resizing = $images_need_resizing_raw;
358
+
359
+ $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
360
+ if ( is_array( $atts_raw ) ) {
361
+ array_map( 'sanitize_text_field', $atts_raw );
362
+ } else {
363
+ $atts_raw = array();
364
+ }
365
+ $atts = $atts_raw; // now sanitized
366
+
367
+ $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
368
+
369
+ $database_settings = sbi_get_database_settings();
370
+ $instagram_feed_settings = new SB_Instagram_Settings( $atts, $database_settings );
371
+
372
+ if ( empty( $database_settings['connected_accounts'] ) && empty( $atts['accesstoken'] ) ) {
373
+ return '<div class="sb_instagram_error"><p>' . __( 'Please connect an account on the Instagram Feed plugin Settings page.', 'instagram-feed' ) . '</p></div>';
374
+ }
375
+
376
+ $instagram_feed_settings->set_feed_type_and_terms();
377
+ $instagram_feed_settings->set_transient_name();
378
+ $transient_name = $instagram_feed_settings->get_transient_name();
379
+
380
+ if ( $transient_name !== $feed_id ) {
381
+ die( 'id does not match' );
382
+ }
383
+
384
+ sbi_resize_posts_by_id( $images_need_resizing, $transient_name, $instagram_feed_settings->get_settings() );
385
+
386
+ global $sb_instagram_posts_manager;
387
+
388
+ $sb_instagram_posts_manager->update_successful_ajax_test();
389
+
390
+ die();
391
+ }
392
+ add_action( 'wp_ajax_sbi_resized_images_submit', 'sbi_process_submitted_resize_ids' );
393
+ add_action( 'wp_ajax_nopriv_sbi_resized_images_submit', 'sbi_process_submitted_resize_ids' );
394
+
395
+ /**
396
+ * Used for testing if admin-ajax.php can be successfully reached using
397
+ * AJAX in the frontend
398
+ */
399
+ function sbi_update_successful_ajax() {
400
+
401
+ global $sb_instagram_posts_manager;
402
+
403
+ delete_transient( 'sb_instagram_doing_ajax_test' );
404
+
405
+ $sb_instagram_posts_manager->update_successful_ajax_test();
406
+
407
+ die();
408
+ }
409
+ add_action( 'wp_ajax_sbi_on_ajax_test_trigger', 'sbi_update_successful_ajax' );
410
+ add_action( 'wp_ajax_nopriv_sbi_on_ajax_test_trigger', 'sbi_update_successful_ajax' );
411
+
412
+ /**
413
+ * Outputs an organized error report for the front end.
414
+ * This hooks into the end of the feed before the closing div
415
+ *
416
+ * @param object $instagram_feed
417
+ * @param string $feed_id
418
+ */
419
+ function sbi_error_report( $instagram_feed, $feed_id ) {
420
+ global $sb_instagram_posts_manager;
421
+
422
+ $style = current_user_can( 'manage_instagram_feed_options' ) ? ' style="display: block;"' : '';
423
+
424
+ $error_messages = $sb_instagram_posts_manager->get_frontend_errors();
425
+ if ( ! empty( $error_messages ) ) {?>
426
+ <div id="sbi_mod_error"<?php echo $style; ?>>
427
+ <span><?php _e('This error message is only visible to WordPress admins', 'instagram-feed' ); ?></span><br />
428
+ <?php foreach ( $error_messages as $error_message ) {
429
+ echo $error_message;
430
+ } ?>
431
+ </div>
432
+ <?php
433
+ }
434
+
435
+ $sb_instagram_posts_manager->reset_frontend_errors();
436
+ }
437
+ add_action( 'sbi_before_feed_end', 'sbi_error_report', 10, 2 );
438
+
439
+ /**
440
+ * Debug report added at the end of the feed when sbi_debug query arg is added to a page
441
+ * that has the feed on it.
442
+ *
443
+ * @param object $instagram_feed
444
+ * @param string $feed_id
445
+ */
446
+ function sbi_debug_report( $instagram_feed, $feed_id ) {
447
+
448
+ if ( ! isset( $_GET['sbi_debug'] ) ) {
449
+ return;
450
+ }
451
+
452
+ ?>
453
+ <p>Status</p>
454
+ <ul>
455
+ <li>Time: <?php echo date( "Y-m-d H:i:s", time() ); ?></li>
456
+ <?php foreach ( $instagram_feed->get_report() as $item ) : ?>
457
+ <li><?php echo esc_html( $item ); ?></li>
458
+ <?php endforeach; ?>
459
+
460
+ </ul>
461
+
462
+ <?php
463
+ $database_settings = sbi_get_database_settings();
464
+
465
+ $public_settings_keys = SB_Instagram_Settings::get_public_db_settings_keys();
466
+ ?>
467
+ <p>Settings</p>
468
+ <ul>
469
+ <?php foreach ( $public_settings_keys as $key ) : if ( isset( $database_settings[ $key ] ) ) : ?>
470
+ <li>
471
+ <small><?php echo esc_html( $key ); ?>:</small>
472
+ <?php if ( ! is_array( $database_settings[ $key ] ) ) :
473
+ echo $database_settings[ $key ];
474
+ else : ?>
475
+ <pre>
476
+ <?php var_export( $database_settings[ $key ] ); ?>
477
+ </pre>
478
+ <?php endif; ?>
479
+ </li>
480
+
481
+ <?php endif; endforeach; ?>
482
+ </ul>
483
+ <?php
484
+ }
485
+ add_action( 'sbi_before_feed_end', 'sbi_debug_report', 11, 2 );
486
+
487
+ /**
488
+ * Uses post IDs to process images that may need resizing
489
+ *
490
+ * @param array $ids
491
+ * @param string $transient_name
492
+ * @param array $settings
493
+ * @param int $offset
494
+ */
495
+ function sbi_resize_posts_by_id( $ids, $transient_name, $settings, $offset = 0 ) {
496
+ $instagram_feed = new SB_Instagram_Feed( $transient_name );
497
+
498
+ if ( $instagram_feed->regular_cache_exists() ) {
499
+ // set_post_data_from_cache
500
+ $instagram_feed->set_post_data_from_cache();
501
+
502
+ $cached_post_data = $instagram_feed->get_post_data();
503
+
504
+ $num_ids = count( $ids );
505
+ $found_posts = array();
506
+ $i = 0;
507
+ while ( count( $found_posts) < $num_ids && isset( $cached_post_data[ $i ] ) ) {
508
+ if ( ! empty( $cached_post_data[ $i ]['id'] ) && in_array( $cached_post_data[ $i ]['id'], $ids, true ) ) {
509
+ $found_posts[] = $cached_post_data[ $i ];
510
+ }
511
+ $i++;
512
+ }
513
+
514
+ $fill_in_timestamp = date( 'Y-m-d H:i:s', time() + 120 );
515
+
516
+ if ( $offset !== 0 ) {
517
+ $fill_in_timestamp = date( 'Y-m-d H:i:s', strtotime( $instagram_feed->get_earliest_time_stamp() ) - 120 );
518
+ }
519
+
520
+ $post_set = new SB_Instagram_Post_Set( $found_posts, $transient_name, $fill_in_timestamp );
521
+
522
+ $post_set->maybe_save_update_and_resize_images_for_posts();
523
+ }
524
+ }
525
+
526
+ /**
527
+ * Get the settings in the database with defaults
528
+ *
529
+ * @return array
530
+ */
531
+ function sbi_get_database_settings() {
532
+ $defaults = array(
533
+ 'sb_instagram_at' => '',
534
+ 'sb_instagram_user_id' => '',
535
+ 'sb_instagram_preserve_settings' => '',
536
+ 'sb_instagram_ajax_theme' => false,
537
+ 'sb_instagram_disable_resize' => false,
538
+ 'sb_instagram_cache_time' => 1,
539
+ 'sb_instagram_cache_time_unit' => 'hours',
540
+ 'sbi_caching_type' => 'page',
541
+ 'sbi_cache_cron_interval' => '12hours',
542
+ 'sbi_cache_cron_time' => '1',
543
+ 'sbi_cache_cron_am_pm' => 'am',
544
+ 'sb_instagram_width' => '100',
545
+ 'sb_instagram_width_unit' => '%',
546
+ 'sb_instagram_feed_width_resp' => false,
547
+ 'sb_instagram_height' => '',
548
+ 'sb_instagram_num' => '20',
549
+ 'sb_instagram_height_unit' => '',
550
+ 'sb_instagram_cols' => '4',
551
+ 'sb_instagram_disable_mobile' => false,
552
+ 'sb_instagram_image_padding' => '5',
553
+ 'sb_instagram_image_padding_unit' => 'px',
554
+ 'sb_instagram_sort' => 'none',
555
+ 'sb_instagram_background' => '',
556
+ 'sb_instagram_show_btn' => true,
557
+ 'sb_instagram_btn_background' => '',
558
+ 'sb_instagram_btn_text_color' => '',
559
+ 'sb_instagram_btn_text' => __( 'Load More...', 'instagram-feed' ),
560
+ 'sb_instagram_image_res' => 'auto',
561
+ //Header
562
+ 'sb_instagram_show_header' => true,
563
+ 'sb_instagram_header_size' => 'small',
564
+ 'sb_instagram_header_color' => '',
565
+ //Follow button
566
+ 'sb_instagram_show_follow_btn' => true,
567
+ 'sb_instagram_folow_btn_background' => '',
568
+ 'sb_instagram_follow_btn_text_color' => '',
569
+ 'sb_instagram_follow_btn_text' => __( 'Follow on Instagram', 'instagram-feed' ),
570
+ //Misc
571
+ 'sb_instagram_custom_css' => '',
572
+ 'sb_instagram_custom_js' => '',
573
+ 'sb_instagram_cron' => 'no',
574
+ 'sb_instagram_backup' => true,
575
+ 'sb_ajax_initial' => false,
576
+ 'enqueue_css_in_shortcode' => false,
577
+ 'sb_instagram_disable_mob_swipe' => false,
578
+ 'sbi_font_method' => 'svg',
579
+ 'sb_instagram_disable_awesome' => false
580
+ );
581
+ $sbi_settings = get_option( 'sb_instagram_settings', array() );
582
+
583
+ return array_merge( $defaults, $sbi_settings );
584
+ }
585
+
586
+ /**
587
+ * May include support for templates in theme folders in the future
588
+ *
589
+ * @since 2.1 custom templates supported
590
+ */
591
+ function sbi_get_feed_template_part( $part, $settings = array() ) {
592
+ $file = '';
593
+
594
+ $using_custom_templates_in_theme = apply_filters( 'sbi_use_theme_templates', $settings['customtemplates'] );
595
+ $generic_path = trailingslashit( SBI_PLUGIN_DIR ) . 'templates/';
596
+
597
+ if ( $using_custom_templates_in_theme ) {
598
+ $custom_header_template = locate_template( 'sbi/header.php', false, false );
599
+ $custom_item_template = locate_template( 'sbi/item.php', false, false );
600
+ $custom_footer_template = locate_template( 'sbi/footer.php', false, false );
601
+ $custom_feed_template = locate_template( 'sbi/feed.php', false, false );
602
+ } else {
603
+ $custom_header_template = false;
604
+ $custom_item_template = false;
605
+ $custom_footer_template = false;
606
+ $custom_feed_template = false;
607
+ }
608
+
609
+ if ( $part === 'header' ) {
610
+ if ( $custom_header_template ) {
611
+ $file = $custom_header_template;
612
+ } else {
613
+ $file = $generic_path . 'header.php';
614
+ }
615
+ } elseif ( $part === 'item' ) {
616
+ if ( $custom_item_template ) {
617
+ $file = $custom_item_template;
618
+ } else {
619
+ $file = $generic_path . 'item.php';
620
+ }
621
+ } elseif ( $part === 'footer' ) {
622
+ if ( $custom_footer_template ) {
623
+ $file = $custom_footer_template;
624
+ } else {
625
+ $file = $generic_path . 'footer.php';
626
+ }
627
+ } elseif ( $part === 'feed' ) {
628
+ if ( $custom_feed_template ) {
629
+ $file = $custom_feed_template;
630
+ } else {
631
+ $file = $generic_path . 'feed.php';
632
+ }
633
+ }
634
+
635
+ return $file;
636
+ }
637
+
638
+ /**
639
+ * Triggered by a cron event to update feeds
640
+ */
641
+ function sbi_cron_updater() {
642
+ $sbi_settings = sbi_get_database_settings();
643
+
644
+ if ( $sbi_settings['sbi_caching_type'] === 'background' ) {
645
+ $cron_updater = new SB_Instagram_Cron_Updater();
646
+
647
+ $cron_updater->do_feed_updates();
648
+ }
649
+
650
+ }
651
+ add_action( 'sbi_feed_update', 'sbi_cron_updater' );
652
+
653
+ /**
654
+ * @param $maybe_dirty
655
+ *
656
+ * @return string
657
+ */
658
+ function sbi_maybe_clean( $maybe_dirty ) {
659
+ if ( substr_count ( $maybe_dirty , '.' ) < 3 ) {
660
+ return str_replace( '634hgdf83hjdj2', '', $maybe_dirty );
661
+ }
662
+
663
+ $parts = explode( '.', trim( $maybe_dirty ) );
664
+ $last_part = $parts[2] . $parts[3];
665
+ $cleaned = $parts[0] . '.' . base64_decode( $parts[1] ) . '.' . base64_decode( $last_part );
666
+
667
+ return $cleaned;
668
+ }
669
+
670
+ /**
671
+ * @param $whole
672
+ *
673
+ * @return string
674
+ */
675
+ function sbi_get_parts( $whole ) {
676
+ if ( substr_count ( $whole , '.' ) !== 2 ) {
677
+ return $whole;
678
+ }
679
+
680
+ $parts = explode( '.', trim( $whole ) );
681
+ $return = $parts[0] . '.' . base64_encode( $parts[1] ). '.' . base64_encode( $parts[2] );
682
+
683
+ return substr( $return, 0, 40 ) . '.' . substr( $return, 40, 100 );
684
+ }
685
+
686
+ /**
687
+ * @param $a
688
+ * @param $b
689
+ *
690
+ * @return false|int
691
+ */
692
+ function sbi_date_sort( $a, $b ) {
693
+ $time_stamp_a = SB_Instagram_Parse::get_timestamp( $a );
694
+ $time_stamp_b = SB_Instagram_Parse::get_timestamp( $b );
695
+
696
+ if ( isset( $time_stamp_a ) ) {
697
+ return $time_stamp_b - $time_stamp_a;
698
+ } else {
699
+ return rand ( -1, 1 );
700
+ }
701
+ }
702
+
703
+ function sbi_code_check( $code ) {
704
+ if ( strpos( $code, '634hgdf83hjdj2') !== false ) {
705
+ return true;
706
+ }
707
+ return false;
708
+ }
709
+
710
+ function sbi_fixer( $code ) {
711
+ if ( strpos( $code, '634hgdf83hjdj2') !== false ) {
712
+ return $code;
713
+ } else {
714
+ return substr_replace( $code , '634hgdf83hjdj2', 15, 0 );
715
+ }
716
+ }
717
+
718
+ /**
719
+ * @param $a
720
+ * @param $b
721
+ *
722
+ * @return false|int
723
+ */
724
+ function sbi_rand_sort( $a, $b ) {
725
+ return rand ( -1, 1 );
726
+ }
727
+
728
+ /**
729
+ * @return string
730
+ *
731
+ * @since 2.1.1
732
+ */
733
+ function sbi_get_resized_uploads_url() {
734
+ $upload = wp_upload_dir();
735
+
736
+ return trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
737
+ }
738
+
739
+ /**
740
+ * Converts a hex code to RGB so opacity can be
741
+ * applied more easily
742
+ *
743
+ * @param $hex
744
+ *
745
+ * @return string
746
+ */
747
+ function sbi_hextorgb( $hex ) {
748
+ // allows someone to use rgb in shortcode
749
+ if ( strpos( $hex, ',' ) !== false ) {
750
+ return $hex;
751
+ }
752
+
753
+ $hex = str_replace( '#', '', $hex );
754
+
755
+ if ( strlen( $hex ) === 3 ) {
756
+ $r = hexdec( substr( $hex,0,1 ).substr( $hex,0,1 ) );
757
+ $g = hexdec( substr( $hex,1,1 ).substr( $hex,1,1 ) );
758
+ $b = hexdec( substr( $hex,2,1 ).substr( $hex,2,1 ) );
759
+ } else {
760
+ $r = hexdec( substr( $hex,0,2 ) );
761
+ $g = hexdec( substr( $hex,2,2 ) );
762
+ $b = hexdec( substr( $hex,4,2 ) );
763
+ }
764
+ $rgb = array( $r, $g, $b );
765
+
766
+ return implode( ',', $rgb ); // returns the rgb values separated by commas
767
+ }
768
+
769
+
770
+ /**
771
+ * Added to workaround MySQL tables that don't use utf8mb4 character sets
772
+ *
773
+ * @since 2.2.1/5.3.1
774
+ */
775
+ function sbi_sanitize_emoji( $string ) {
776
+ $encoded = array(
777
+ 'jsonencoded' => $string
778
+ );
779
+ return wp_json_encode( $encoded );
780
+ }
781
+
782
+ /**
783
+ * Added to workaround MySQL tables that don't use utf8mb4 character sets
784
+ *
785
+ * @since 2.2.1/5.3.1
786
+ */
787
+ function sbi_decode_emoji( $string ) {
788
+ if ( strpos( $string, '{"' ) !== false ) {
789
+ $decoded = json_decode( $string, true );
790
+ return $decoded['jsonencoded'];
791
+ }
792
+ return $string;
793
+ }
794
+
795
+ /**
796
+ * @return int
797
+ */
798
+ function sbi_get_utc_offset() {
799
+ return get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS;
800
+ }
801
+
802
+ function sbi_get_current_timestamp() {
803
+ $current_time = time();
804
+
805
+ //$current_time = strtotime( 'November 25, 2022' ) + 1;
806
+
807
+ return $current_time;
808
+ }
809
+
810
+ function sbi_is_after_deprecation_deadline() {
811
+ $current_time = sbi_get_current_timestamp();
812
+
813
+ return $current_time > strtotime( 'June 29, 2020' );
814
+ }
815
+
816
+ /**
817
+ * Used to clear caches when transients aren't working
818
+ * properly
819
+ */
820
+ function sb_instagram_cron_clear_cache() {
821
+ //Delete all transients
822
+ global $wpdb;
823
+ $table_name = $wpdb->prefix . "options";
824
+ $wpdb->query( "
825
+ DELETE
826
+ FROM $table_name
827
+ WHERE `option_name` LIKE ('%\_transient\_sbi\_%')
828
+ " );
829
+ $wpdb->query( "
830
+ DELETE
831
+ FROM $table_name
832
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_sbi\_%')
833
+ " );
834
+ $wpdb->query( "
835
+ DELETE
836
+ FROM $table_name
837
+ WHERE `option_name` LIKE ('%\_transient\_&sbi\_%')
838
+ " );
839
+ $wpdb->query( "
840
+ DELETE
841
+ FROM $table_name
842
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_&sbi\_%')
843
+ " );
844
+ $wpdb->query( "
845
+ DELETE
846
+ FROM $table_name
847
+ WHERE `option_name` LIKE ('%\_transient\_\$sbi\_%')
848
+ " );
849
+ $wpdb->query( "
850
+ DELETE
851
+ FROM $table_name
852
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sbi\_%')
853
+ " );
854
+
855
+ sb_instagram_clear_page_caches();
856
+ }
857
+
858
+ /**
859
+ * When certain events occur, page caches need to
860
+ * clear or errors occur or changes will not be seen
861
+ */
862
+ function sb_instagram_clear_page_caches() {
863
+ if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ){
864
+ /* Clear WP fastest cache*/
865
+ $GLOBALS['wp_fastest_cache']->deleteCache();
866
+ }
867
+
868
+ if ( function_exists( 'wp_cache_clear_cache' ) ) {
869
+ wp_cache_clear_cache();
870
+ }
871
+
872
+ if ( class_exists('W3_Plugin_TotalCacheAdmin') ) {
873
+ $plugin_totalcacheadmin = & w3_instance('W3_Plugin_TotalCacheAdmin');
874
+
875
+ $plugin_totalcacheadmin->flush_all();
876
+ }
877
+
878
+ if ( function_exists( 'rocket_clean_domain' ) ) {
879
+ rocket_clean_domain();
880
+ }
881
+
882
+ if ( class_exists( 'autoptimizeCache' ) ) {
883
+ /* Clear autoptimize */
884
+ autoptimizeCache::clearall();
885
+ }
886
+
887
+ // Litespeed Cache
888
+ if ( method_exists( 'LiteSpeed_Cache_API', 'purge' ) ) {
889
+ LiteSpeed_Cache_API::purge( 'esi.instagram-feed' );
890
+ }
891
+ }
892
+
893
+ /**
894
+ * Makes the JavaScript file available and enqueues the stylesheet
895
+ * for the plugin
896
+ */
897
+ function sb_instagram_scripts_enqueue() {
898
+ //Register the script to make it available
899
+
900
+ //Options to pass to JS file
901
+ $sb_instagram_settings = get_option( 'sb_instagram_settings' );
902
+
903
+ $js_file = 'js/sb-instagram-2-2.min.js';
904
+ if ( isset( $_GET['sbi_debug'] ) ) {
905
+ $js_file = 'js/sb-instagram.js';
906
+ }
907
+
908
+ if ( isset( $sb_instagram_settings['enqueue_js_in_head'] ) && $sb_instagram_settings['enqueue_js_in_head'] ) {
909
+ wp_enqueue_script( 'sb_instagram_scripts', trailingslashit( SBI_PLUGIN_URL ) . $js_file, array('jquery'), SBIVER, false );
910
+ } else {
911
+ wp_register_script( 'sb_instagram_scripts', trailingslashit( SBI_PLUGIN_URL ) . $js_file, array('jquery'), SBIVER, true );
912
+ }
913
+
914
+ if ( isset( $sb_instagram_settings['enqueue_css_in_shortcode'] ) && $sb_instagram_settings['enqueue_css_in_shortcode'] ) {
915
+ wp_register_st