Instagram Widget by WPZOOM - Version 1.4.4

Version Description

  • New option to hide video thumbnails. Sometimes video thubmanils may show as blank squares, so the new option will help to fix this problem.
Download this release

Release Info

Developer WPZOOM
Plugin Icon 128x128 Instagram Widget by WPZOOM
Version 1.4.4
Comparing to
See all releases

Version 1.4.4

class-wpzoom-instagram-widget-api.php ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wpzoom_Instagram_Widget_API {
4
+ /**
5
+ * @var Wpzoom_Instagram_Widget_API The reference to *Singleton* instance of this class
6
+ */
7
+ private static $instance;
8
+
9
+ /**
10
+ * Instagram Access Token
11
+ *
12
+ * @var string
13
+ */
14
+ protected $access_token;
15
+
16
+ /**
17
+ * Returns the *Singleton* instance of this class.
18
+ *
19
+ * @return Wpzoom_Instagram_Widget_API The *Singleton* instance.
20
+ */
21
+ public static function getInstance()
22
+ {
23
+ if ( null === self::$instance ) {
24
+ self::$instance = new self();
25
+ }
26
+
27
+ return self::$instance;
28
+ }
29
+
30
+ protected function __construct() {
31
+ $options = get_option( 'wpzoom-instagram-widget-settings' );
32
+ $this->access_token = $options['access-token'];
33
+ $this->username = !empty($options['username']) ? $options['username'] : '';
34
+ $this->request_type = !empty($options['request_type']) ? $options['request_type'] : '';
35
+ $this->transient_lifetime_type = !empty($options['transient-lifetime-type']) ? $options['transient-lifetime-type'] : 'days';
36
+ $this->transient_lifetime_value = !empty($options['transient-lifetime-value']) ? $options['transient-lifetime-value'] : 1;
37
+
38
+ }
39
+
40
+ function get_transient_lifetime() {
41
+
42
+ $values = array( 'minutes' => MINUTE_IN_SECONDS, 'hours' => HOUR_IN_SECONDS, 'days' => DAY_IN_SECONDS );
43
+ $keys = array_keys( $values );
44
+ $type = in_array( $this->transient_lifetime_type, $keys ) ? $values[ $this->transient_lifetime_type ] : $values['minutes'];
45
+
46
+ return $type * $this->transient_lifetime_value;
47
+ }
48
+
49
+ function get_user_info_without_token( $user ) {
50
+
51
+ $response = $this->get_response_without_token( $user );
52
+
53
+ if ( empty( $response ) ) {
54
+ return new WP_Error( 'empty-json', __( 'Empty json decoded data.', 'wpzoom-instagram-widget' ) );
55
+ }
56
+
57
+ if ( isset( $response->entry_data->ProfilePage[0]->graphql->user ) ) {
58
+ $user_info = $response->entry_data->ProfilePage[0]->graphql->user;
59
+ } else {
60
+ return new WP_Error( 'empty-json', __( 'Empty json decoded data.', 'wpzoom-instagram-widget' ) );
61
+ }
62
+
63
+ $converted = new stdClass;
64
+
65
+ $converted->data = (object) array(
66
+ 'bio' => ! empty( $user_info->biography ) ? $user_info->biography : '',
67
+ 'counts' => (object) array(
68
+ 'followed_by' => ! empty( $user_info->edge_followed_by->count ) ? $user_info->edge_followed_by->count : 0,
69
+ 'follows' => ! empty( $user_info->edge_follow->count ) ? $user_info->edge_follow->count : 0,
70
+ 'media' => ! empty( $user_info->edge_owner_to_timeline_media->count ) ? $user_info->edge_owner_to_timeline_media->count : 0,
71
+ ),
72
+ 'full_name' => ! empty( $user_info->full_name ) ? $user_info->full_name : '',
73
+ 'id' => ! empty( $user_info->id ) ? $user_info->id : '',
74
+ 'is_business' => ! empty( $user_info->is_business_account ) ? $user_info->is_business_account : '',
75
+ 'profile_picture' => ! empty( $user_info->profile_pic_url ) ? $user_info->profile_pic_url : '',
76
+ 'username' => ! empty( $user_info->username ) ? $user_info->username : '',
77
+ 'website' => ! empty( $user_info->external_url ) ? $user_info->external_url : ''
78
+ );
79
+
80
+ return $converted;
81
+
82
+ }
83
+
84
+ function get_response_without_token( $user ) {
85
+
86
+ $user = trim( $user );
87
+ $url = $url = 'https://instagram.com/' . str_replace( '@', '', $user );
88
+
89
+ $request = wp_remote_get( $url );
90
+
91
+ if ( is_wp_error( $request ) || empty( $request ) ) {
92
+ return new WP_Error( 'invalid_response', __( 'Invalid response from Instagram', 'wpzoom-instagram-widget' ) );
93
+ }
94
+
95
+ $body = wp_remote_retrieve_body( $request );
96
+
97
+ $doc = new DOMDocument();
98
+
99
+ @$doc->loadHTML( $body );
100
+
101
+ $script_tags = $doc->getElementsByTagName( 'script' );
102
+
103
+ $json = '';
104
+
105
+ foreach ( $script_tags as $script_tag ) {
106
+ if ( strpos( $script_tag->nodeValue, 'window._sharedData = ' ) !== false ) {
107
+ $json = $script_tag->nodeValue;
108
+ break;
109
+ }
110
+ }
111
+
112
+ $json = str_replace( array( 'window._sharedData = ', '};' ), array( '', '}' ), $json );
113
+ $result = json_decode( $json );
114
+
115
+ if ( empty( $result ) ) {
116
+ return new WP_Error( 'empty-json', __( 'Empty json decoded data.', 'wpzoom-instagram-widget' ) );
117
+ }
118
+
119
+ return $result;
120
+ }
121
+
122
+ function get_items_without_token( $user ) {
123
+
124
+
125
+ $result = $this->get_response_without_token( $user );
126
+
127
+ if ( empty( $result ) ) {
128
+ return new WP_Error( 'empty-json', __( 'Empty json decoded data.', 'wpzoom-instagram-widget' ) );
129
+ }
130
+
131
+ if ( isset( $result->entry_data->ProfilePage[0]->graphql->user->edge_owner_to_timeline_media->edges ) ) {
132
+ $edges = $result->entry_data->ProfilePage[0]->graphql->user->edge_owner_to_timeline_media->edges;
133
+ } else {
134
+ return new WP_Error( 'empty-json', __( 'Empty json decoded data.', 'wpzoom-instagram-widget' ) );
135
+ }
136
+
137
+ $converted = new stdClass;
138
+ $converted->data = array();
139
+ foreach ( $edges as $edge ) {
140
+
141
+ $node = $edge->node;
142
+
143
+ $converted->data[] = (object) array(
144
+ 'user' => (object) array(
145
+ 'id' => $node->owner->id,
146
+ 'fullname' => '',
147
+ 'profile_picture' => '',
148
+ 'username' => $node->owner->username
149
+ ),
150
+ 'images' => (object) array(
151
+ 'thumbnail' => (object) array(
152
+ 'url' => $node->thumbnail_resources[0]->src,
153
+ 'width' => $node->thumbnail_resources[0]->config_width,
154
+ 'height' => $node->thumbnail_resources[0]->config_height
155
+ ),
156
+ 'low_resolution' => (object) array(
157
+ 'url' => $node->thumbnail_resources[2]->src,
158
+ 'width' => $node->thumbnail_resources[2]->config_width,
159
+ 'height' => $node->thumbnail_resources[2]->config_height
160
+ ),
161
+ 'standard_resolution' => (object) array(
162
+ 'url' => $node->thumbnail_resources[4]->src,
163
+ 'width' => $node->thumbnail_resources[4]->config_width,
164
+ 'height' => $node->thumbnail_resources[4]->config_height
165
+ ),
166
+ ),
167
+ 'type' => empty($node->is_video) ? 'image': 'video',
168
+ 'likes' => isset( $node->edge_liked_by ) ? $node->edge_liked_by : 0,
169
+ 'comments' => isset( $node->edge_media_to_comment ) ? $node->edge_media_to_comment : 0,
170
+ 'created_time' => $node->taken_at_timestamp,
171
+ 'link' => sprintf( 'https://www.instagram.com/p/%s/', $node->shortcode ),
172
+ 'caption' => (object) array(
173
+ 'text' => isset( $node->edge_media_to_caption->edges[0]->node->text ) ? $node->edge_media_to_caption->edges[0]->node->text : ''
174
+ )
175
+ );
176
+ }
177
+
178
+ return $converted;
179
+ }
180
+
181
+ /**
182
+ * @param $screen_name string Instagram username
183
+ * @param $image_limit int Number of images to retrieve
184
+ * @param $image_width int Desired image width to retrieve
185
+ *
186
+ * @return array|bool Array of tweets or false if method fails
187
+ */
188
+ public function get_items( $instance ) {
189
+
190
+ $sliced = wp_array_slice_assoc( $instance, array(
191
+ 'image-limit',
192
+ 'image-width',
193
+ 'image-resolution',
194
+ 'username',
195
+ 'disable-video-thumbs'
196
+ ) );
197
+
198
+ $image_limit = $sliced['image-limit'];
199
+ $image_width = $sliced['image-width'];
200
+ $image_resolution = ! empty( $sliced['image-resolution'] ) ? $sliced['image-resolution'] : 'default_algorithm';
201
+ $injected_username = ! empty( $sliced['username'] ) ? $sliced['username'] : '';
202
+ $disable_video_thumbs = ! empty( $sliced['disable-video-thumbs'] );
203
+
204
+ $transient = 'zoom_instagram_is_configured';
205
+
206
+ $injected_username = trim( $injected_username );
207
+
208
+ if ( ! empty( $injected_username ) ) {
209
+ $injected_username = str_replace( '@', '', $injected_username );
210
+ $transient = $transient . '_' . $injected_username;
211
+ }
212
+
213
+ if ( false !== ( $data = get_transient( $transient ) ) && is_object( $data ) && ! empty( $data->data ) ) {
214
+
215
+ return $this->processing_response_data( $data, $image_width, $image_resolution, $image_limit, $disable_video_thumbs );
216
+ }
217
+
218
+ $is_external_username = ! empty( $this->username ) || ! empty( $injected_username );
219
+ $external_username = ! empty( $injected_username ) ? $injected_username : $this->username;
220
+
221
+
222
+ if ( ! empty( $this->access_token ) ) {
223
+ $api_image_limit = 30;
224
+ $response = wp_remote_get( sprintf( 'https://api.instagram.com/v1/users/self/media/recent/?access_token=%s&count=%s', $this->access_token, $api_image_limit ) );
225
+
226
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
227
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
228
+
229
+ return false;
230
+ }
231
+
232
+ $data = json_decode( wp_remote_retrieve_body( $response ) );
233
+
234
+ $token_username = ! empty( $data->data[0]->user->username ) ? $data->data[0]->user->username : '';
235
+
236
+
237
+ if ( ! empty( $token_username ) && ! empty( $is_external_username ) ) {
238
+
239
+ if ( $external_username !== $token_username ) {
240
+
241
+ $data = $this->get_items_without_token( $external_username );
242
+
243
+ if ( is_wp_error( $data ) ) {
244
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
245
+
246
+ return false;
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ if ( empty( $this->access_token ) && ! empty( $is_external_username ) ) {
253
+
254
+
255
+ $data = $this->get_items_without_token( $external_username );
256
+
257
+ if ( is_wp_error( $data ) ) {
258
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
259
+
260
+ return false;
261
+ }
262
+
263
+ }
264
+
265
+ if ( ! empty( $data->data ) ) {
266
+ set_transient( $transient, $data, $this->get_transient_lifetime() );
267
+ } else {
268
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
269
+
270
+ return false;
271
+ }
272
+
273
+ return $this->processing_response_data( $data, $image_width, $image_resolution, $image_limit, $disable_video_thumbs );
274
+ }
275
+
276
+ public function processing_response_data( $data, $image_width, $image_resolution = 'default_algorithm', $image_limit, $disable_video_thumbs = false ) {
277
+
278
+ $result = array();
279
+ $username = '';
280
+
281
+ foreach ( $data->data as $key => $item ) {
282
+
283
+ if ( empty( $username ) ) {
284
+ $username = $item->user->username;
285
+ }
286
+
287
+ if ( $key === $image_limit ) {
288
+ break;
289
+ }
290
+
291
+ if ( ! empty( $disable_video_thumbs ) && isset( $item->type ) && 'video' == $item->type ) {
292
+ $image_limit++;
293
+ continue;
294
+
295
+ }
296
+
297
+ $result[] = array(
298
+ 'link' => $item->link,
299
+ 'image-url' => $item->images->{$this->get_best_size( $image_width, $image_resolution )}->url,
300
+ 'image-caption' => ! empty( $item->caption->text ) ? esc_attr( $item->caption->text ) : '',
301
+ 'likes_count' => ! empty( $item->likes->count ) ? esc_attr( $item->likes->count ) : 0,
302
+ 'comments_count' => ! empty( $item->comments->count ) ? esc_attr( $item->comments->count ) : 0
303
+ );
304
+ }
305
+
306
+ $result = array( 'items' => $result, 'username' => $username );
307
+
308
+ return $result;
309
+ }
310
+
311
+ public function get_user_info( $injected_username = '' ) {
312
+
313
+
314
+ $transient = 'zoom_instagram_user_info';
315
+
316
+ $injected_username = rtrim( $injected_username );
317
+
318
+ if ( ! empty( $injected_username ) ) {
319
+ $injected_username = str_replace( '@', '', $injected_username );
320
+ $transient = $transient . '_' . $injected_username;
321
+ }
322
+
323
+ if ( false !== ( $data = get_transient( $transient ) ) && is_object( $data ) && ! empty( $data->data ) ) {
324
+
325
+ return $data;
326
+ }
327
+
328
+ $is_external_username = ! empty( $this->username ) || ! empty( $injected_username );
329
+ $external_username = ! empty( $injected_username ) ? $injected_username : $this->username;
330
+
331
+ if ( ! empty( $this->access_token ) ) {
332
+
333
+ $response = wp_remote_get( sprintf( 'https://api.instagram.com/v1/users/self/?access_token=%s', $this->access_token ) );
334
+
335
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
336
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
337
+
338
+ return false;
339
+ }
340
+
341
+ $data = json_decode( wp_remote_retrieve_body( $response ) );
342
+
343
+ $token_username = ! empty( $data->data->username ) ? $data->data->username : '';
344
+
345
+ if ( ! empty( $token_username ) && ! empty( $is_external_username ) ) {
346
+
347
+ if ( $external_username !== $token_username ) {
348
+
349
+ $data = $this->get_user_info_without_token( $external_username );
350
+
351
+ if ( is_wp_error( $data ) ) {
352
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
353
+
354
+ return false;
355
+ }
356
+ }
357
+ }
358
+
359
+ }
360
+
361
+ if ( empty( $this->access_token ) && ! empty( $is_external_username ) ) {
362
+
363
+ $data = $this->get_user_info_without_token( $external_username );
364
+
365
+ if ( is_wp_error( $data ) ) {
366
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
367
+
368
+ return false;
369
+ }
370
+
371
+ }
372
+
373
+ if ( ! empty( $data->data ) ) {
374
+ set_transient( $transient, $data, $this->get_transient_lifetime() );
375
+ } else {
376
+ set_transient( $transient, false, MINUTE_IN_SECONDS );
377
+
378
+ return false;
379
+ }
380
+
381
+ return $data;
382
+
383
+ }
384
+
385
+ /**
386
+ * @param $screen_name string Instagram username
387
+ *
388
+ * @return bool|int Instagram user id or false on error
389
+ */
390
+ protected function get_user_id( $screen_name ) {
391
+ $user_id_option = 'zoom_instagram_uid_' . $screen_name;
392
+
393
+ if ( false !== ( $user_id = get_option( $user_id_option ) ) ) {
394
+ return $user_id;
395
+ }
396
+
397
+ $response = wp_remote_get( sprintf( 'https://api.instagram.com/v1/users/search?q=%s&access_token=%s', $screen_name, $this->access_token ) );
398
+
399
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
400
+ return false;
401
+ }
402
+
403
+ $result = json_decode( wp_remote_retrieve_body( $response ) );
404
+
405
+ if ( ! isset( $result->data ) ) {
406
+ return false;
407
+ }
408
+
409
+ $user_id = false;
410
+
411
+ foreach ( $result->data as $user ) {
412
+ if ( $user->username === $screen_name ) {
413
+ $user_id = $user->id;
414
+
415
+ break;
416
+ }
417
+ }
418
+
419
+ update_option( $user_id_option, $user_id );
420
+
421
+ return $user_id;
422
+ }
423
+
424
+ /**
425
+ * @param $desired_width int Desired image width in pixels
426
+ *
427
+ * @return string Image size for Instagram API
428
+ */
429
+ protected function get_best_size( $desired_width, $image_resolution = 'default_algorithm' ) {
430
+ $size = 'thumbnail';
431
+ $sizes = array(
432
+ 'thumbnail' => 150,
433
+ 'low_resolution' => 306,
434
+ 'standard_resolution' => 640
435
+ );
436
+
437
+ $diff = PHP_INT_MAX;
438
+
439
+ if ( array_key_exists( $image_resolution, $sizes ) ) {
440
+ return $image_resolution;
441
+ }
442
+
443
+ foreach ( $sizes as $key => $value ) {
444
+ if ( abs( $desired_width - $value ) < $diff ) {
445
+ $size = $key;
446
+ $diff = abs( $desired_width - $value );
447
+ }
448
+ }
449
+
450
+ return $size;
451
+ }
452
+
453
+ /**
454
+ * Check if given access token is valid for Instagram Api.
455
+ */
456
+ public static function is_access_token_valid( $access_token ) {
457
+ $response = wp_remote_get( sprintf( 'https://api.instagram.com/v1/users/self/?access_token=%s', $access_token ) );
458
+
459
+ if ( is_wp_error( $response ) ) {
460
+ return $response;
461
+ }
462
+
463
+ if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
464
+ return false;
465
+ }
466
+
467
+ return true;
468
+ }
469
+
470
+ public function is_configured() {
471
+ $transient = 'zoom_instagram_is_configured';
472
+
473
+ if ( false !== ( $result = get_transient( $transient ) ) ) {
474
+ if ( 'yes' === $result ) {
475
+ return true;
476
+ }
477
+
478
+ if ( 'no' === $result ) {
479
+ return false;
480
+ }
481
+ }
482
+
483
+ if(empty($this->username)){
484
+ $condition = $this->is_access_token_valid( $this->access_token );
485
+
486
+ } else{
487
+ $condition = true;
488
+ }
489
+
490
+
491
+ if ( true === $condition ) {
492
+ set_transient( $transient, 'yes', DAY_IN_SECONDS );
493
+
494
+ return true;
495
+ }
496
+
497
+ set_transient( $transient, 'no', DAY_IN_SECONDS );
498
+
499
+ return false;
500
+ }
501
+
502
+ public static function reset_cache() {
503
+ delete_transient( 'zoom_instagram_is_configured' );
504
+ delete_transient( 'zoom_instagram_user_info' );
505
+ }
506
+
507
+ public function get_access_token() {
508
+ return $this->access_token;
509
+ }
510
+
511
+ public function set_access_token( $access_token ) {
512
+ $this->access_token = $access_token;
513
+ }
514
+ }
class-wpzoom-instagram-widget-settings.php ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wpzoom_Instagram_Widget_Settings {
4
+ public function __construct() {
5
+ add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
6
+ add_action( 'admin_init', array( $this, 'settings_init' ) );
7
+
8
+ add_filter( 'plugin_action_links', array( $this, 'add_action_links' ), 10, 2 );
9
+
10
+ add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ),9 );
11
+ }
12
+
13
+ function add_action_links( $links, $file ) {
14
+ if ( $file != plugin_basename( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) ) {
15
+ return $links;
16
+ }
17
+
18
+ $settings_link = sprintf(
19
+ '<a href="%1$s">%2$s</a>',
20
+ menu_page_url( 'wpzoom-instagram-widget', false ),
21
+ esc_html__( 'Settings', 'wpzoom-instagram-widget' )
22
+ );
23
+
24
+ array_unshift( $links, $settings_link );
25
+
26
+ return $links;
27
+ }
28
+
29
+ public function add_admin_menu() {
30
+ add_options_page(
31
+ 'Instagram Widget',
32
+ 'Instagram Widget',
33
+ 'manage_options',
34
+ 'wpzoom-instagram-widget',
35
+ array( $this, 'settings_page' )
36
+ );
37
+ }
38
+
39
+ public function settings_init() {
40
+ register_setting(
41
+ 'wpzoom-instagram-widget-settings-group',
42
+ 'wpzoom-instagram-widget-settings',
43
+ array( $this, 'sanitize' )
44
+ );
45
+
46
+ add_settings_section(
47
+ 'wpzoom-instagram-widget-settings-general',
48
+ null,
49
+ '__return_false',
50
+ 'wpzoom-instagram-widget-settings-group'
51
+ );
52
+
53
+ add_settings_field(
54
+ 'wpzoom-instagram-widget-request-type',
55
+ __( 'Request Type', 'wpzoom-instagram-widget' ),
56
+ array( $this, 'settings_field_request_type' ),
57
+ 'wpzoom-instagram-widget-settings-group',
58
+ 'wpzoom-instagram-widget-settings-general',
59
+ array('class' => 'wpzoom-instagram-widget-with-token-group')
60
+ );
61
+
62
+ add_settings_field(
63
+ 'wpzoom-instagram-widget-access-token-button',
64
+ __( '', 'wpzoom-instagram-widget' ),
65
+ array( $this, 'settings_field_access_token_button' ),
66
+ 'wpzoom-instagram-widget-settings-group',
67
+ 'wpzoom-instagram-widget-settings-general',
68
+ array('class' => 'wpzoom-instagram-widget-with-access-token-group')
69
+
70
+ );
71
+
72
+ add_settings_field(
73
+ 'wpzoom-instagram-widget-access-token-input',
74
+ __( 'Access Token', 'wpzoom-instagram-widget' ),
75
+ array( $this, 'settings_field_access_token_input' ),
76
+ 'wpzoom-instagram-widget-settings-group',
77
+ 'wpzoom-instagram-widget-settings-general',
78
+ array('class' => 'wpzoom-instagram-widget-with-access-token-group')
79
+
80
+ );
81
+
82
+ add_settings_field(
83
+ 'wpzoom-instagram-widget-username-description',
84
+ __( '', 'wpzoom-instagram-widget' ),
85
+ array( $this, 'settings_field_username_description' ),
86
+ 'wpzoom-instagram-widget-settings-group',
87
+ 'wpzoom-instagram-widget-settings-general',
88
+ array('class' => 'wpzoom-instagram-widget-without-access-token-group')
89
+ );
90
+
91
+ add_settings_field(
92
+ 'wpzoom-instagram-widget-username',
93
+ __( 'Username', 'wpzoom-instagram-widget' ),
94
+ array( $this, 'settings_field_username' ),
95
+ 'wpzoom-instagram-widget-settings-group',
96
+ 'wpzoom-instagram-widget-settings-general',
97
+ array('class' => 'wpzoom-instagram-widget-without-access-token-group')
98
+
99
+ );
100
+
101
+ add_settings_field(
102
+ 'wpzoom-instagram-widget-transient-lifetime',
103
+ __( 'Check for new Instagram posts every', 'wpzoom-instagram-widget' ),
104
+ array( $this, 'settings_field_transient_lifetime' ),
105
+ 'wpzoom-instagram-widget-settings-group',
106
+ 'wpzoom-instagram-widget-settings-general'
107
+ );
108
+
109
+
110
+ }
111
+
112
+ public function settings_field_access_token_button() {
113
+ $oauth_url = 'https://instagram.com/oauth/authorize/?client_id=955bdb2319484968b93de8d6a1032c66&response_type=token&redirect_uri=https://www.wpzoom.com/instagram/';
114
+ $oauth_url .= '?auth_site=' . esc_url( admin_url( 'options-general.php?page=wpzoom-instagram-widget' ) );
115
+ $oauth_url.='&hl=en';
116
+ ?>
117
+
118
+ <p class="description"><?php _e( 'Using this method, you will be prompted to authorize the plugin to access your Instagram photos. The widget will automatically display the latest photos of the account which was authorized on this page.', 'wpzoom-instagram-widget' ); ?></p>
119
+
120
+ <br />
121
+
122
+ <a class="button button-connect" href="<?php echo esc_url( $oauth_url ); ?>">
123
+ <?php if ( ! Wpzoom_Instagram_Widget_API::getInstance()->is_configured() ) : ?>
124
+ <span><?php _e( 'Connect with Instagram', 'wpzoom-instagram-widget' ); ?></span>
125
+ <?php else: ?>
126
+ <span class="zoom-instagarm-widget-connected"><?php _e( 'Re-connect with Instagram', 'wpzoom-instagram-widget' ); ?></span>
127
+ <?php endif; ?>
128
+ </a>
129
+ </p>
130
+ <?php
131
+ }
132
+
133
+ public function settings_field_transient_lifetime() {
134
+ $settings = get_option( 'wpzoom-instagram-widget-settings' );
135
+ $lifetime_value = ! empty( $settings['transient-lifetime-value'] ) ? $settings['transient-lifetime-value'] : 1;
136
+ $lifetime_type = ! empty( $settings['transient-lifetime-type'] ) ? $settings['transient-lifetime-type'] : 'days';
137
+ ?>
138
+ <input class="regular-text code"
139
+ id="wpzoom-instagram-widget-settings_transient-lifetime-value"
140
+ name="wpzoom-instagram-widget-settings[transient-lifetime-value]"
141
+ value="<?php echo esc_attr( $lifetime_value ) ?>"
142
+ type="number"
143
+ min="1">
144
+
145
+ <select class="regular-text code"
146
+ id="wpzoom-instagram-widget-settings_transient-lifetime-type"
147
+ name="wpzoom-instagram-widget-settings[transient-lifetime-type]">
148
+ <option <?php selected( $lifetime_type, 'hours' ); ?> value="hours"><?php _e( 'Hours', 'wpzoom-instagram-widget' ) ?></option>
149
+ <option <?php selected( $lifetime_type, 'days' ); ?> value="days"><?php _e( 'Days', 'wpzoom-instagram-widget' ) ?></option>
150
+ <option <?php selected( $lifetime_type, 'minutes' ); ?> value="minutes"><?php _e( 'Minutes', 'wpzoom-instagram-widget' ) ?></option>
151
+ </select>
152
+ <?php
153
+ }
154
+
155
+ public function settings_field_access_token_input() {
156
+ $settings = get_option( 'wpzoom-instagram-widget-settings' );
157
+ ?>
158
+ <input class="regular-text code" id="wpzoom-instagram-widget-settings_access-token" name="wpzoom-instagram-widget-settings[access-token]" value="<?php echo esc_attr( $settings['access-token'] ) ?>" type="text">
159
+ <p class="description">
160
+ <?php
161
+ printf(
162
+ __(
163
+ 'The Instagram Access Token is a long string of characters unique to your account that grants other applications access to your Instagram feed. You can also get it manually from <a href="%1$s">here</a>.',
164
+ 'wpzoom-instagram-widget'
165
+ ),
166
+ 'https://www.wpzoom.com/instagram/'
167
+ );
168
+ ?>
169
+ </p>
170
+ <?php
171
+ }
172
+
173
+ public function settings_field_username_description() {
174
+ ?>
175
+ <p class="description"><?php _e( 'Using this method, a public feed, limited to <strong>12 photos</strong>, will be displayed in the widget.<br/>This option is useful if you want to display the feed of an Instagram account which you don\'t own or you have troubles getting your Access Token.', 'wpzoom-instagram-widget' ); ?></p>
176
+
177
+ </p>
178
+ <?php
179
+ }
180
+
181
+ public function settings_field_username() {
182
+ $settings = get_option( 'wpzoom-instagram-widget-settings' );
183
+ ?>
184
+ <input class="regular-text code" id="wpzoom-instagram-widget-settings_username" name="wpzoom-instagram-widget-settings[username]" value="<?php echo esc_attr( $settings['username'] ) ?>" type="text">
185
+ <p class="description">
186
+ <?php
187
+ printf(
188
+ __(
189
+ 'The username entered here will be used in the Instagram feed, unless a different username will be entered in the widget settings.',
190
+ 'wpzoom-instagram-widget'
191
+ )
192
+ );
193
+ ?>
194
+ </p>
195
+ <?php
196
+ }
197
+
198
+ public function settings_field_request_type() {
199
+ $settings = get_option( 'wpzoom-instagram-widget-settings' );
200
+ $request_type = empty( $settings['request-type'] ) ? 'with-access-token' : $settings['request-type'];
201
+ ?>
202
+
203
+ <div class="wpzoom-instagram-widget-settins-request-type-wrapper">
204
+ <p><label for="wpzoom-instagram-widget-settings_with-access-token"><input class="code" id="wpzoom-instagram-widget-settings_with-access-token"
205
+ name="wpzoom-instagram-widget-settings[request-type]"
206
+ value="with-access-token" <?php checked( $request_type, 'with-access-token' ) ?> type="radio"> <?php _e('With Access Token', 'wpzoom-instagram-widget')?>&nbsp;&nbsp;</label>
207
+ <label for="wpzoom-instagram-widget-settings_without-access-token"><input class="code" id="wpzoom-instagram-widget-settings_without-access-token"
208
+ name="wpzoom-instagram-widget-settings[request-type]" value="without-access-token"
209
+ <?php checked( $request_type, 'without-access-token' ) ?>type="radio"><?php _e('Public Feed (12 photos)', 'wpzoom-instagram-widget')?></label>
210
+ </p>
211
+ </div>
212
+
213
+ <?php
214
+ }
215
+
216
+ public function settings_page() {
217
+ ?>
218
+
219
+ <div class="wrap">
220
+
221
+ <h1><?php _e( 'Instagram Widget by WPZOOM', 'wpzoom-instagram-widget' ); ?></h1>
222
+
223
+ <div class="zoom-instagram-widget">
224
+
225
+ <h2><?php _e( 'Connect your account', 'wpzoom-instagram-widget' ); ?></h2>
226
+
227
+ <p><?php _e( 'To get started, select an option below. If you want to show your own feed, use the first option: <strong>With Access Token</strong>. If you want to show the feed of an Instagram account which you don\'t own, use the option <strong>Public Feed</strong>.', 'wpzoom-instagram-widget' ); ?></p>
228
+
229
+ <form action="options.php" method="post">
230
+
231
+ <?php
232
+ settings_fields( 'wpzoom-instagram-widget-settings-group' );
233
+ do_settings_sections( 'wpzoom-instagram-widget-settings-group' );
234
+ submit_button();
235
+ ?>
236
+
237
+ </form>
238
+
239
+ </div>
240
+
241
+ <div class="zoom-themes-link">
242
+
243
+ <h2><?php _e( 'Premium WordPress Themes by WPZOOM', 'wpzoom-instagram-widget' ); ?></h2>
244
+
245
+ <p><?php _e( 'Are you looking to give your website a new look?<br/> Check out our collection of <strong>40 expertly-crafted themes</strong> and find the perfect one for your needs!', 'wpzoom-instagram-widget' ); ?></p>
246
+
247
+ <p><?php printf( __( '<a class="cta-button" target="_blank" href="%1$s"">View our Themes &rarr;</a>' ), 'https://www.wpzoom.com/themes/' ); ?></p>
248
+
249
+ </div>
250
+
251
+ </div>
252
+
253
+ <?php
254
+ }
255
+
256
+ public function scripts( $hook ) {
257
+ if ( $hook != 'settings_page_wpzoom-instagram-widget' ) {
258
+ return;
259
+ }
260
+
261
+ wp_enqueue_style( 'zoom-instagram-widget-admin', plugin_dir_url( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) . 'css/admin-instagram-widget.css', array(), '1.4.2' );
262
+ wp_enqueue_script( 'zoom-instagram-widget-admin', plugin_dir_url( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) . 'js/admin-instagram-widget.js', array( 'jquery' ), '1.4.2' );
263
+ wp_localize_script( 'zoom-instagram-widget-admin', 'zoom_instagram_widget_admin', array(
264
+ 'i18n_connect_confirm' => __( "Instagram Widget is already connected to Instagram.\r\n\r\nDo you want to connect again?", 'wpzoom-instagram-widget' ),
265
+ ) );
266
+ }
267
+
268
+ public function sanitize( $input ) {
269
+ $result = array();
270
+
271
+ $result['access-token'] = sanitize_text_field( $input['access-token'] );
272
+
273
+ if ( ! empty( $result['access-token'] ) ) {
274
+ $validation_result = Wpzoom_Instagram_Widget_API::is_access_token_valid( $result['access-token'] );
275
+
276
+ if ( $validation_result !== true ) {
277
+ $access_token_error_message = __( 'Provided Access Token has been rejected by Instagram API. Please try again or use the other option.', 'wpzoom-instagram-widget' );
278
+
279
+ if ( is_wp_error( $validation_result ) ) {
280
+ $access_token_error_message = $validation_result->get_error_message();
281
+ }
282
+
283
+ if ( $validation_result !== true ) {
284
+ add_settings_error(
285
+ 'wpzoom-instagram-widget-access-token',
286
+ esc_attr( 'wpzoom-instagram-widget-access-token-invalid' ),
287
+ $access_token_error_message,
288
+ 'error'
289
+ );
290
+ }
291
+
292
+ $result['access-token'] = '';
293
+ }
294
+ }
295
+
296
+ $result['username'] = sanitize_text_field( $input['username'] );
297
+ $result['request-type'] = sanitize_text_field( $input['request-type'] );
298
+ $result['transient-lifetime-value'] = sanitize_text_field( $input['transient-lifetime-value'] );
299
+ $result['transient-lifetime-type'] = sanitize_text_field( $input['transient-lifetime-type'] );
300
+
301
+ Wpzoom_Instagram_Widget_API::reset_cache();
302
+
303
+ return $result;
304
+ }
305
+ }
306
+
307
+ new Wpzoom_Instagram_Widget_Settings();
class-wpzoom-instagram-widget.php ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wpzoom_Instagram_Widget extends WP_Widget {
4
+ /**
5
+ * @var Wpzoom_Instagram_Widget_API
6
+ */
7
+ protected $api;
8
+
9
+ /**
10
+ * @var array Default widget settings.
11
+ */
12
+ protected $defaults;
13
+
14
+ public function __construct() {
15
+ parent::__construct(
16
+ 'wpzoom_instagram_widget',
17
+ esc_html__( 'Instagram Widget by WPZOOM', 'wpzoom-instagram-widget' ),
18
+ array(
19
+ 'classname' => 'zoom-instagram-widget',
20
+ 'description' => __( 'Displays a user\'s Instagram timeline.', 'wpzoom-instagram-widget' ),
21
+ )
22
+ );
23
+
24
+ $this->defaults = array(
25
+ 'title' => esc_html__( 'Instagram', 'wpzoom-instagram-widget' ),
26
+ 'button_text' => esc_html__( 'View on Instagram', 'wpzoom-instagram-widget' ),
27
+ 'image-limit' => 9,
28
+ 'show-view-on-instagram-button' => true,
29
+ 'show-counts-on-hover' => false,
30
+ 'show-user-info' => false,
31
+ 'show-user-bio' => false,
32
+ 'lazy-load-images' => false,
33
+ 'disable-video-thumbs' => false,
34
+ 'images-per-row' => 3,
35
+ 'image-width' => 120,
36
+ 'image-spacing' => 10,
37
+ 'image-resolution' => 'default_algorithm',
38
+ 'username' => '',
39
+ );
40
+
41
+ $this->api = Wpzoom_Instagram_Widget_API::getInstance();
42
+
43
+ add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
44
+ }
45
+
46
+ /**
47
+ * Widget specific scripts & styles
48
+ */
49
+ public function scripts() {
50
+ wp_enqueue_style( 'zoom-instagram-widget', plugin_dir_url( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) . 'css/instagram-widget.css', array('dashicons'), '1.4.2' );
51
+ wp_enqueue_script( 'zoom-instagram-widget-lazy-load', plugin_dir_url( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) . 'js/jquery.lazy.min.js', array( 'jquery' ), '1.4.2' );
52
+ wp_enqueue_script( 'zoom-instagram-widget', plugin_dir_url( dirname( __FILE__ ) . '/instagram-widget-by-wpzoom.php' ) . 'js/instagram-widget.js', array( 'jquery' ), '1.4.2' );
53
+ }
54
+
55
+ /**
56
+ * Front-end display of widget.
57
+ *
58
+ * @see WP_Widget::widget()
59
+ *
60
+ * @param array $args Widget arguments.
61
+ * @param array $instance Saved values from database.
62
+ */
63
+ public function widget( $args, $instance ) {
64
+ $instance = wp_parse_args( (array) $instance, $this->defaults );
65
+
66
+ echo $args['before_widget'];
67
+
68
+ if ( $instance['title'] ) {
69
+ echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
70
+ }
71
+
72
+
73
+ $items = $this->api->get_items( $instance );
74
+
75
+ if ( ! is_array( $items ) ) {
76
+ $this->display_errors();
77
+ } else {
78
+
79
+ if ( ! empty( $instance['show-user-info'] ) ) {
80
+ $user_info = $this->api->get_user_info($instance['username']);
81
+
82
+ if (
83
+ is_object( $user_info ) &&
84
+ ! empty( $user_info ) &&
85
+ ! empty( $user_info->data )
86
+ ) {
87
+ $this->display_user_info( $instance, $user_info );
88
+ }
89
+ }
90
+
91
+ $this->display_items( $items['items'], $instance );
92
+ $this->display_instagram_button( $instance, $items['username'] );
93
+ }
94
+
95
+
96
+ echo $args['after_widget'];
97
+ }
98
+
99
+ /**
100
+ * Sanitize widget form values as they are saved.
101
+ *
102
+ * @see WP_Widget::update()
103
+ *
104
+ * @param array $new_instance Values just sent to be saved.
105
+ * @param array $old_instance Previously saved values from database.
106
+ *
107
+ * @return array Updated safe values to be saved.
108
+ */
109
+ public function update( $new_instance, $old_instance ) {
110
+ $instance['title'] = sanitize_text_field( $new_instance['title'] );
111
+ $instance['button_text'] = sanitize_text_field( $new_instance['button_text'] );
112
+
113
+ $instance['image-limit'] = ( 0 !== (int) $new_instance['image-limit'] ) ? (int) $new_instance['image-limit'] : null;
114
+
115
+ $instance['images-per-row'] = ( 0 !== (int) $new_instance['images-per-row'] ) ? (int) $new_instance['images-per-row'] : null;
116
+ $instance['image-width'] = ( 0 !== (int) $new_instance['image-width'] ) ? (int) $new_instance['image-width'] : null;
117
+ $instance['image-spacing'] = ( 0 <= (int) $new_instance['image-spacing'] ) ? (int) $new_instance['image-spacing'] : null;
118
+ $instance['image-resolution'] = !empty($new_instance['image-resolution']) ? $new_instance['image-resolution'] : $this->defaults['image-resolution'];
119
+ $instance['username'] = !empty($new_instance['username']) ? $new_instance['username'] : $this->defaults['username'];
120
+
121
+ $instance['show-view-on-instagram-button'] = ! empty( $new_instance['show-view-on-instagram-button'] );
122
+ $instance['show-counts-on-hover'] = ! empty( $new_instance['show-counts-on-hover'] );
123
+ $instance['show-user-info'] = ! empty( $new_instance['show-user-info'] );
124
+ $instance['show-user-bio'] = ! empty( $new_instance['show-user-bio'] );
125
+ $instance['lazy-load-images'] = ! empty( $new_instance['lazy-load-images'] );
126
+ $instance['disable-video-thumbs'] = ! empty( $new_instance['disable-video-thumbs'] );
127
+
128
+
129
+ return $instance;
130
+ }
131
+
132
+ /**
133
+ * Back-end widget form.
134
+ *
135
+ * @see WP_Widget::form()
136
+ *
137
+ * @param array $instance Previously saved values from database.
138
+ *
139
+ * @return string|void
140
+ */
141
+ public function form( $instance ) {
142
+ $instance = wp_parse_args( (array) $instance, $this->defaults );
143
+ ?>
144
+
145
+ <?php if ( empty($instance['username']) && ! $this->api->is_configured() ) : ?>
146
+
147
+ <p style="color: #d54e21">
148
+ <?php
149
+ printf( __( 'You need to configure <a href="%1$s">plugin settings</a> before using this widget.', 'wpzoom-instagram-widget' ),
150
+ menu_page_url( 'wpzoom-instagram-widget', false ) );
151
+ ?>
152
+ </p>
153
+
154
+ <?php endif; ?>
155
+
156
+ <p>
157
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'wpzoom-instagram-widget' ); ?></label>
158
+ <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
159
+ </p>
160
+
161
+
162
+ <p>
163
+ <label for="<?php echo $this->get_field_id( 'image-limit' ); ?>"><?php esc_html_e( 'Number of Images Shown:', 'wpzoom-instagram-widget' ); ?></label>
164
+ <input class="widefat" id="<?php echo $this->get_field_id( 'image-limit' ); ?>" name="<?php echo $this->get_field_name( 'image-limit' ); ?>" type="number" min="1" max="30" value="<?php echo esc_attr( $instance['image-limit'] ); ?>"/>
165
+ </p>
166
+
167
+ <p>
168
+ <label for="<?php echo $this->get_field_id( 'images-per-row' ); ?>"><?php esc_html_e( 'Desired number of Images per row:', 'wpzoom-instagram-widget' ); ?></label>
169
+ <input class="widefat" id="<?php echo $this->get_field_id( 'images-per-row' ); ?>" name="<?php echo $this->get_field_name( 'images-per-row' ); ?>" type="number" min="1" max="20" value="<?php echo esc_attr( $instance['images-per-row'] ); ?>"/>
170
+ </p>
171
+
172
+ <p>
173
+ <label for="<?php echo $this->get_field_id( 'image-width' ); ?>"><?php esc_html_e( 'Desired Image width in pixels:', 'wpzoom-instagram-widget' ); ?> <small>(Just integer)</small></label>
174
+ <input class="widefat" id="<?php echo $this->get_field_id( 'image-width' ); ?>" name="<?php echo $this->get_field_name( 'image-width' ); ?>" type="number" min="20" value="<?php echo esc_attr( $instance['image-width'] ); ?>"/>
175
+ </p>
176
+
177
+ <p>
178
+ <label for="<?php echo $this->get_field_id( 'image-spacing' ); ?>"><?php esc_html_e( 'Image spacing in pixels:', 'wpzoom-instagram-widget' ); ?> <small>(Just integer)</small></label>
179
+ <input class="widefat" id="<?php echo $this->get_field_id( 'image-spacing' ); ?>" name="<?php echo $this->get_field_name( 'image-spacing' ); ?>" type="number" min="0" max="50" value="<?php echo esc_attr( $instance['image-spacing'] ); ?>"/>
180
+ </p>
181
+
182
+ <p class="description">
183
+ <?php
184
+ echo wp_kses_post(
185
+ __( 'Fields above do not influence directly widget appearance. Final number of images per row and image width is calculated depending on browser resolution. This ensures your photos look beautiful on all devices.', 'wpzoom-instagram-widget' )
186
+ );
187
+ ?>
188
+ </p>
189
+
190
+ <p>
191
+ <label for="<?php echo $this->get_field_id( 'username' ); ?>"><strong><?php esc_html_e( 'Instagram @username:', 'wpzoom-instagram-widget' ); ?></strong></label>
192
+ <input class="widefat" id="<?php echo $this->get_field_id( 'username' ); ?>" name="<?php echo $this->get_field_name( 'username' ); ?>" type="text" value="<?php echo esc_attr( $instance['username'] ); ?>"/>
193
+ </p>
194
+
195
+ <p class="description">
196
+
197
+ <?php
198
+ printf( __( 'If you have already connected your Instagram account in the <a href="%1$s">plugin settings</a>, leave this field empty. You can use this option if you want to display the feed of a different Instagram account.', 'wpzoom-instagram-widget' ),
199
+ menu_page_url( 'wpzoom-instagram-widget', false ) );
200
+ ?>
201
+
202
+ </p>
203
+
204
+ <p>
205
+ <label for="<?php echo $this->get_field_id( 'image-resolution' ); ?>"><?php esc_html_e( 'Set forced image resolution:', 'wpzoom-instagram-widget' ); ?></label>
206
+ <select class="widefat" id="<?php echo $this->get_field_id( 'image-resolution' ); ?>" name="<?php echo $this->get_field_name( 'image-resolution' ); ?>">
207
+ <option value="default_algorithm" <?php selected( $instance['image-resolution'], "default_algorithm" ); ?>>
208
+ <?php _e('By Default Algorithm', 'wpzoom-instagram-widget' ); ?>
209
+ </option>
210
+ <option value="thumbnail" <?php selected( $instance['image-resolution'], "thumbnail" ); ?>>
211
+ <?php _e('Thumbnail ( 150x150px )', 'wpzoom-instagram-widget' ); ?>
212
+ </option>
213
+ <option value="low_resolution" <?php selected( $instance['image-resolution'], "low_resolution" ); ?>>
214
+ <?php _e('Low Resolution ( 320x320px )', 'wpzoom-instagram-widget' ); ?>
215
+
216
+ </option>
217
+ <option value="standard_resolution" <?php selected( $instance['image-resolution'], "standard_resolution" ); ?>>
218
+ <?php _e('Standard Resolution ( 640x640px )', 'wpzoom-instagram-widget' ); ?>
219
+ </option>
220
+ </select>
221
+ </p>
222
+ <p>
223
+ <input class="checkbox" type="checkbox" <?php checked( $instance['show-user-info'] ); ?> id="<?php echo $this->get_field_id( 'show-user-info' ); ?>" name="<?php echo $this->get_field_name( 'show-user-info' ); ?>" />
224
+ <label for="<?php echo $this->get_field_id( 'show-user-info' ); ?>"><?php _e(' Display <strong>User Details</strong>', 'wpzoom-instagram-widget' ); ?></label>
225
+ </p>
226
+
227
+ <p>
228
+ <input class="checkbox" type="checkbox" <?php checked( $instance['show-user-bio'] ); ?> id="<?php echo $this->get_field_id( 'show-user-bio' ); ?>" name="<?php echo $this->get_field_name( 'show-user-bio' ); ?>" />
229
+ <label for="<?php echo $this->get_field_id( 'show-user-bio' ); ?>"><?php _e(' Display <strong>Bio in User Details</strong>', 'wpzoom-instagram-widget' ); ?></label>
230
+ </p>
231
+
232
+ <p>
233
+ <input class="checkbox" type="checkbox" <?php checked( $instance['show-view-on-instagram-button'] ); ?> id="<?php echo $this->get_field_id( 'show-view-on-instagram-button' ); ?>" name="<?php echo $this->get_field_name( 'show-view-on-instagram-button' ); ?>" />
234
+ <label for="<?php echo $this->get_field_id( 'show-view-on-instagram-button' ); ?>"><?php _e(' Display <strong>View on Instagram</strong> button', 'wpzoom-instagram-widget' ); ?></label>
235
+ </p>
236
+
237
+ <p>
238
+ <input class="checkbox" type="checkbox" <?php checked( $instance['show-counts-on-hover'] ); ?> id="<?php echo $this->get_field_id( 'show-counts-on-hover' ); ?>" name="<?php echo $this->get_field_name( 'show-counts-on-hover' ); ?>" />
239
+ <label for="<?php echo $this->get_field_id( 'show-counts-on-hover' ); ?>"><?php _e(' Show <strong>overlay with number of comments and likes</strong> on hover', 'wpzoom-instagram-widget' ); ?></label>
240
+ </p>
241
+
242
+ <p>
243
+ <input class="checkbox" type="checkbox" <?php checked( $instance['lazy-load-images'] ); ?> id="<?php echo $this->get_field_id( 'lazy-load-images' ); ?>" name="<?php echo $this->get_field_name( 'lazy-load-images' ); ?>" />
244
+ <label for="<?php echo $this->get_field_id( 'lazy-load-images' ); ?>"><?php _e('Lazy Load <strong>images</strong>', 'wpzoom-instagram-widget' ); ?></label>
245
+ </p>
246
+ <p>
247
+ <input class="checkbox" type="checkbox" <?php checked( $instance['disable-video-thumbs'] ); ?> id="<?php echo $this->get_field_id( 'disable-video-thumbs' ); ?>" name="<?php echo $this->get_field_name( 'disable-video-thumbs' ); ?>" />
248
+ <label for="<?php echo $this->get_field_id( 'disable-video-thumbs' ); ?>"><?php _e('Hide video <strong>thumbnails</strong>', 'wpzoom-instagram-widget' ); ?></label>
249
+ </p>
250
+ <p>
251
+ <label for="<?php echo $this->get_field_id( 'button_text' ); ?>"><?php esc_html_e( 'Button Text:', 'wpzoom-instagram-widget' ); ?></label>
252
+ <input class="widefat" id="<?php echo $this->get_field_id( 'button_text' ); ?>" name="<?php echo $this->get_field_name( 'button_text' ); ?>" type="text" value="<?php echo esc_attr( $instance['button_text'] ); ?>"/>
253
+ </p>
254
+
255
+
256
+
257
+ <?php
258
+ }
259
+
260
+ protected function display_items( $items, $instance ) {
261
+ $count = 0;
262
+ $show_overlay = wp_validate_boolean($instance['show-counts-on-hover']);
263
+ $small_class = (!empty($instance['image-width']) && $instance['image-width'] <= 180) ? 'small' : '';
264
+ ?>
265
+ <ul class="zoom-instagram-widget__items zoom-instagram-widget__items--no-js"
266
+ data-images-per-row="<?php echo esc_attr( $instance['images-per-row'] ); ?>"
267
+ data-image-width="<?php echo esc_attr( $instance['image-width'] ); ?>"
268
+ data-image-spacing="<?php echo esc_attr( $instance['image-spacing'] ); ?>"
269
+ data-image-lazy-loading="<?php echo esc_attr( $instance['lazy-load-images'] ); ?>">
270
+
271
+ <?php foreach ( $items as $item ) : ?>
272
+ <?php
273
+ $link = $item['link'];
274
+ $src = $item['image-url'];
275
+ $alt = esc_attr($item['image-caption']);
276
+ $likes = $item['likes_count'];
277
+ $comments = $item['comments_count'];
278
+ ?>
279
+
280
+ <li class="zoom-instagram-widget__item">
281
+
282
+ <?php
283
+ $inline_style = 'width:'.esc_attr( $instance['image-width']).'px;';
284
+ $inline_style .= 'height:'.esc_attr( $instance['image-width']).'px;';
285
+ if(empty( $instance['lazy-load-images'] )){
286
+ $inline_style.= "background-image: url('".$src."');";
287
+ }
288
+
289
+ if($show_overlay):?>
290
+ <div class='hover-layout zoom-instagram-widget__overlay zoom-instagram-widget__black <?php echo $small_class?>'>
291
+
292
+ <div class='hover-controls'>
293
+ <span class="dashicons dashicons-heart"></span>
294
+ <span class="counter"><?php echo $this->format_number($likes); ?></span>
295
+ <span class="dashicons dashicons-format-chat"></span>
296
+ <span class="counter"><?php echo $this->format_number($comments); ?></span>
297
+ </div>
298
+ <div class='zoom-instagram-icon-wrap'>
299
+ <a class="zoom-svg-instagram-stroke" href="<?php echo $link; ?>" rel="noopener" target="_blank" title="<?php echo $alt; ?>"></a>
300
+ </div>
301
+
302
+
303
+ <a class='zoom-instagram-link' data-src="<?php echo $src; ?>" style="<?php echo $inline_style; ?>"
304
+ href="<?php echo $link; ?>" target="_blank" rel="noopener" title="<?php echo $alt; ?>"
305
+ >
306
+ </a>
307
+ </div>
308
+ <?php else: ?>
309
+ <a class='zoom-instagram-link' data-src="<?php echo $src; ?>" style="<?php echo $inline_style; ?>"
310
+ href="<?php echo $link; ?>" target="_blank" rel="noopener" title="<?php echo $alt; ?>"
311
+ >
312
+ </a>
313
+ <?php endif; ?>
314
+ </li>
315
+
316
+ <?php if ( ++$count === $instance['image-limit'] ) break; ?>
317
+
318
+ <?php endforeach; ?>
319
+
320
+ </ul>
321
+
322
+ <div style="clear:both;"></div>
323
+ <?php
324
+ }
325
+
326
+
327
+ protected function display_user_info( $instance, $user_info ) {
328
+ ?>
329
+ <div class="zoom-instagram-widget-user-info">
330
+ <?php if ( ! empty( $user_info->data->profile_picture ) ): ?>
331
+ <div class="zoom-instagram-widget-user-info-picture">
332
+ <a target="_blank" rel="noopener" href="<?php printf( 'http://instagram.com/%s?ref=badge', esc_attr( $user_info->data->username ) ); ?>"><img width="90" src="<?php echo $user_info->data->profile_picture ?>" alt="<?php echo esc_attr( $user_info->data->full_name ) ?>"/></a>
333
+ </div>
334
+ <?php endif; ?>
335
+ <div class="zoom-instagram-widget-user-info-meta">
336
+ <div class="zoom-instagram-widget-user-info-about-data">
337
+ <div class="zoom-instagram-widget-user-info-names-wrapper">
338
+ <?php if ( ! empty( $user_info->data->full_name ) ): ?>
339
+ <div class="zoom-instagram-widget-user-info-fullname">
340
+ <?php esc_html_e( $user_info->data->full_name ) ?>
341
+ </div>
342
+ <?php endif; ?>
343
+ <?php if ( ! empty( $user_info->data->username ) ): ?>
344
+ <div class="zoom-instagram-widget-user-info-username">
345
+ <?php esc_html_e( '@' . $user_info->data->username ) ?>
346
+ </div>
347
+ <?php endif; ?>
348
+ </div>
349
+ <div>
350
+ <a class="zoom-instagram-widget-user-info-follow-button" target="_blank" rel="noopener" href="<?php printf( 'http://instagram.com/%s?ref=badge', esc_attr( $user_info->data->username ) ); ?>">
351
+ <?php _e( 'Follow', 'wpzoom-instagram-widget' ) ?>
352
+ </a>
353
+ </div>
354
+ </div>
355
+ <div class="zoom-instagram-widget-user-info-stats">
356
+ <?php if ( ! empty( $user_info->data->counts->media ) ): ?>
357
+ <div>
358
+ <div class="zoom-instagram-widget-user-info-counts"
359
+ title="<?php echo number_format($user_info->data->counts->media)?>">
360
+ <?php echo $this->format_number($user_info->data->counts->media); ?>
361
+ </div>
362
+ <div class="zoom-instagram-widget-user-info-counts-subhead">
363
+ <?php _e( 'posts', 'wpzoom-instagram-widget' ); ?>
364
+ </div>
365
+ </div>
366
+ <?php endif; ?>
367
+ <?php if ( ! empty( $user_info->data->counts->followed_by ) ): ?>
368
+ <div class="zoom-instagram-widget-user-info-middle-cell">
369
+ <div class="zoom-instagram-widget-user-info-counts"
370
+ title="<?php echo number_format($user_info->data->counts->followed_by)?>">
371
+ <?php echo $this->format_number($user_info->data->counts->followed_by); ?>
372
+ </div>
373
+ <div class="zoom-instagram-widget-user-info-counts-subhead">
374
+ <?php _e( 'followers', 'wpzoom-instagram-widget' ); ?>
375
+ </div>
376
+ </div>
377
+ <?php endif; ?>
378
+ <?php if ( ! empty( $user_info->data->counts->follows ) ): ?>
379
+ <div>
380
+ <div class="zoom-instagram-widget-user-info-counts"
381
+ title="<?php echo number_format($user_info->data->counts->follows)?>">
382
+ <?php echo $this->format_number($user_info->data->counts->follows); ?>
383
+ </div>
384
+ <div class="zoom-instagram-widget-user-info-counts-subhead">
385
+ <?php _e( 'following', 'wpzoom-instagram-widget' ); ?>
386
+ </div>
387
+ </div>
388
+ <?php endif; ?>
389
+ </div>
390
+ </div>
391
+
392
+ </div>
393
+ <?php
394
+ if ( ! empty( $instance['show-user-bio'] ) ) {
395
+
396
+ if ( ! empty( $user_info->data->bio ) ): ?>
397
+ <div class="zoom-instagram-widget-user-info-bio"><?php echo nl2br( $user_info->data->bio ) ?></div>
398
+ <?php endif;
399
+
400
+ } ?>
401
+
402
+ <?php
403
+ }
404
+
405
+ public function format_number( $num ) {
406
+
407
+ if ( $num < 10000 ) {
408
+ return number_format( $num );
409
+ }
410
+
411
+ $units = array( '', 'k', 'm', 'b', 't' );
412
+ for ( $i = 0; $num >= 1000; $i ++ ) {
413
+ $num /= 1000;
414
+ }
415
+
416
+ return round( $num, 1 ) . $units[ $i ];
417
+ }
418
+
419
+ protected function display_instagram_button( $instance, $username) {
420
+ $show_view_on_instagram_button = $instance['show-view-on-instagram-button'];
421
+
422
+ if ( ! $show_view_on_instagram_button ) {
423
+ return;
424
+ }
425
+
426
+ ?>
427
+ <div class="zoom-instagram-widget__follow-me">
428
+ <a href="<?php printf( 'http://instagram.com/%s?ref=badge', esc_attr( $username ) ); ?>" class="ig-b- ig-b-v-24" rel="noopener" target="_blank"><?php echo esc_attr( $instance['button_text'] ); ?></a>
429
+ </div>
430
+ <?php
431
+ }
432
+
433
+ /**
434
+ * Output errors if widget is misconfigured and current user can manage options (plugin settings).
435
+ *
436
+ * @return void
437
+ */
438
+ protected function display_errors() {
439
+ if ( current_user_can( 'edit_theme_options' ) ) {
440
+ ?>
441
+ <p>
442
+ <?php _e( 'Instagram Widget misconfigured, check plugin &amp; widget settings.', 'wpzoom-instagram-widget' ); ?>
443
+ </p>
444
+ <?php
445
+ } else {
446
+ echo "&#8230;";
447
+ }
448
+ }
449
+ }
css/admin-instagram-widget.css ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .zoom-instagram-widget .button-connect {
2
+ /*height: auto;*/
3
+ /*padding: 9px 12px;*/
4
+ color: #fff;
5
+ border: 1px solid #1c5380;
6
+ border-radius: 3px;
7
+ background-color: #6f97b6;
8
+ background-image: -webkit-linear-gradient(top, #6f97b6, #3f729b);
9
+ background-image: linear-gradient(to bottom, #6f97b6, #3f729b);
10
+ background-position: 50% 50%;
11
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1), inset 1px 0 0 rgba(255, 255, 255, 0.05), inset -1px 0 0 rgba(255, 255, 255, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.2);
12
+ text-shadow: 0 1px 1px #1c5380;
13
+ }
14
+
15
+ .zoom-instagram-widget .button-connect:focus,
16
+ .zoom-instagram-widget .button-connect:hover {
17
+ border-color: #1c5380;
18
+ color: #fff;
19
+ background-image: -webkit-linear-gradient(top, #5D87A8, #3f729b);
20
+ background-image: linear-gradient(to bottom, #5D87A8, #3f729b);
21
+ }
22
+
23
+ .zoom-instagram-widget {
24
+ background: #fff;
25
+ padding: 30px;
26
+ border: 1px solid #DDD;
27
+ border-radius: 3px;
28
+ margin: 30px 10px 30px 0 !important;
29
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
30
+ max-width: 700px;
31
+ }
32
+
33
+ .zoom-themes-link {
34
+ border: 1px solid #E2E9EC;
35
+ background: #F7FAFA url('../images/wpzoom.png') no-repeat center bottom;
36
+ padding: 30px 30px 260px 30px;
37
+ border-radius: 3px;
38
+ margin: 30px 0 30px 0 !important;
39
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
40
+ max-width: 700px;
41
+ text-align: center;
42
+ }
43
+
44
+ .zoom-themes-link p {
45
+ font-size: 15px;
46
+ line-height: 1.6;
47
+ }
48
+
49
+ .cta-button {
50
+ text-align: center;
51
+ text-decoration: none;
52
+ color: #fff;
53
+ background: #3EBD3E;
54
+ padding: 10px 15px;
55
+ display: inline-block;
56
+ border-radius: 3px;
57
+ box-shadow: 0 -1px 1px rgba(0,0,0, 0.2) inset;
58
+ border: 1px solid #259425;
59
+ font-size: 16px;
60
+ text-shadow: 1px 1px rgba(0, 0, 0, 0.3);
61
+ }
62
+ .cta-button:hover {
63
+ background: #2A9B2A;
64
+ color: #fff;
65
+ }
66
+
67
+ #wpzoom-instagram-widget-settings_transient-lifetime-value{
68
+ max-width: 150px;
69
+ float: left;
70
+ }
71
+
72
+ #wpzoom-instagram-widget-settings_transient-lifetime-type{
73
+ float: left;
74
+ max-width: 100px;
75
+ }
css/instagram-widget.css ADDED
@@ -0,0 +1,268 @@