Instagram Slider Widget - Version 1.2.0

Version Description

  • Full Rewritte of the plugin
Download this release

Release Info

Developer jetonr
Plugin Icon 128x128 Instagram Slider Widget
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.1.3 to 1.2.0

assets/css/instag-slider.css CHANGED
@@ -8,7 +8,7 @@
8
  .pllexislider, .pllexislider .slides li:hover, .pllexislider .slides > li:hover > a { border: none; }
9
 
10
  /* no list style */
11
- .instag .no-bullet, .pllexislider .no-bullet { list-style:none; padding: 0; margin:0; }
12
 
13
  /* Flexi Slider Template */
14
  .pllexislider { margin: 0; position: relative; }
@@ -17,25 +17,85 @@
17
  .pllexislider .slides { zoom: 1; overflow: hidden; }
18
 
19
  /* Thumbnails Template */
20
- .instag ul.thumbnails > li { margin:0 auto; display: inline-block; *display:inline; float: none; width:24% !important; }
21
- .instag ul.thumbnails img { width: 100%; }
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  /* Control Nav */
24
- .pllexislider .pllex-control-nav { z-index:2; position: absolute; top: 10px; right: 0px; padding: 0 15px; margin-right: auto; margin-left: auto }
25
- .pllexislider.overlay .pllex-control-nav { display:none; }
26
  .pllexislider .pllex-control-nav li { margin: 0 3px; display: inline-block; zoom: 1; *display: inline; }
27
  .pllexislider .pllex-control-paging li a { width: 11px; border: none; height: 11px; display: block; background: #fff; background: rgba(255,255,255,255,0.5); cursor: pointer; text-indent: -9999px; -webkit-border-radius: 20px; -moz-border-radius: 20px; -o-border-radius: 20px; border-radius: 20px; -webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); -moz-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); -o-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); box-shadow: inset 0 0 2px rgba(0,0,0,0.3); }
28
  .pllexislider .pllex-control-paging li a:hover,
29
  .pllexislider .pllex-control-paging li a.pllex-active { background: rgba(0,0,0,0.6); -webkit-box-shadow: 0px 0px 1px 2px rgba(255,255,255,1); -moz-box-shadow: 0px 0px 1px 2px rgba(255,255,255,0.7); box-shadow: 0px 0px 1px 2px rgba(255,255,255,1);}
30
  .pllexislider .pllex-control-paging li a.pllex-active { cursor: default; }
31
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  /* Slider Normal */
33
- .pllexislider.normal ul li .instadescription p { margin-top:5px; margin-bottom: 5px; display: block; }
34
- .pllexislider.normal ul li .instatime { margin-top:5px; width: 40%; float:right; text-align: right; }
 
 
35
 
36
  /* Slider Overlay */
37
- .pllexislider.overlay ul li .jr-insta-wrap { position: relative; color: #FFF; line-height: normal; }
38
- .pllexislider.overlay ul li .jr-insta-wrap .jr-insta-datacontainer { position: absolute; display: none; left: 0; bottom: 0; width: 100%; text-shadow: 0 0 5px rgba(0,0,0,0.7); background: rgba(0,0,0,0.4); padding: 5px 15px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
39
- .pllexislider.overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-desc { line-height: normal; color: #FFF; margin-top: 5px; margin-bottom: 5px; display: block; }
40
- .pllexislider.overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-time { width: 40%; float:right; text-align: right; }
41
- .pllexislider.overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-username a { color: #FFF !important; text-decoration: none; font-weight: bold; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  .pllexislider, .pllexislider .slides li:hover, .pllexislider .slides > li:hover > a { border: none; }
9
 
10
  /* no list style */
11
+ .jr-insta-thumb .no-bullet, .pllexislider .no-bullet { list-style:none; padding: 0; margin:0; }
12
 
13
  /* Flexi Slider Template */
14
  .pllexislider { margin: 0; position: relative; }
17
  .pllexislider .slides { zoom: 1; overflow: hidden; }
18
 
19
  /* Thumbnails Template */
20
+ .jr-insta-thumb { width: 100%; margin: 0 auto; padding: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
21
+ .jr-insta-thumb:after { content: ""; display: table; clear: both; }
22
+ .jr-insta-thumb .thumbnails { width: 100%; float: left; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 3px }
23
+ .jr-insta-thumb .thumbnails img { display: block; padding: 0 !important; margin: 0 !important; max-width: 100% !important; -webkit-backface-visibility: hidden; }
24
+ .jr-insta-thumb .thumbnails > li { border: 0; background: 0; box-shadow:none; -webkit-box-shadow: none; -moz-box-shadow: none; display: -moz-inline-stack; display: inline-block; vertical-align: top; zoom: 1; *display: inline; padding: inherit !important; margin: 0 !important; text-decoration: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
25
+ .jr-insta-thumb .jr_col_1 > li { width: 100%; }
26
+ .jr-insta-thumb .jr_col_2 > li { width: 50%; }
27
+ .jr-insta-thumb .jr_col_3 > li { width: 33.33%; }
28
+ .jr-insta-thumb .jr_col_4 > li { width: 25%; }
29
+ .jr-insta-thumb .jr_col_5 > li { width: 20%; }
30
+ .jr-insta-thumb .jr_col_6 > li { width: 16.66%; }
31
+ .jr-insta-thumb .jr_col_7 > li { width: 14.28%; }
32
+ .jr-insta-thumb .jr_col_8 > li { width: 12.5%; }
33
+ .jr-insta-thumb .jr_col_9 > li { width: 11.11%; }
34
+ .jr-insta-thumb .jr_col_10 > li { width: 10%; }
35
 
36
  /* Control Nav */
37
+ .pllexislider .pllex-control-nav { z-index:2; position: absolute; top: 10px; right: 0; padding: 0 15px; margin-right: auto; margin-left: auto }
38
+ .pllexislider-overlay .pllex-control-nav { display:none; }
39
  .pllexislider .pllex-control-nav li { margin: 0 3px; display: inline-block; zoom: 1; *display: inline; }
40
  .pllexislider .pllex-control-paging li a { width: 11px; border: none; height: 11px; display: block; background: #fff; background: rgba(255,255,255,255,0.5); cursor: pointer; text-indent: -9999px; -webkit-border-radius: 20px; -moz-border-radius: 20px; -o-border-radius: 20px; border-radius: 20px; -webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); -moz-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); -o-box-shadow: inset 0 0 2px rgba(0,0,0,0.3); box-shadow: inset 0 0 2px rgba(0,0,0,0.3); }
41
  .pllexislider .pllex-control-paging li a:hover,
42
  .pllexislider .pllex-control-paging li a.pllex-active { background: rgba(0,0,0,0.6); -webkit-box-shadow: 0px 0px 1px 2px rgba(255,255,255,1); -moz-box-shadow: 0px 0px 1px 2px rgba(255,255,255,0.7); box-shadow: 0px 0px 1px 2px rgba(255,255,255,1);}
43
  .pllexislider .pllex-control-paging li a.pllex-active { cursor: default; }
44
 
45
+ /* Direction Nav */
46
+ .pllexislider .pllex-direction-nav { z-index:2; position: absolute; list-style:none; padding: 0; top: 7px; right: 7px; margin: 0; background-color: rgba(0,0,0, 0.6); -webkit-border-radius: 15%; -moz-border-radius: 15%; -o-border-radius: 15%; border-radius: 15%; }
47
+ .pllexislider-overlay .pllex-direction-nav { display:none; }
48
+ .pllexislider .pllex-direction-nav li a { line-height: normal; overflow: hidden; display: block; }
49
+ .pllexislider .pllex-direction-nav li a:focus { outline: 0 }
50
+ .pllexislider .pllex-direction-nav li:first-child { float: left; margin-right: 0; border-left: 0; border-right: 1px solid gray; }
51
+ .pllexislider .pllex-direction-nav li { float: right; margin-top: 0; border-right: 0; border-left: 1px solid #1e1e1e; }
52
+ .pllexislider .pllex-direction-nav .pllex-next:before,
53
+ .pllexislider .pllex-direction-nav .pllex-prev:before { display: inline-block; padding: 0 4px 1px; speak: none; color: #fff; font-size: 18px; text-shadow: 0 2px 0 rgba(0, 0, 0, 1); }
54
+ .pllexislider .pllex-direction-nav .pllex-next:before { content: '\25BA'; }
55
+ .pllexislider .pllex-direction-nav .pllex-prev:before { content: '\25C4'; }
56
+
57
  /* Slider Normal */
58
+ .pllexislider-normal ul li .jr-insta-datacontainer { margin-top:5px; margin-bottom: 5px; display: block; }
59
+ .pllexislider-normal ul li .jr-insta-datacontainer .jr-insta-username { text-decoration: none; display: inline-block; }
60
+ .pllexislider-normal ul li .jr-insta-datacontainer .jr-insta-time { float: right; display: inline-block; text-align: right; }
61
+ .pllexislider-normal ul li .jr-insta-datacontainer .jr-insta-caption { line-height: normal; margin-top: 5px; margin-bottom: 5px; display: block; clear : both }
62
 
63
  /* Slider Overlay */
64
+ .pllexislider-overlay a { color: #ffffff; text-decoration: none; }
65
+ .pllexislider-overlay ul li .jr-insta-wrap { position: relative; color: #FFF; line-height: normal; }
66
+ .pllexislider-overlay ul li .jr-insta-wrap .jr-insta-datacontainer { position: absolute; display: none; left: 0; bottom: 0; width: 100%; text-shadow: 0 0 5px rgba(0,0,0,0.7); background: rgba(0,0,0,0.4); padding: 5px 15px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
67
+ .pllexislider-overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-username a { color: #FFF !important; text-decoration: none; font-weight: bold; }
68
+ .pllexislider-overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-time { float:right; text-align: right; }
69
+ .pllexislider-overlay ul li .jr-insta-wrap .jr-insta-datacontainer .jr-insta-caption { line-height: normal; color: #FFF; margin-top: 5px; margin-bottom: 5px; display: block; }
70
+
71
+ /* Media queries */
72
+ @media all and (max-width: 640px){
73
+
74
+ .jr-insta-thumb .jr_col_3 > li,
75
+ .jr-insta-thumb .jr_col_4 > li,
76
+ .jr-insta-thumb .jr_col_5 > li,
77
+ .jr-insta-thumb .jr_col_6 > li {
78
+ width: 50%;
79
+ }
80
+
81
+ .jr-insta-thumb .jr_col_7 > li,
82
+ .jr-insta-thumb .jr_col_8 > li,
83
+ .jr-insta-thumb .jr_col_9 > li,
84
+ .jr-insta-thumb .jr_col_10 > li {
85
+ width: 25%;
86
+ }
87
+ }
88
+
89
+ @media all and (max-width: 480px) {
90
+
91
+ .jr-insta-thumb .jr_col_3 > li,
92
+ .jr-insta-thumb .jr_col_4 > li,
93
+ .jr-insta-thumb .jr_col_5 > li,
94
+ .jr-insta-thumb .jr_col_6 > li,
95
+ .jr-insta-thumb .jr_col_7 > li,
96
+ .jr-insta-thumb .jr_col_8 > li,
97
+ .jr-insta-thumb .jr_col_9 > li,
98
+ .jr-insta-thumb .jr_col_10 > li {
99
+ width: 100%;
100
+ }
101
+ }
assets/css/jr-insta-admin.css ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .jr-container .pressthis a span:before { content: "\f487"; color: #DC143C; }
2
+ .jr-container .pressthis a,
3
+ .jr-container .pressthis a:active,
4
+ .jr-container .pressthis a:focus,
5
+ .jr-container .pressthis a:hover { cursor: pointer; font-size: 12px; background: #53b5d9; border: 1px solid #0074a2; color: #ffffff; font-weight: bold }
6
+ .jr-container .jr_insta_error { border-left: 4px solid #dd3d36; -moz-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); padding: 5px 12px; }
7
+ .jr-container .jr-radio { margin-right: 20px }
8
+ .jr-container .jr-advanced { text-decoration: none; border: none }
9
+ .jr-container .jr-advanced:focus { outline: 0; border: none; box-shadow:none }
10
+
11
+ .jr-container .jr-advanced-input div { border: 1px solid #cfcfcf; padding: 10px; margin: 20px 0; }
12
+ .jr-container .jr-advanced-input .jr-advanced-title{ margin: -22px 0 0 0; background-color: white; width: 160px; padding: 3px 10px; border: 1px solid #cfcfcf; }
assets/js/jr-insta-admin.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+
3
+ $(document).ready(function($){
4
+
5
+ // Hide Custom Url if image link is not set to custom url
6
+ $('body').on('change', '.jr-container select[id$="images_link"]', function(e){
7
+ var images_link = $(this);
8
+ if ( images_link.val() != 'custom_url' ) {
9
+ images_link.closest('.jr-container').find('input[id$="custom_url"]').val('').parent().animate({opacity: 'hide' , height: 'hide'}, 200);
10
+ } else {
11
+ images_link.closest('.jr-container').find('input[id$="custom_url"]').parent().animate({opacity: 'show' , height: 'show'}, 200);
12
+ }
13
+ });
14
+
15
+ // Hide Refresh hour if source is wp media library
16
+ $('body').on('change', '.jr-container select[id$="template"]', function(e){
17
+ var template = $(this);
18
+ if ( template.val() == 'thumbs' ) {
19
+ template.closest('.jr-container').find('.jr-slider-options').animate({opacity: 'hide' , height: 'hide'}, 200);
20
+ template.closest('.jr-container').find('input[id$="columns"]').closest('p').animate({opacity: 'show' , height: 'show'}, 200);
21
+ } else {
22
+ template.closest('.jr-container').find('.jr-slider-options').animate({opacity: 'show' , height: 'show'}, 200);
23
+ template.closest('.jr-container').find('input[id$="columns"]').closest('p').animate({opacity: 'hide' , height: 'hide'}, 200);
24
+ }
25
+ });
26
+
27
+ // Hide Refresh hour if source is wp media library
28
+ $('body').on('change', '.jr-container input:radio[id$="source"]', function(e){
29
+ var source = $(this);
30
+ if ( source.val() != 'instagram' ) {
31
+ source.closest('.jr-container').find('input[id$="refresh_hour"]').closest('p').animate({opacity: 'hide' , height: 'hide'}, 200);
32
+ } else {
33
+ source.closest('.jr-container').find('input[id$="refresh_hour"]').closest('p').animate({opacity: 'show' , height: 'show'}, 200);
34
+ }
35
+ });
36
+
37
+ // Toggle advanced options
38
+ $('body').on('click', '.jr-advanced', function(e){
39
+ e.preventDefault();
40
+ var advanced_container = $(this).parent().next();
41
+
42
+ if ( advanced_container.is(':hidden') ) {
43
+ $(this).html('[ - Close ]');
44
+ } else {
45
+ $(this).html('[ + Open ]');
46
+ }
47
+ advanced_container.toggle();
48
+ });
49
+
50
+ });
51
+
52
+ })(jQuery);
instaram_slider.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Instagram Slider Widget
4
  Plugin URI: http://jrwebstudio.com/instagram-slider/
5
- Version: 1.1.3
6
  Description: Instagram Slider Widget is a responsive slider widget that shows 20 latest images from a public instagram user.
7
  Author: jetonr
8
  Author URI: http://jrwebstudio.com/
@@ -10,521 +10,800 @@ License: GPLv2 or later
10
  */
11
 
12
  /**
13
- * After the plugins have loaded initalise a single instance of JR_InstagramSlider
14
  */
15
- add_action( 'plugins_loaded', array( 'JR_InstagramSlider', 'get_instance' ) );
16
 
17
  /**
18
  * JR_InstagramSlider Class
19
  */
20
  class JR_InstagramSlider extends WP_Widget {
21
-
22
  /**
23
  * Plugin version, used for cache-busting of style and script file references.
24
  *
25
  * @var string
26
  */
27
- const VERSION = '1.1.3';
28
-
29
- /**
30
- * Instance of this class.
31
- *
32
- * @var object
33
- */
34
- protected static $instance = null;
35
 
36
  /**
37
  * Initialize the plugin by registering widget and loading public scripts
38
  *
39
- */
40
  public function __construct() {
41
-
42
- // Register Widget On Widgets Init
43
- add_action( 'widgets_init', array( $this, 'register_widget' ) );
44
-
 
 
 
 
45
  // Enqueue Plugin Styles and scripts
46
- add_action( 'wp_enqueue_scripts', array( $this, 'public_enqueue' ) );
47
 
48
-
49
- $widget_options = array(
50
- 'classname' => 'jr-insta-slider',
51
- 'description' => __( 'A widget that displays a slider with instagram images ', 'jrinstaslider' )
52
- );
53
 
54
- parent::__construct( 'jr_insta_slider', __('Instagram Slider', 'jrinstaslider'), $widget_options );
 
55
  }
56
-
57
- /**
58
- * Return an instance of this class.
59
- *
60
- * @return object A single instance of this class.
61
- */
62
- public static function get_instance() {
63
-
64
- // If the single instance hasn't been set, set it now.
65
- if ( null == self::$instance ) {
66
- self::$instance = new self;
67
- }
68
-
69
- return self::$instance;
70
- }
71
-
72
  /**
73
  * Register widget on windgets init
74
- *
75
- * @return void
76
  */
77
- public function register_widget() {
78
  register_widget( __CLASS__ );
79
  }
80
-
81
  /**
82
  * Enqueue public-facing Scripts and style sheet.
83
- *
84
- * @return void
85
  */
86
  public function public_enqueue() {
87
 
88
- // Enqueue Styles
89
- wp_enqueue_style(
90
- 'instag-slider',
91
- plugins_url( 'assets/css/instag-slider.css', __FILE__ ),
92
- array(),
93
- self::VERSION
94
- );
95
 
96
- // Enqueue Scripts
97
- wp_enqueue_script(
98
- 'jquery-pllexi-slider',
99
- plugins_url( 'assets/js/jquery.flexslider-min.js', __FILE__ ),
100
- array( 'jquery' ),
101
- '2.2',
102
- false
103
- );
 
 
 
 
 
 
 
 
 
 
104
  }
105
 
106
  /**
107
  * The Public view of the Widget
108
  *
109
  * @return mixed
110
- */
111
  public function widget( $args, $instance ) {
 
112
  extract( $args );
113
-
114
  //Our variables from the widget settings.
115
- $title = apply_filters('widget_title', $instance['title'] );
116
- $username = isset( $instance['username'] ) ? $instance['username'] : '';
117
- $link_to = isset( $instance['images_link'] ) ? $instance['images_link'] : 'image_url';
118
- $custom_url = isset( $instance['custom_url'] ) ? $instance['custom_url'] : '';
119
- $randomise = isset( $instance['randomise'] ) ? true : false;
120
- $images_nr = isset( $instance['images_number'] ) ? $instance['images_number'] : 5;
121
- $refresh_hour = isset( $instance['refresh_hour'] ) ? $instance['refresh_hour'] : 5;
122
- $template = isset( $instance['template'] ) ? $instance['template'] : 'slider';
123
- $attachment = isset( $instance['attachment'] ) ? true : false;
124
-
125
  echo $before_widget;
126
-
127
  // Display the widget title
128
  if ( $title ) {
129
  echo $before_title . $title . $after_title;
130
  }
131
- // Get instagram data
132
- $insta_data = $this->instagram_data( $username, $refresh_hour, $images_nr, $attachment );
133
-
134
- // Randomise Images
135
- $insta_data = $this->randomise( $insta_data, $randomise );
136
 
137
- //include the template based on user choice
138
- $this->template( $template, $insta_data, $link_to, $custom_url );
139
 
140
  echo $after_widget;
141
  }
142
-
143
  /**
144
  * Update the widget settings
145
  *
146
- * @param array $new_instance New instance values
147
- * @param array $old_instance Old instance values
148
  *
149
  * @return array
150
  */
151
- public function update( $new_instance, $old_instance ) {
152
- $instance = $old_instance;
153
-
154
- //Strip tags from title and name to remove HTML
155
- $instance['title'] = strip_tags( $new_instance['title'] );
156
- $instance['username'] = $new_instance['username'];
157
- $instance['template'] = $new_instance['template'];
158
- $instance['images_link'] = $new_instance['images_link'];
159
- $instance['custom_url'] = $new_instance['custom_url'];
160
- $instance['randomise'] = $new_instance['randomise'];
161
- $instance['images_number'] = $new_instance['images_number'];
162
- $instance['refresh_hour'] = $new_instance['refresh_hour'];
163
- $instance['attachment'] = $new_instance['attachment'];
 
 
 
 
 
 
 
 
 
164
 
165
  return $instance;
166
  }
167
-
 
168
  /**
169
  * Widget Settings Form
170
  *
171
  * @return mixed
172
- */
173
  public function form( $instance ) {
174
 
175
- //Set up some default widget settings.
176
  $defaults = array(
177
- 'title' => __('Instagram Slider', 'jrinstaslider'),
178
- 'username' => __('', 'jrinstaslider'),
179
- 'template' => 'slider',
180
- 'images_link' => 'image_url',
181
- 'custom_url' => '',
182
- 'randomise' => 0,
183
- 'images_number' => 5,
184
- 'refresh_hour' => 5,
185
- 'attachment' => 0,
 
 
 
 
 
 
 
186
  );
187
- $instance = wp_parse_args( (array) $instance, $defaults ); ?>
188
- <style type="text/css">
189
- div[id*=_jr_insta_slider-] .pressthis a span:before { content: "\f487"; }
190
- div[id*=_jr_insta_slider-] .pressthis a,
191
- div[id*=_jr_insta_slider-] .pressthis a:active,
192
- div[id*=_jr_insta_slider-] .pressthis a:focus,
193
- div[id*=_jr_insta_slider-] .pressthis a:hover { cursor: pointer; font-size: 12px; }
194
- </style>
195
- <p>
196
- <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'jrinstaslider'); ?></label>
197
- <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" />
198
- </p>
199
- <p>
200
- <label for="<?php echo $this->get_field_id( 'username' ); ?>"><?php _e('Instagram Username:', 'jrinstaslider'); ?></label>
201
- <input class="widefat" id="<?php echo $this->get_field_id( 'username' ); ?>" name="<?php echo $this->get_field_name( 'username' ); ?>" value="<?php echo $instance['username']; ?>" />
202
- </p>
203
- <p>
204
- <label for="<?php echo $this->get_field_id( 'template' ); ?>"><?php _e( 'Images Layout', 'jrinstaslider' ); ?>
205
- <select class="widefat" name="<?php echo $this->get_field_name( 'template' ); ?>">
206
- <option value="slider" <?php echo ($instance['template'] == 'slider') ? ' selected="selected"' : ''; ?>><?php _e( 'Slider - Normal', 'jrinstaslider' ); ?></option>
207
- <option value="slider-overlay" <?php echo ($instance['template'] == 'slider-overlay') ? ' selected="selected"' : ''; ?>><?php _e( 'Slider - Overlay Text', 'jrinstaslider' ); ?></option>
208
- <option value="thumbs" <?php echo ($instance['template'] == 'thumbs') ? ' selected="selected"' : ''; ?>><?php _e( 'Thumbnails', 'jrinstaslider' ); ?></option>
209
- </select>
210
- </label>
211
- </p>
212
- <p>
213
- <?php _e('Link Images To:', 'jrinstaslider'); ?><br>
214
- <label><input type="radio" id="<?php echo $this->get_field_id( 'images_link' ); ?>" name="<?php echo $this->get_field_name( 'images_link' ); ?>" value="image_url" <?php checked( 'image_url', $instance['images_link'] ); ?> /> <?php _e('Instagram Image', 'jrinstaslider'); ?></label><br />
215
- <label><input type="radio" id="<?php echo $this->get_field_id( 'images_link' ); ?>" name="<?php echo $this->get_field_name( 'images_link' ); ?>" value="user_url" <?php checked( 'user_url', $instance['images_link'] ); ?> /> <?php _e('Instagram Profile', 'jrinstaslider'); ?></label><br />
216
- <label><input type="radio" id="<?php echo $this->get_field_id( 'images_link' ); ?>" name="<?php echo $this->get_field_name( 'images_link' ); ?>" value="local_image_url" <?php checked( 'local_image_url', $instance['images_link'] ); ?> /> <?php _e('Locally Saved Image', 'jrinstaslider'); ?></label><br />
217
- <label><input type="radio" id="<?php echo $this->get_field_id( 'images_link' ); ?>" name="<?php echo $this->get_field_name( 'images_link' ); ?>" value="custom_url" <?php checked( 'custom_url', $instance['images_link'] ); ?> /> <?php _e('Custom Link', 'jrinstaslider'); ?></label><br />
218
- </p>
219
- <p>
220
- <label for="<?php echo $this->get_field_id( 'custom_url' ); ?>"><?php _e('Custom Link for Images:', 'jrinstaslider'); ?></label>
221
- <input class="widefat" id="<?php echo $this->get_field_id( 'custom_url' ); ?>" name="<?php echo $this->get_field_name( 'custom_url' ); ?>" value="<?php echo $instance['custom_url']; ?>" />
222
- <small><?php _e('* use this field only if the above option is set to <strong>Custom Link</strong>', 'jrinstaslider'); ?></small>
223
- </p>
224
- <p>
225
- <label for="<?php echo $this->get_field_id( 'randomise' ); ?>"><?php _e( 'Randomise Images:', 'jrinstaslider' ); ?></label>
226
- <input class="widefat" id="<?php echo $this->get_field_id( 'randomise' ); ?>" name="<?php echo $this->get_field_name( 'randomise' ); ?>" type="checkbox" value="1" <?php checked( '1', $instance['randomise'] ); ?> />
227
- </p>
228
- <p>
229
- <label for="<?php echo $this->get_field_id( 'images_number' ); ?>"><?php _e('Number of Images to Show:', 'jrinstaslider'); ?>
230
- <input class="small-text" id="<?php echo $this->get_field_id( 'images_number' ); ?>" name="<?php echo $this->get_field_name( 'images_number' ); ?>" value="<?php echo $instance['images_number']; ?>" />
231
- <small><?php _e('( max 20 )', 'jrinstaslider'); ?></small>
232
- </label>
233
- </p>
234
- <p>
235
- <label for="<?php echo $this->get_field_id( 'refresh_hour' ); ?>"><?php _e('Check for new images every:', 'jrinstaslider'); ?>
236
- <input class="small-text" id="<?php echo $this->get_field_id( 'refresh_hour' ); ?>" name="<?php echo $this->get_field_name( 'refresh_hour' ); ?>" value="<?php echo $instance['refresh_hour']; ?>" />
237
- <small><?php _e('hours', 'jrinstaslider'); ?></small>
238
- </label>
239
- </p>
240
- <p>
241
- <label for="<?php echo $this->get_field_id( 'attachment' ); ?>"><?php _e( 'Insert images into Media Library:', 'jrinstaslider' ); ?></label>
242
- <input class="widefat" id="<?php echo $this->get_field_id( 'attachment' ); ?>" name="<?php echo $this->get_field_name( 'attachment' ); ?>" type="checkbox" value="1" <?php checked( '1', $instance['attachment'] ); ?> />
243
- </p>
244
- <p class="pressthis"><a target="_blank" title="Donate, It Feels Great" href="http://goo.gl/RZiu34"><span>Donate, It Feels Great!</span></a></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  <?php
246
  }
247
 
248
  /**
249
- * Randomises an array using php shuffle() function
250
- *
251
- * @param array $data Instagram data array
252
- * @param bolean $randomise True or false to randomise
253
- *
254
- * @return array of randomised data
255
  */
256
- private function randomise( $data, $randomise = false ) {
257
-
258
- if ( true == $randomise ) {
259
- shuffle( $data );
260
  }
261
- return $data;
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  /**
265
  * Stores the fetched data from instagram in WordPress DB using transients
266
  *
267
- * @param string $username Instagram Username to fetch images from
268
- * @param string $cache_hours Cache hours for transient
269
- * @param string $nr_images Nr of images to fetch from instagram
270
  *
271
  * @return array of localy saved instagram data
272
  */
273
- private function instagram_data( $username, $cache_hours, $nr_images, $media_library = false ) {
274
 
275
- $opt_name = 'jr_insta_'.md5( $username );
276
- $instaData = get_transient( $opt_name );
277
- $user_opt = get_option( $opt_name );
278
-
279
- if (
280
- false === $instaData
281
- || $user_opt['username'] != $username
282
- || $user_opt['cache_hours'] != $cache_hours
283
- || $user_opt['nr_images'] != $nr_images
284
- )
285
- {
286
  $instaData = array();
287
- $insta_url = 'http://instagram.com/';
288
- $user_profile = $insta_url.$username;
289
- $json = wp_remote_get( $user_profile, array( 'sslverify' => false, 'timeout'=> 60 ) );
290
- $user_options = compact('username', 'cache_hours', 'nr_images');
291
 
292
- update_option( $opt_name, $user_options );
293
 
294
  if ( $json['response']['code'] == 200 ) {
295
-
296
- $json = $json['body'];
297
- $json = strstr( $json, 'window._sharedData = ' );
298
- $json = str_replace('window._sharedData = ', '', $json);
299
 
300
  // Compatibility for version of php where strstr() doesnt accept third parameter
301
- if ( version_compare( phpversion(), '5.3.10', '<' ) ) {
302
- $json = substr( $json, 0, strpos($json, '</script>' ) );
303
  } else {
304
  $json = strstr( $json, '</script>', true );
305
  }
306
 
307
- $json = rtrim( $json, ';' );
308
 
309
  // Function json_last_error() is not available before PHP * 5.3.0 version
310
  if ( function_exists( 'json_last_error' ) ) {
311
-
312
  ( $results = json_decode( $json, true ) ) && json_last_error() == JSON_ERROR_NONE;
313
-
314
  } else {
315
 
316
  $results = json_decode( $json, true );
317
  }
318
-
319
  if ( ( $results ) && is_array( $results ) ) {
320
- foreach( $results['entry_data']['UserProfile'][0]['userMedia'] as $current => $result ) {
321
-
322
- if( $current >= $nr_images ) break;
323
- $caption = $result['caption'];
324
- $image = $result['images']['standard_resolution'];
325
- $id = $result['id'];
326
- $image = $image['url'];
327
- $link = $result['link'];
328
- $created_time = $caption['created_time'];
329
- $text = $this->utf8_4byte_to_3byte($caption['text']);
330
- $upload_dir = wp_upload_dir();
331
- $filename_data= explode( '.', $image );
332
-
333
- if ( is_array( $filename_data ) ) {
334
-
335
- $fileformat = end( $filename_data );
336
-
337
- if ( $fileformat !== false ){
 
 
 
 
 
338
 
 
339
 
340
- $image = $this->download_insta_image( $image, md5( $id ) . '.' . $fileformat );
341
 
342
- array_push( $instaData, array(
343
- 'id' => $id,
344
- 'user_name' => $username,
345
- 'user_url' => $user_profile,
346
- 'created_time' => $created_time,
347
- 'text' => $text,
348
- 'image' => $image,
349
- 'image_path' => $upload_dir['path'] . '/' . md5( $id ) . '.' . $fileformat,
350
- 'link' => $link
351
- ));
352
 
353
- } // end -> if $fileformat !== false
354
-
355
- } // end -> is_array( $filename_data )
 
 
 
 
 
 
 
 
 
 
 
 
356
 
357
  } // end -> foreach
358
-
359
  } // end -> ( $results ) && is_array( $results ) )
360
-
361
  } // end -> $json['response']['code'] === 200 )
362
-
 
 
363
  if ( $instaData ) {
364
  set_transient( $opt_name, $instaData, $cache_hours * 60 * 60 );
365
- } // end -> true $instaData
366
-
367
- } // end -> false === $instaData
368
-
369
- // Insert into Media Library
370
- if ( true == $media_library ) {
371
-
372
- $media_library = array();
373
-
374
- foreach ( $instaData as $media_item ) {
375
-
376
- $media_library['title'] = $media_item['text'];
377
- $media_library['path'] = $media_item['image_path'];
378
- $media_library['src'] = $media_item['image'];
379
-
380
- $this->insert_into_media( $media_library );
381
  }
382
- }
 
383
 
384
  return $instaData;
385
  }
386
 
387
  /**
388
- * Function to display Templates for widget
389
- *
390
- * @param string $template The input to be sanitised
391
- * @param array $data_arr The input to be sanitised
392
- * @param string $link_to The input to be sanitised
393
- *
394
- * @include file templates
395
- *
396
- * return void
397
  */
398
- private function template( $template, $data_arr, $link_to, $custom_url ){
399
 
400
- $filename = plugin_dir_path( __FILE__ ) . "views/" . $template . '.php';
401
-
402
- if( file_exists( $filename ) ){
403
-
404
- include $filename;
405
-
406
- } else {
407
-
408
- echo __( sprintf( 'Template not found<br>%s' , $filename), 'jrinstaslider' );
409
- }
410
  }
411
-
412
  /**
413
  * Save Instagram images to upload folder and ads to media.
414
  * If the upload fails it returns the remote image url.
415
- *
416
  * @param string $url Url of image to download
417
- * @param string $file File path for image
418
  *
419
  * @return string $url Url to image
420
  */
421
- private function download_insta_image( $url, $file ){
422
-
423
- $upload_dir = wp_upload_dir();
424
- $local_file = $upload_dir['path'] . '/' . $file;
425
 
426
- if ( file_exists( $local_file ) ) {
427
- return $upload_dir['baseurl'] . $upload_dir['subdir'] . '/' . $file;
428
- }
429
 
430
- $get = wp_remote_get( $url, array( 'sslverify' => false ) );
431
- $body = wp_remote_retrieve_body( $get );
432
- $upload = wp_upload_bits( $file, '', $body );
433
-
434
- if ( false === $upload['error'] ) {
435
-
436
- return $upload['url'];
437
  }
438
 
439
- return $url;
440
- }
441
-
442
- /**
443
- * Insert Images to media library.
444
- *
445
- * @param array $attachment_data Data for attachemnt
446
- *
447
- * @return void
448
- */
449
- private function insert_into_media( $attachment_data = array() ) {
450
-
451
- if ( ! $this->get_attachment_id_from_src( $attachment_data['src'] ) ) {
452
-
453
- // Check the type of tile. We'll use this as the 'post_mime_type'.
454
- $filetype = wp_check_filetype( $attachment_data['path'], null );
455
- $attch_title = trim( preg_replace( '/([@]{1})([a-zA-Z0-9\_]+)|#(\w*[a-zA-Z_]+\w*)|\?/i', '', $attachment_data['title'] ) );
456
-
457
- if ( '' == $attch_title ) {
458
- $attch_title = basename( $attachment_data['path'] );
459
- }
460
-
461
- // Prepare an array of post data for the attachment.
462
- $attachment = array(
463
- 'guid' => $attachment_data['src'],
464
- 'post_mime_type' => $filetype['type'],
465
- 'post_title' => $attch_title,
466
- 'post_content' => '',
467
- 'post_status' => 'inherit'
468
- );
469
-
470
- // Insert the attachment.
471
- $attach_id = wp_insert_attachment( $attachment, $attachment_data['path'] );
472
-
473
- // Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
474
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
475
-
476
- // Generate the metadata for the attachment, and update the database record.
477
- $attach_data = wp_generate_attachment_metadata( $attach_id, $attachment_data['path']);
478
- wp_update_attachment_metadata( $attach_id, $attach_data );
479
  }
480
-
481
- }
482
 
483
- /**
484
- * Get Attachment Id from image source
485
- *
486
- * @param string $image_src Url of image to get id from
487
- *
488
- * @return string $id Returns attachement id
489
- */
490
- private function get_attachment_id_from_src( $url ) {
491
-
492
- // add multisite check for other types of links
493
- if(defined('MULTISITE') && MULTISITE) {
494
- global $wpdb;
495
-
496
- $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $url));
497
- if ( isset( $attachment[0] ) ) {
498
- return $attachment[0];
499
- }
500
- }
501
-
502
- // Split the $url into two parts with the wp-content directory as the separator.
503
- $parse_url = explode( parse_url( WP_CONTENT_URL, PHP_URL_PATH ), $url );
504
-
505
- // Get the host of the current site and the host of the $url, ignoring www.
506
- $this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
507
- $file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
508
-
509
- // Return false if there aren't any $url parts or if the current host and $url host do not match.
510
- if ( ! isset( $parse_url[1] ) || empty( $parse_url[1] ) || ( $this_host != $file_host ) ) {
511
- return false;
512
  }
513
-
514
- // Now we're going to quickly search the DB for any attachment GUID with a partial path match.
515
- // Example: /uploads/2013/05/test-image.jpg
516
- global $wpdb;
517
-
518
- $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parse_url[1] ) );
519
-
520
- // Returns attachment if isset.
521
- if ( isset( $attachment[0] ) ) {
522
- return $attachment[0];
523
  }
524
 
525
- return false;
526
- }
 
 
 
527
 
 
 
 
 
528
  /**
529
  * Sanitize 4-byte UTF8 chars; no full utf8mb4 support in drupal7+mysql stack.
530
  * This solution runs in O(n) time BUT assumes that all incoming input is
@@ -534,38 +813,43 @@ class JR_InstagramSlider extends WP_Widget {
534
  *
535
  * @return the sanitized input
536
  */
537
- private function utf8_4byte_to_3byte( $input ) {
538
-
539
- if (!empty($input)) {
540
- $utf8_2byte = 0xC0 /*1100 0000*/; $utf8_2byte_bmask = 0xE0 /*1110 0000*/;
541
- $utf8_3byte = 0xE0 /*1110 0000*/; $utf8_3byte_bmask = 0XF0 /*1111 0000*/;
542
- $utf8_4byte = 0xF0 /*1111 0000*/; $utf8_4byte_bmask = 0xF8 /*1111 1000*/;
543
-
544
- $sanitized = "";
545
- $len = strlen($input);
546
- for ($i = 0; $i < $len; ++$i) {
547
- $mb_char = $input[$i]; // Potentially a multibyte sequence
548
- $byte = ord($mb_char);
549
- if (($byte & $utf8_2byte_bmask) == $utf8_2byte) {
550
- $mb_char .= $input[++$i];
551
- }
552
- else if (($byte & $utf8_3byte_bmask) == $utf8_3byte) {
553
- $mb_char .= $input[++$i];
554
- $mb_char .= $input[++$i];
555
- }
556
- else if (($byte & $utf8_4byte_bmask) == $utf8_4byte) {
557
- // Replace with ? to avoid MySQL exception
558
- $mb_char = '?';
559
- $i += 3;
560
- }
561
-
562
- $sanitized .= $mb_char;
 
 
 
 
 
 
 
 
563
  }
564
-
565
- $input= $sanitized;
566
- }
567
-
568
- return $input;
569
  }
570
-
571
- } // end of class JR_InstagramSlider
2
  /*
3
  Plugin Name: Instagram Slider Widget
4
  Plugin URI: http://jrwebstudio.com/instagram-slider/
5
+ Version: 1.2.0
6
  Description: Instagram Slider Widget is a responsive slider widget that shows 20 latest images from a public instagram user.
7
  Author: jetonr
8
  Author URI: http://jrwebstudio.com/
10
  */
11
 
12
  /**
13
+ * On widgets Init register Widget
14
  */
15
+ add_action( 'widgets_init', array( 'JR_InstagramSlider', 'register_widget' ) );
16
 
17
  /**
18
  * JR_InstagramSlider Class
19
  */
20
  class JR_InstagramSlider extends WP_Widget {
21
+
22
  /**
23
  * Plugin version, used for cache-busting of style and script file references.
24
  *
25
  * @var string
26
  */
27
+ const VERSION = '1.2.0';
 
 
 
 
 
 
 
28
 
29
  /**
30
  * Initialize the plugin by registering widget and loading public scripts
31
  *
32
+ */
33
  public function __construct() {
34
+
35
+ // Widget ID and Class Setup
36
+ parent::__construct( 'jr_insta_slider', __( 'Instagram Slider', 'jrinstaslider' ), array(
37
+ 'classname' => 'jr-insta-slider',
38
+ 'description' => __( 'A widget that displays a slider with instagram images ', 'jrinstaslider' )
39
+ )
40
+ );
41
+
42
  // Enqueue Plugin Styles and scripts
43
+ add_action( 'wp_enqueue_scripts', array( $this, 'public_enqueue' ) );
44
 
45
+ // Enqueue Plugin Styles and scripts for admin pages
46
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue' ) );
 
 
 
47
 
48
+ // Instgram Action to display images
49
+ add_action( 'jr_instagram', array( $this, 'instagram_images' ) );
50
  }
51
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  /**
53
  * Register widget on windgets init
 
 
54
  */
55
+ public static function register_widget() {
56
  register_widget( __CLASS__ );
57
  }
58
+
59
  /**
60
  * Enqueue public-facing Scripts and style sheet.
 
 
61
  */
62
  public function public_enqueue() {
63
 
64
+ wp_enqueue_style( 'instag-slider', plugins_url( 'assets/css/instag-slider.css', __FILE__ ), array(), self::VERSION );
 
 
 
 
 
 
65
 
66
+ wp_enqueue_script( 'jquery-pllexi-slider', plugins_url( 'assets/js/jquery.flexslider-min.js', __FILE__ ), array( 'jquery' ), '2.2', false );
67
+ }
68
+
69
+ /**
70
+ * Enqueue admin side scripts and styles
71
+ *
72
+ * @param string $hook
73
+ */
74
+ public function admin_enqueue( $hook ) {
75
+
76
+ if ( 'widgets.php' != $hook ) {
77
+ return;
78
+ }
79
+
80
+ wp_enqueue_style( 'jr-insta-admin-styles', plugins_url( 'assets/css/jr-insta-admin.css', __FILE__ ), array(), self::VERSION );
81
+
82
+ wp_enqueue_script( 'jr-insta-admin-script', plugins_url( 'assets/js/jr-insta-admin.js', __FILE__ ), array( 'jquery' ), self::VERSION, true );
83
+
84
  }
85
 
86
  /**
87
  * The Public view of the Widget
88
  *
89
  * @return mixed
90
+ */
91
  public function widget( $args, $instance ) {
92
+
93
  extract( $args );
94
+
95
  //Our variables from the widget settings.
96
+ $title = apply_filters( 'widget_title', $instance['title'] );
97
+
 
 
 
 
 
 
 
 
98
  echo $before_widget;
99
+
100
  // Display the widget title
101
  if ( $title ) {
102
  echo $before_title . $title . $after_title;
103
  }
 
 
 
 
 
104
 
105
+ do_action( 'jr_instagram', $instance );
 
106
 
107
  echo $after_widget;
108
  }
109
+
110
  /**
111
  * Update the widget settings
112
  *
113
+ * @param array $new_instance New instance values
114
+ * @param array $old_instance Old instance values
115
  *
116
  * @return array
117
  */
118
+ public function update( $new_instance, $instance ) {
119
+
120
+ $instance['title'] = strip_tags( $new_instance['title'] );
121
+ $instance['username'] = $new_instance['username'];
122
+ $instance['source'] = $new_instance['source'];
123
+ $instance['template'] = $new_instance['template'];
124
+ $instance['images_link'] = $new_instance['images_link'];
125
+ $instance['custom_url'] = $new_instance['custom_url'];
126
+ $instance['orderby'] = $new_instance['orderby'];
127
+ $instance['images_number'] = $new_instance['images_number'];
128
+ $instance['columns'] = $new_instance['columns'];
129
+ $instance['refresh_hour'] = $new_instance['refresh_hour'];
130
+ $instance['image_size'] = $new_instance['image_size'];
131
+ $instance['image_link_rel'] = $new_instance['image_link_rel'];
132
+ $instance['image_link_class'] = $new_instance['image_link_class'];
133
+ $instance['controls'] = $new_instance['controls'];
134
+ $instance['animation'] = $new_instance['animation'];
135
+ $instance['description'] = $new_instance['description'];
136
+
137
+ if ( $instance['source'] == 'instagram' ) {
138
+ $this->instagram_data( $instance['username'], $instance['refresh_hour'], $instance['images_number'] );
139
+ }
140
 
141
  return $instance;
142
  }
143
+
144
+
145
  /**
146
  * Widget Settings Form
147
  *
148
  * @return mixed
149
+ */
150
  public function form( $instance ) {
151
 
 
152
  $defaults = array(
153
+ 'title' => __('Instagram Slider', 'jrinstaslider'),
154
+ 'username' => '',
155
+ 'source' => 'instagram',
156
+ 'template' => 'slider',
157
+ 'images_link' => 'image_url',
158
+ 'custom_url' => '',
159
+ 'orderby' => 'rand',
160
+ 'images_number' => 5,
161
+ 'columns' => 4,
162
+ 'refresh_hour' => 5,
163
+ 'image_size' => 'full',
164
+ 'image_link_rel' => '',
165
+ 'image_link_class' => '',
166
+ 'controls' => 'prev_next',
167
+ 'animation' => 'slide',
168
+ 'description' => array( 'username', 'time','caption' )
169
  );
170
+
171
+ $instance = wp_parse_args( (array) $instance, $defaults );
172
+
173
+ ?>
174
+ <div class="jr-container">
175
+ <p>
176
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'jrinstaslider'); ?></label>
177
+ <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" />
178
+ </p>
179
+ <p>
180
+ <label for="<?php echo $this->get_field_id( 'username' ); ?>"><?php _e('Instagram Username:', 'jrinstaslider'); ?></label>
181
+ <input class="widefat" id="<?php echo $this->get_field_id( 'username' ); ?>" name="<?php echo $this->get_field_name( 'username' ); ?>" value="<?php echo $instance['username']; ?>" />
182
+ </p>
183
+ <p>
184
+ <?php _e( 'Source:', 'jrinstaslider' ); ?><br>
185
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'source' ); ?>" name="<?php echo $this->get_field_name( 'source' ); ?>" value="instagram" <?php checked( 'instagram', $instance['source'] ); ?> /> <?php _e( 'Instagram', 'jrinstaslider' ); ?></label>
186
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'source' ); ?>" name="<?php echo $this->get_field_name( 'source' ); ?>" value="media_library" <?php checked( 'media_library', $instance['source'] ); ?> /> <?php _e( 'WP Media Library', 'jrinstaslider' ); ?></label>
187
+ <br><small class="description"><?php _e( 'WP Media Library option will display previously saved instagram images for the user in the field above!', 'jrinstaslider') ?></small>
188
+ </p>
189
+ <p>
190
+ <label for="<?php echo $this->get_field_id( 'template' ); ?>"><?php _e( 'Template', 'jrinstaslider' ); ?>
191
+ <select class="widefat" name="<?php echo $this->get_field_name( 'template' ); ?>" id="<?php echo $this->get_field_id( 'template' ); ?>">
192
+ <option value="slider" <?php echo ($instance['template'] == 'slider') ? ' selected="selected"' : ''; ?>><?php _e( 'Slider - Normal', 'jrinstaslider' ); ?></option>
193
+ <option value="slider-overlay" <?php echo ($instance['template'] == 'slider-overlay') ? ' selected="selected"' : ''; ?>><?php _e( 'Slider - Overlay Text', 'jrinstaslider' ); ?></option>
194
+ <option value="thumbs" <?php echo ($instance['template'] == 'thumbs') ? ' selected="selected"' : ''; ?>><?php _e( 'Thumbnails', 'jrinstaslider' ); ?></option>
195
+ </select>
196
+ </label>
197
+ </p>
198
+ <p>
199
+ <label for="<?php echo $this->get_field_id( 'orderby' ); ?>"><?php _e( 'Order by', 'jrinstaslider' ); ?>
200
+ <select class="widefat" name="<?php echo $this->get_field_name( 'orderby' ); ?>" id="<?php echo $this->get_field_id( 'orderby' ); ?>">
201
+ <option value="date-ASC" <?php selected( $instance['orderby'], 'date-ASC', true); ?>><?php _e( 'Date - Ascending', 'jrinstaslider' ); ?></option>
202
+ <option value="date-DESC" <?php selected( $instance['orderby'], 'date-DESC', true); ?>><?php _e( 'Date - Descending', 'jrinstaslider' ); ?></option>
203
+ <option value="popular-ASC" <?php selected( $instance['orderby'], 'popular-ASC', true); ?>><?php _e( 'Popularity - Ascending', 'jrinstaslider' ); ?></option>
204
+ <option value="popular-DESC" <?php selected( $instance['orderby'], 'popular-DESC', true); ?>><?php _e( 'Popularity - Descending', 'jrinstaslider' ); ?></option>
205
+ <option value="rand" <?php selected( $instance['orderby'], 'rand', true); ?>><?php _e( 'Random', 'jrinstaslider' ); ?></option>
206
+ </select>
207
+ </label>
208
+ </p>
209
+ <p>
210
+ <label for="<?php echo $this->get_field_id( 'images_link' ); ?>"><?php _e( 'Link to', 'jrinstaslider' ); ?>
211
+ <select class="widefat" name="<?php echo $this->get_field_name( 'images_link' ); ?>" id="<?php echo $this->get_field_id( 'images_link' ); ?>">
212
+ <option value="image_url" <?php selected( $instance['images_link'], 'image_url', true); ?>><?php _e( 'Instagram Image', 'jrinstaslider' ); ?></option>
213
+ <option value="user_url" <?php selected( $instance['images_link'], 'user_url', true); ?>><?php _e( 'Instagram Profile', 'jrinstaslider' ); ?></option>
214
+ <option value="local_image_url" <?php selected( $instance['images_link'], 'local_image_url', true); ?>><?php _e( 'Locally Saved Image', 'jrinstaslider' ); ?></option>
215
+ <option value="attachment" <?php selected( $instance['images_link'], 'attachment', true); ?>><?php _e( 'Attachment Page', 'jrinstaslider' ); ?></option>
216
+ <option value="custom_url" <?php selected( $instance['images_link'], 'custom_url', true ); ?>><?php _e( 'Custom Link', 'jrinstaslider' ); ?></option>
217
+ <option value="none" <?php selected( $instance['images_link'], 'none', true); ?>><?php _e( 'None', 'jrinstaslider' ); ?></option>
218
+ </select>
219
+ </label>
220
+ </p>
221
+ <p class="<?php if ( 'custom_url' != $instance['images_link'] ) echo 'hidden'; ?>">
222
+ <label for="<?php echo $this->get_field_id( 'custom_url' ); ?>"><?php _e( 'Custom link:', 'jrinstaslider'); ?></label>
223
+ <input class="widefat" id="<?php echo $this->get_field_id( 'custom_url' ); ?>" name="<?php echo $this->get_field_name( 'custom_url' ); ?>" value="<?php echo $instance['custom_url']; ?>" />
224
+ <small><?php _e('* use this field only if the above option is set to <strong>Custom Link</strong>', 'jrinstaslider'); ?></small>
225
+ </p>
226
+ <p>
227
+ <label for="<?php echo $this->get_field_id( 'images_number' ); ?>"><?php _e( 'Number of images to show:', 'jrinstaslider' ); ?>
228
+ <input class="small-text" id="<?php echo $this->get_field_id( 'images_number' ); ?>" name="<?php echo $this->get_field_name( 'images_number' ); ?>" value="<?php echo $instance['images_number']; ?>" />
229
+ <small><?php _e( 'limit is 20 if <strong>Source</strong> is Instagram', 'jrinstaslider' ); ?></small>
230
+ </label>
231
+ </p>
232
+ <p class="<?php if ( 'thumbs' != $instance['template'] ) echo 'hidden'; ?>">
233
+ <label for="<?php echo $this->get_field_id( 'columns' ); ?>"><?php _e( 'Number of Columns:', 'jrinstaslider' ); ?>
234
+ <input class="small-text" id="<?php echo $this->get_field_id( 'columns' ); ?>" name="<?php echo $this->get_field_name( 'columns' ); ?>" value="<?php echo $instance['columns']; ?>" />
235
+ <small><?php _e('max is 10 ( only for thumbnails template )', 'jrinstaslider'); ?></small>
236
+ </label>
237
+ </p>
238
+ <p class="<?php if ( 'instagram' != $instance['source'] ) echo 'hidden'; ?>">
239
+ <label for="<?php echo $this->get_field_id( 'refresh_hour' ); ?>"><?php _e( 'Check for new images every:', 'jrinstaslider' ); ?>
240
+ <input class="small-text" id="<?php echo $this->get_field_id( 'refresh_hour' ); ?>" name="<?php echo $this->get_field_name( 'refresh_hour' ); ?>" value="<?php echo $instance['refresh_hour']; ?>" />
241
+ <small><?php _e('hours', 'jrinstaslider'); ?></small>
242
+ </label>
243
+ </p>
244
+ <p>
245
+ <strong>Advanced Options</strong>
246
+ <?php
247
+ $advanced_class = '';
248
+ $advanced_text = '[ - Close ]';
249
+ if ( '' == trim( $instance['image_link_rel'] ) && '' == trim( $instance['image_link_class'] ) && '' == trim( $instance['image_size'] ) ) {
250
+ $advanced_class = 'hidden';
251
+ $advanced_text = '[ + Open ]';
252
+ }
253
+ ?>
254
+ <a href="#" class="jr-advanced"><?php echo $advanced_text; ?></a>
255
+ </p>
256
+ <div class="jr-advanced-input <?php echo $advanced_class; ?>">
257
+ <div class="jr-image-options">
258
+ <h4 class="jr-advanced-title"><?php _e( 'Advanced Image Options', 'jrinstaslider'); ?></h4>
259
+ <?php
260
+ $image_size_options = get_intermediate_image_sizes();
261
+ $image_sizes = array( 'thumbnail', 'medium', 'large' );
262
+ if ( is_array( $image_size_options ) && !empty( $image_size_options ) ) {
263
+ $image_sizes = $image_size_options;
264
+ }
265
+ ?>
266
+ <p>
267
+ <label for="<?php echo $this->get_field_id( 'image_size' ); ?>"><?php _e( 'Image size', 'jrinstaslider' ); ?></label>
268
+ <select class="widefat" id="<?php echo $this->get_field_id( 'image_size' ); ?>" name="<?php echo $this->get_field_name( 'image_size' ); ?>">
269
+ <option value=""><?php _e('Select Image Size', 'jrinstaslider') ?></option>
270
+ <?php
271
+ foreach ( $image_sizes as $image_size_option ) {
272
+ echo '
273
+ <option value="' . esc_attr( $image_size_option ) . '"'
274
+ . selected( $image_size_option, $instance['image_size'], false )
275
+ . '>' . ucfirst( $image_size_option ) . '</option>';
276
+ }
277
+ ?>
278
+ </select>
279
+ <small class="description"><?php _e( 'Image Sizes are defined using add_image_size() function', 'jrinstaslider' ); ?></small>
280
+ </p>
281
+ <p>
282
+ <label for="<?php echo $this->get_field_id( 'image_link_rel' ); ?>"><?php _e( 'Image Link rel attribute', 'jrinstaslider' ); ?>:</label>
283
+ <input class="widefat" id="<?php echo $this->get_field_id( 'image_link_rel' ); ?>" name="<?php echo $this->get_field_name( 'image_link_rel' ); ?>" value="<?php echo $instance['image_link_rel']; ?>" />
284
+ <small class="description"><?php _e( 'Specifies the relationship between the current page and the linked website', 'jrinstaslider' ); ?></small>
285
+ </p>
286
+ <p>
287
+ <label for="<?php echo $this->get_field_id( 'image_link_class' ); ?>"><?php _e( 'Image Link class', 'jrinstaslider' ); ?>:</label>
288
+ <input class="widefat" id="<?php echo $this->get_field_id( 'image_link_class' ); ?>" name="<?php echo $this->get_field_name( 'image_link_class' ); ?>" value="<?php echo $instance['image_link_class']; ?>" />
289
+ <small class="description"><?php _e( 'Usefull if you are using jQuery lightbox plugins to open links', 'jrinstaslider' ); ?></small>
290
+
291
+ </p>
292
+ </div>
293
+ <div class="jr-slider-options <?php if ( 'thumbs' == $instance['template'] ) echo 'hidden'; ?>">
294
+ <h4 class="jr-advanced-title"><?php _e( 'Advanced Slider Options', 'jrinstaslider'); ?></h4>
295
+ <p>
296
+ <?php _e( 'Slider Navigation Controls:', 'jrinstaslider' ); ?><br>
297
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'controls' ); ?>" name="<?php echo $this->get_field_name( 'controls' ); ?>" value="prev_next" <?php checked( 'prev_next', $instance['controls'] ); ?> /> <?php _e( 'Prev & Next', 'jrinstaslider' ); ?></label>
298
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'controls' ); ?>" name="<?php echo $this->get_field_name( 'controls' ); ?>" value="numberless" <?php checked( 'numberless', $instance['controls'] ); ?> /> <?php _e( 'Numberless', 'jrinstaslider' ); ?></label>
299
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'controls' ); ?>" name="<?php echo $this->get_field_name( 'controls' ); ?>" value="none" <?php checked( 'none', $instance['controls'] ); ?> /> <?php _e( 'No Navigation', 'jrinstaslider' ); ?></label>
300
+ </p>
301
+ <p>
302
+ <?php _e( 'Slider Animation:', 'jrinstaslider' ); ?><br>
303
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'animation' ); ?>" name="<?php echo $this->get_field_name( 'animation' ); ?>" value="slide" <?php checked( 'slide', $instance['animation'] ); ?> /> <?php _e( 'Slide', 'jrinstaslider' ); ?></label>
304
+ <label class="jr-radio"><input type="radio" id="<?php echo $this->get_field_id( 'animation' ); ?>" name="<?php echo $this->get_field_name( 'animation' ); ?>" value="fade" <?php checked( 'fade', $instance['animation'] ); ?> /> <?php _e( 'Fade', 'jrinstaslider' ); ?></label>
305
+ </p>
306
+ <p>
307
+ <label for="<?php echo $this->get_field_id('description'); ?>"><?php _e( 'Slider Text Description:', 'jrinstaslider' ); ?></label>
308
+ <select size=3 class='widefat' id="<?php echo $this->get_field_id('description'); ?>" name="<?php echo $this->get_field_name('description'); ?>[]" multiple="multiple">
309
+ <option value='username' <?php $this->selected( $instance['description'], 'username' ); ?>><?php _e( 'Username', 'jrinstaslider'); ?></option>
310
+ <option value='time'<?php $this->selected( $instance['description'], 'time' ); ?>><?php _e( 'Time', 'jrinstaslider'); ?></option>
311
+ <option value='caption'<?php $this->selected( $instance['description'], 'caption' ); ?>><?php _e( 'Caption', 'jrinstaslider'); ?></option>
312
+ </select>
313
+ <small class="description"><?php _e( 'Hold ctrl and click the fields you want to show/hide on your slider. Leave all unselected to hide them all. Default all selected.', 'jrinstaslider') ?></small>
314
+ </p>
315
+ </div>
316
+ </div>
317
+ <p class="pressthis"><a target="_blank" title="Donate To Keep This Plugin Alive!" href="http://goo.gl/RZiu34"><span>Donate To Keep This Plugin Alive!</span></a></p>
318
+ </div>
319
  <?php
320
  }
321
 
322
  /**
323
+ * Selected array function echoes selected if in array
324
+ *
325
+ * @param array $haystack The array to search in
326
+ * @param string $current The string value to search in array;
327
+ *
328
+ * @return string
329
  */
330
+ private function selected( $haystack, $current ) {
331
+
332
+ if( is_array( $haystack ) && in_array( $current, $haystack ) ) {
333
+ $current = $haystack = 1;
334
  }
335
+ selected( $haystack, $current, true );
336
+ }
337
+
338
+ /**
339
+ * Echoes the Display Instagram Images method
340
+ *
341
+ * @param array $args
342
+ *
343
+ * @return void
344
+ */
345
+ public function instagram_images( $args ) {
346
+ echo $this->display_images( $args );
347
  }
348
 
349
+ /**
350
+ * Runs the query for images and returns the html
351
+ *
352
+ * @param array $args
353
+ *
354
+ * @return string
355
+ */
356
+ private function display_images( $args ) {
357
+
358
+ $username = isset( $args['username'] ) && !empty( $args['username'] ) ? $args['username'] : false;
359
+ $source = isset( $args['source'] ) && !empty( $args['source'] ) ? $args['source'] : 'instagram';
360
+ $template = isset( $args['template'] ) ? $args['template'] : 'slider';
361
+ $orderby = isset( $args['orderby'] ) ? $args['orderby'] : 'rand';
362
+ $images_link = isset( $args['images_link'] ) ? $args['images_link'] : 'local_image_url';
363
+ $custom_url = isset( $args['custom_url'] ) ? $args['custom_url'] : '';
364
+ $images_number = isset( $args['images_number'] ) ? absint( $args['images_number'] ) : 5;
365
+ $columns = isset( $args['columns'] ) ? absint( $args['columns'] ) : 4;
366
+ $refresh_hour = isset( $args['refresh_hour'] ) ? absint( $args['refresh_hour'] ) : 5;
367
+ $image_size = isset( $args['image_size'] ) ? $args['image_size'] : 'full';
368
+ $image_link_rel = isset( $args['image_link_rel'] ) ? $args['image_link_rel'] : '';
369
+ $image_link_class = isset( $args['image_link_class'] ) ? $args['image_link_class'] : '';
370
+ $controls = isset( $args['controls'] ) ? $args['controls'] : 'prev_next';
371
+ $animation = isset( $args['animation'] ) ? $args['animation'] : 'slide';
372
+ $description = isset( $args['description'] ) ? $args['description'] : array();
373
+
374
+ if ( false == $username ) {
375
+ return false;
376
+ }
377
+
378
+ if ( !empty( $description ) && !is_array( $description ) ) {
379
+ $description = explode( ',', $description );
380
+ }
381
+
382
+ if ( $source == 'instagram' && $refresh_hour == 0 ) {
383
+ $refresh_hour = 5;
384
+ }
385
+
386
+ $template_args = array(
387
+ 'image_size' => $image_size,
388
+ 'link_rel' => $image_link_rel,
389
+ 'link_class' => $image_link_class
390
+ );
391
+
392
+ $query_args = array(
393
+ 'post_type' => 'attachment',
394
+ 'post_status' => 'inherit',
395
+ 'post_mime_type' => 'image',
396
+ 'posts_per_page' => -1,
397
+ 'orderby' => 'rand',
398
+ 'no_found_rows' => true
399
+ );
400
+
401
+ if ( $orderby != 'rand' ) {
402
+
403
+ $orderby = explode( '-', $orderby );
404
+ $meta_key = $orderby[0] == 'date' ? 'jr_insta_timestamp' : 'jr_insta_popularity';
405
+
406
+ $query_args['meta_key'] = $meta_key;
407
+ $query_args['orderby'] = 'meta_value_num';
408
+ $query_args['order'] = $orderby[1];
409
+ }
410
+
411
+ if ( $source != 'instagram' ) {
412
+ $query_args['posts_per_page'] = $images_number;
413
+ $query_args['meta_query'] = array(
414
+ array(
415
+ 'key' => 'jr_insta_username',
416
+ 'value' => $username,
417
+ 'compare' => '='
418
+ )
419
+ );
420
+ } else {
421
+ $query_args['post__in'] = $this->instagram_data( $username, $refresh_hour, $images_number );
422
+ }
423
+
424
+ $instagram_images = new WP_Query( $query_args );
425
+
426
+ $output = __( 'No Images Yet', 'jrinstaslider' );
427
+
428
+ if ( $instagram_images->have_posts() ) {
429
+
430
+ $images_div_class = 'jr-insta-thumb';
431
+ $ul_class = 'thumbnails jr_col_' . $columns;
432
+ $slider_script = '';
433
+
434
+ if ( $template != 'thumbs' ) {
435
+
436
+ $template_args['description'] = $description;
437
+ $direction_nav = ( $controls == 'prev_next' ) ? 'true' : 'false';
438
+ $control_nav = ( $controls == 'numberless' ) ? 'true': 'false';
439
+ $ul_class = 'slides';
440
+
441
+ if ( $template == 'slider' ) {
442
+ $images_div_class = 'pllexislider pllexislider-normal';
443
+ $slider_script =
444
+ "<script type='text/javascript'>" . "\n" .
445
+ " jQuery(document).ready(function($) {" . "\n" .
446
+ " $('.pllexislider-normal').pllexislider({" . "\n" .
447
+ " animation: '{$animation}'," . "\n" .
448
+ " directionNav: {$direction_nav}," . "\n" .
449
+ " controlNav: {$control_nav}," . "\n" .
450
+ " prevText: ''," . "\n" .
451
+ " nextText: ''," . "\n" .
452
+ " });" . "\n" .
453
+ " });" . "\n" .
454
+ "</script>" . "\n";
455
+ } else {
456
+ $images_div_class = 'pllexislider pllexislider-overlay';
457
+ $slider_script =
458
+ "<script type='text/javascript'>" . "\n" .
459
+ " jQuery(document).ready(function($) {" . "\n" .
460
+ " $('.pllexislider-overlay').pllexislider({" . "\n" .
461
+ " animation: '{$animation}'," . "\n" .
462
+ " directionNav: {$direction_nav}," . "\n" .
463
+ " controlNav: {$control_nav}," . "\n" .
464
+ " prevText: ''," . "\n" .
465
+ " nextText: ''," . "\n" .
466
+ " start: function(slider){" . "\n" .
467
+ " slider.hover(" . "\n" .
468
+ " function () {" . "\n" .
469
+ " slider.find('.jr-insta-datacontainer, .pllex-control-nav, .pllex-direction-nav').stop(true,true).fadeIn();" . "\n" .
470
+ " }," . "\n" .
471
+ " function () {" . "\n" .
472
+ " slider.find('.jr-insta-datacontainer, .pllex-control-nav, .pllex-direction-nav').stop(true,true).fadeOut();" . "\n" .
473
+ " }" . "\n" .
474
+ " );" . "\n" .
475
+ " }" . "\n" .
476
+ " });" . "\n" .
477
+ " });" . "\n" .
478
+ "</script>" . "\n";
479
+ }
480
+ }
481
+
482
+ $images_div = "<div class='{$images_div_class}'>\n";
483
+ $images_ul = "<ul class='no-bullet {$ul_class}'>\n";
484
+
485
+ $output = $slider_script . $images_div . $images_ul;
486
+
487
+ while ( $instagram_images->have_posts() ) : $instagram_images->the_post();
488
+
489
+ $id = get_the_id();
490
+
491
+ if ( 'image_url' == $images_link ) {
492
+ $template_args['link_to'] = get_post_meta( $id, 'jr_insta_link', true );
493
+ } elseif ( 'user_url' == $images_link ) {
494
+ $template_args['link_to'] = 'http://instagram.com/' . $username;
495
+ } elseif ( 'local_image_url' == $images_link ) {
496
+ $template_args['link_to'] = wp_get_attachment_url( $id );
497
+ } elseif ( 'attachment' == $images_link ) {
498
+ $template_args['link_to'] = get_permalink( $id );
499
+ } elseif ( 'custom_url' == $images_link ) {
500
+ $template_args['link_to'] = $custom_url;
501
+ }
502
+
503
+ $output .= $this->get_template( $template, $template_args );
504
+
505
+ endwhile;
506
+
507
+ $output .= "</ul>";
508
+ $output .= "</div>";
509
+
510
+ }
511
+
512
+ wp_reset_postdata();
513
+
514
+ return $output;
515
+ }
516
+
517
+ /**
518
+ * Function to display Templates styles
519
+ *
520
+ * @param string $template
521
+ * @param array $args
522
+ *
523
+ * return mixed
524
+ */
525
+ private function get_template( $template, $args ) {
526
+
527
+ $image_url = wp_get_attachment_image_src( get_the_id(), $args['image_size'] );
528
+ $all_metas = get_post_custom( get_the_id() );
529
+ $link_to = isset( $args['link_to'] ) ? $args['link_to'] : false;
530
+ $caption = get_the_excerpt();
531
+ $short_caption = wp_trim_words( $caption, 10 );
532
+
533
+ $image_src = '<img src="' . $image_url[0] . '" alt="' . $short_caption . '" title="' . $short_caption . '" />';
534
+ $image_output = $image_src;
535
+
536
+ if ( $link_to ) {
537
+ $image_output = '<a href="' . $link_to . '" target="_blank"';
538
+
539
+ if ( ! empty( $args['link_rel'] ) ) {
540
+ $image_output .= ' rel="' . $args['link_rel'] . '"';
541
+ }
542
+
543
+ if ( ! empty( $args['link_class'] ) ) {
544
+ $image_output .= ' class="' . $args['link_class'] . '"';
545
+ }
546
+ $image_output .= ' title="' . $short_caption . '">' . $image_src . '</a>';
547
+ }
548
+
549
+ $output = '';
550
+
551
+ // Template : Normal Slider
552
+ if ( $template == 'slider' ) {
553
+
554
+ $output .= "<li>";
555
+
556
+ $output .= $image_output;
557
+
558
+ if ( count( $args['description'] ) >= 1 ) {
559
+
560
+ $output .= "<div class='jr-insta-datacontainer'>\n";
561
+
562
+ if ( $all_metas['jr_insta_timestamp'][0] && in_array( 'time', $args['description'] ) ) {
563
+ $time = human_time_diff( $all_metas['jr_insta_timestamp'][0] );
564
+ $output .= "<span class='jr-insta-time'>{$time} ago</span>\n";
565
+ }
566
+ if ( in_array( 'username', $args['description'] ) ) {
567
+ $output .= "<span class='jr-insta-username'>by <a rel='nofollow' href='http://instagram.com/{$all_metas['jr_insta_username'][0]}' target='_blank'>{$all_metas['jr_insta_username'][0]}</a></span>\n";
568
+ }
569
+
570
+ if ( $caption != '' && in_array( 'caption', $args['description'] ) ) {
571
+ $caption = preg_replace( '/@([a-z0-9_]+)/i', '&nbsp;<a href="http://instagram.com/$1" rel="nofollow" target="_blank">@$1</a>&nbsp;', $caption );
572
+ $output .= "<span class='jr-insta-caption'>{$caption}</span>\n";
573
+ }
574
+
575
+ $output .= "</div>\n";
576
+ }
577
+
578
+ $output .= "</li>";
579
+
580
+ // Template : Slider with text Overlay on mouse over
581
+ } elseif ( $template == 'slider-overlay' ) {
582
+
583
+ $output .= "<li>";
584
+
585
+ $output .= $image_output;
586
+
587
+ if ( count( $args['description'] ) >= 1 ) {
588
+
589
+ $output .= "<div class='jr-insta-wrap'>\n";
590
+
591
+ $output .= "<div class='jr-insta-datacontainer'>\n";
592
+
593
+ if ( $all_metas['jr_insta_timestamp'][0] && in_array( 'time', $args['description'] ) ) {
594
+ $time = human_time_diff( $all_metas['jr_insta_timestamp'][0] );
595
+ $output .= "<span class='jr-insta-time'>{$time} ago</span>\n";
596
+ }
597
+
598
+ if ( in_array( 'username', $args['description'] ) ) {
599
+ $output .= "<span class='jr-insta-username'>by <a rel='nofollow' target='_blank' href='http://instagram.com/{$all_metas['jr_insta_username'][0]}'>{$all_metas['jr_insta_username'][0]}</a></span>\n";
600
+ }
601
+
602
+ if ( $caption != '' && in_array( 'caption', $args['description'] ) ) {
603
+ $caption = preg_replace( '/@([a-z0-9_]+)/i', '&nbsp;<a href="http://instagram.com/$1" rel="nofollow" target="_blank">@$1</a>&nbsp;', $caption );
604
+ $output .= "<span class='jr-insta-caption'>{$caption}</span>\n";
605
+ }
606
+
607
+ $output .= "</div>\n";
608
+
609
+ $output .= "</div>\n";
610
+ }
611
+
612
+ $output .= "</li>";
613
+
614
+ // Template : Thumbnails no text
615
+ } elseif ( $template == 'thumbs' ) {
616
+
617
+ $output .= "<li>";
618
+ $output .= $image_output;
619
+ $output .= "</li>";
620
+
621
+ } else {
622
+
623
+ $output .= 'This template does not exist!';
624
+ }
625
+
626
+ return $output;
627
+ }
628
+
629
  /**
630
  * Stores the fetched data from instagram in WordPress DB using transients
631
  *
632
+ * @param string $username Instagram Username to fetch images from
633
+ * @param string $cache_hours Cache hours for transient
634
+ * @param string $nr_images Nr of images to fetch from instagram
635
  *
636
  * @return array of localy saved instagram data
637
  */
638
+ private function instagram_data( $username, $cache_hours, $nr_images ) {
639
 
640
+ $opt_name = 'jr_insta_' . md5( $username );
641
+ $instaData = get_transient( $opt_name );
642
+ $user_opt = (array) get_option( $opt_name );
643
+
644
+ if ( false === $instaData || $user_opt['username'] != $username || $user_opt['cache_hours'] != $cache_hours || $user_opt['nr_images'] != $nr_images ) {
645
+
 
 
 
 
 
646
  $instaData = array();
647
+ $user_options = compact( 'username', 'cache_hours', 'nr_images' );
 
 
 
648
 
649
+ $json = wp_remote_get( 'http://instagram.com/' . $username, array( 'sslverify' => false, 'timeout' => 60 ) );
650
 
651
  if ( $json['response']['code'] == 200 ) {
652
+
653
+ $json = $json['body'];
654
+ $json = strstr( $json, 'window._sharedData = ' );
655
+ $json = str_replace( 'window._sharedData = ', '', $json );
656
 
657
  // Compatibility for version of php where strstr() doesnt accept third parameter
658
+ if ( version_compare( PHP_VERSION, '5.3.10', '>=' ) ) {
659
+ $json = substr( $json, 0, strpos( $json, '</script>' ) );
660
  } else {
661
  $json = strstr( $json, '</script>', true );
662
  }
663
 
664
+ $json = rtrim( $json, ';' );
665
 
666
  // Function json_last_error() is not available before PHP * 5.3.0 version
667
  if ( function_exists( 'json_last_error' ) ) {
668
+
669
  ( $results = json_decode( $json, true ) ) && json_last_error() == JSON_ERROR_NONE;
670
+
671
  } else {
672
 
673
  $results = json_decode( $json, true );
674
  }
675
+
676
  if ( ( $results ) && is_array( $results ) ) {
677
+
678
+ foreach ( $results['entry_data']['UserProfile'][0]['userMedia'] as $current => $result ) {
679
+
680
+ if ( $result['type'] != 'image' ) {
681
+ $nr_images++;
682
+ continue;
683
+ }
684
+
685
+ if ( $current >= $nr_images ) {
686
+ break;
687
+ }
688
+
689
+ $image_data['username'] = $result['user']['username'];
690
+ $image_data['url'] = $result['images']['standard_resolution']['url'];
691
+ $image_data['caption'] = $this->sanitize( $result['caption']['text'] );
692
+ $image_data['id'] = $result['id'];
693
+ $image_data['link'] = $result['link'];
694
+ $image_data['popularity'] = (int) ( $result['comments']['count'] ) + ( $result['likes']['count'] );
695
+ $image_data['timestamp'] = $result['created_time'];
696
+
697
+ if ( isset( $user_opt['saved_images'][$image_data['id']] ) ) {
698
+
699
+ if ( is_string( get_post_status( $user_opt['saved_images'][$image_data['id']] ) ) ) {
700
 
701
+ $this->update_wp_attachment( $user_opt['saved_images'][$image_data['id']], $image_data );
702
 
703
+ $instaData[$image_data['id']] = $user_opt['saved_images'][$image_data['id']];
704
 
705
+ } else {
 
 
 
 
 
 
 
 
 
706
 
707
+ $user_opt['deleted_images'][$image_data['id']] = $image_data['url'];
708
+ }
709
+
710
+ } else {
711
+
712
+ $id = $this->save_wp_attachment( $image_data );
713
+
714
+ if ( $id ) {
715
+
716
+ $user_opt['saved_images'][$image_data['id']] = $id;
717
+
718
+ $instaData[$image_data['id']] = $id;
719
+ }
720
+
721
+ } // end isset $saved_images
722
 
723
  } // end -> foreach
724
+
725
  } // end -> ( $results ) && is_array( $results ) )
726
+
727
  } // end -> $json['response']['code'] === 200 )
728
+
729
+ update_option( $opt_name, array_merge( $user_options, $user_opt ) );
730
+
731
  if ( $instaData ) {
732
  set_transient( $opt_name, $instaData, $cache_hours * 60 * 60 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733
  }
734
+
735
+ } // end -> false === $instaData
736
 
737
  return $instaData;
738
  }
739
 
740
  /**
741
+ * Updates attachment using the id
742
+ * @param int $attachment_ID
743
+ * @param array image_data
744
+ * @return void
 
 
 
 
 
745
  */
746
+ private function update_wp_attachment( $attachment_ID, $image_data ) {
747
 
748
+ update_post_meta( $attachment_ID, 'jr_insta_popularity', $image_data['popularity'] );
 
 
 
 
 
 
 
 
 
749
  }
750
+
751
  /**
752
  * Save Instagram images to upload folder and ads to media.
753
  * If the upload fails it returns the remote image url.
754
+ *
755
  * @param string $url Url of image to download
756
+ * @param string $file File path for image
757
  *
758
  * @return string $url Url to image
759
  */
760
+ private function save_wp_attachment( $image_data ) {
 
 
 
761
 
762
+ $image_info = pathinfo( $image_data['url'] );
 
 
763
 
764
+ if ( !in_array( $image_info['extension'], array( 'jpg', 'jpe', 'jpeg', 'gif', 'png' ) ) ) {
765
+ return false;
 
 
 
 
 
766
  }
767
 
768
+ // These files need to be included as dependencies when on the front end.
769
+ if ( !is_admin() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
771
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
772
+ require_once( ABSPATH . 'wp-admin/includes/media.php' );
 
 
773
  }
 
 
774
 
775
+ $tmp = download_url( $image_data['url'] );
776
+
777
+ $file_array = array();
778
+ $file_array['name'] = $image_info['basename'];
779
+ $file_array['tmp_name'] = $tmp;
780
+
781
+ // If error storing temporarily, unlink
782
+ if ( is_wp_error( $tmp ) ) {
783
+ @unlink( $file_array['tmp_name'] );
784
+ $file_array['tmp_name'] = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
785
  }
786
+
787
+ $id = media_handle_sideload( $file_array, 0, NULL, array(
788
+ 'post_excerpt' => $image_data['caption']
789
+ ) );
790
+
791
+ // If error storing permanently, unlink
792
+ if ( is_wp_error( $id ) ) {
793
+ @unlink( $file_array['tmp_name'] );
794
+ return $id;
 
795
  }
796
 
797
+ unset( $image_data['caption'] );
798
+
799
+ foreach ( $image_data as $meta_key => $meta_value ) {
800
+ update_post_meta( $id, 'jr_insta_' . $meta_key, $meta_value );
801
+ }
802
 
803
+ return $id;
804
+ }
805
+
806
+
807
  /**
808
  * Sanitize 4-byte UTF8 chars; no full utf8mb4 support in drupal7+mysql stack.
809
  * This solution runs in O(n) time BUT assumes that all incoming input is
813
  *
814
  * @return the sanitized input
815
  */
816
+ private function sanitize( $input ) {
817
+
818
+ $input = trim( str_replace( '#', '', $input ) );
819
+
820
+ if ( !empty( $input ) ) {
821
+ $utf8_2byte = 0xC0 /*1100 0000*/ ;
822
+ $utf8_2byte_bmask = 0xE0 /*1110 0000*/ ;
823
+ $utf8_3byte = 0xE0 /*1110 0000*/ ;
824
+ $utf8_3byte_bmask = 0XF0 /*1111 0000*/ ;
825
+ $utf8_4byte = 0xF0 /*1111 0000*/ ;
826
+ $utf8_4byte_bmask = 0xF8 /*1111 1000*/ ;
827
+
828
+ $sanitized = "";
829
+ $len = strlen( $input );
830
+ for ( $i = 0; $i < $len; ++$i ) {
831
+
832
+ $mb_char = $input[$i]; // Potentially a multibyte sequence
833
+ $byte = ord( $mb_char );
834
+
835
+ if ( ( $byte & $utf8_2byte_bmask ) == $utf8_2byte ) {
836
+ $mb_char .= $input[++$i];
837
+ } else if ( ( $byte & $utf8_3byte_bmask ) == $utf8_3byte ) {
838
+ $mb_char .= $input[++$i];
839
+ $mb_char .= $input[++$i];
840
+ } else if ( ( $byte & $utf8_4byte_bmask ) == $utf8_4byte ) {
841
+ // Replace with ? to avoid MySQL exception
842
+ $mb_char = '';
843
+ $i += 3;
844
+ }
845
+
846
+ $sanitized .= $mb_char;
847
+ }
848
+
849
+ $input = $sanitized;
850
  }
851
+
852
+ return $input;
 
 
 
853
  }
854
+
855
+ } // end of class JR_InstagramSlider
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: jetonr
3
  Tags: instagram, slider, widget, images
4
  Donate link: http://goo.gl/RZiu34
5
  Requires at least: 3.5
6
- Tested up to: 3.9.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -12,17 +12,17 @@ Instagram Slider Widget is a responsive slider widget that shows 20 latest image
12
  == Description ==
13
  * Instagram Slider Widget is a responsive slider widget that shows 20 latest images from a public instagram user.
14
  = Features =
15
- * Images are stored in your wordpress upload folder.
16
  * Display Images in Slider or Thumbnails
17
  * No Api Key Needed
18
- * Link images to user profile, image url, locally saved image or custom url
19
- * Option to Randomise order of instagram images
20
- * Option to insert images into WordPress Media Library
21
- * For more info visit http://jrwebstudio.com/
22
 
23
  = If you liked this plugin. Please rate it =
24
 
25
  == Installation ==
 
26
  = Installation =
27
  1. Upload `instagram-slider-widget` to the `/wp-content/plugins/` directory
28
  2. Activate the plugin through the \'Plugins\' menu in WordPress
@@ -33,12 +33,21 @@ Instagram Slider Widget is a responsive slider widget that shows 20 latest image
33
  * PHP 5.2.0 or later
34
  * Wordpress 3.5 or later
35
 
 
 
 
 
 
 
36
  == Screenshots ==
37
  1. Frontend Widget Slider
38
  2. Frontend Widget Thumbs
39
  3. Backend Configuration
40
 
41
  == Changelog ==
 
 
 
42
  = 1.1.3 =
43
  * bug fix not working after wordpresss update
44
  * Added multisite support
3
  Tags: instagram, slider, widget, images
4
  Donate link: http://goo.gl/RZiu34
5
  Requires at least: 3.5
6
+ Tested up to: 4.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
12
  == Description ==
13
  * Instagram Slider Widget is a responsive slider widget that shows 20 latest images from a public instagram user.
14
  = Features =
15
+ * Images from instagram are imported as wordpress attachments
16
  * Display Images in Slider or Thumbnails
17
  * No Api Key Needed
18
+ * Link images to user profile, image url, locally saved image, attachment url, custom url or none
19
+ * Sort images Randomily, Popularity, Date
20
+ * For more info visit http://instagram.jrwebstudio.com
 
21
 
22
  = If you liked this plugin. Please rate it =
23
 
24
  == Installation ==
25
+
26
  = Installation =
27
  1. Upload `instagram-slider-widget` to the `/wp-content/plugins/` directory
28
  2. Activate the plugin through the \'Plugins\' menu in WordPress
33
  * PHP 5.2.0 or later
34
  * Wordpress 3.5 or later
35
 
36
+ == Frequently asked questions ==
37
+
38
+ = Where can I get support =
39
+ I will try to respond on wordpress.org asap but for faster reposnse use the link bellow
40
+ * http://support.jrwebstudio.com/product/instagram-slider-widget/
41
+
42
  == Screenshots ==
43
  1. Frontend Widget Slider
44
  2. Frontend Widget Thumbs
45
  3. Backend Configuration
46
 
47
  == Changelog ==
48
+ = 1.2.0 =
49
+ * Full Rewritte of the plugin
50
+
51
  = 1.1.3 =
52
  * bug fix not working after wordpresss update
53
  * Added multisite support
views/slider-overlay.php DELETED
@@ -1,62 +0,0 @@
1
- <script type="text/javascript">
2
- jQuery(document).ready(function($) {
3
- $('.pllexislider').pllexislider({
4
- animation: "fade",
5
- directionNav: false,
6
- start: function(slider){
7
- slider.hover(
8
- function () {
9
- slider.find('.jr-insta-datacontainer, .pllex-control-nav').stop(true,true).fadeIn();
10
- },
11
- function () {
12
- slider.find('.jr-insta-datacontainer, .pllex-control-nav').stop(true,true).fadeOut();
13
- }
14
- );
15
- }
16
- });
17
- });
18
- </script>
19
- <div class="pllexislider overlay">
20
- <ul class="no-bullet slides">
21
- <?php
22
- if ( isset($data_arr) && is_array($data_arr) ) {
23
- foreach ($data_arr as $data) {
24
- foreach ( $data as $k => $v) {
25
- $$k = $v;
26
- }
27
-
28
- /* Set link to User Instagram Profile */
29
- if ( $link_to && ( 'user_url' == $link_to ) ) {
30
- $link = $user_url;
31
- }
32
-
33
- /* Set link to Locally saved image */
34
- if ( $link_to && 'local_image_url' == $link_to ) {
35
- $link = $image;
36
- }
37
-
38
- /* Set link to Custom URL */
39
- if ( ( $link_to && 'custom_url' == $link_to ) && ( isset( $custom_url ) && $custom_url != '' ) ) {
40
- $link = $custom_url;
41
- }
42
-
43
- echo '<li>'. "\n";
44
- echo '<a target="_blank" href="'.$link.'"><img src="'.$image.'" alt="'.$text.'"></a>' . "\n";
45
- echo '<div class="jr-insta-wrap">' . "\n";
46
- echo '<div class="jr-insta-datacontainer">' . "\n";
47
- if ( $created_time ) {
48
- echo '<span class="jr-insta-time">'. human_time_diff( $created_time ) . ' ago</span>' . "\n";
49
- }
50
- echo '<span class="jr-insta-username">by <a target="_blank" href="'. $user_url .'">'. $user_name .'</a></span>' . "\n";
51
- if ($text) {
52
- echo '<span class="jr-insta-desc">'.$text.'</span>' . "\n";
53
- }
54
- echo '</div>' . "\n";
55
- echo '</div>' . "\n";
56
- echo '</li>' . "\n";
57
-
58
- }
59
- }
60
- ?>
61
- </ul>
62
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/slider.php DELETED
@@ -1,50 +0,0 @@
1
- <script type="text/javascript">
2
- jQuery(document).ready(function($) {
3
- $('.pllexislider').pllexislider({
4
- animation: "slide",
5
- directionNav: false,
6
- });
7
- });
8
- </script>
9
- <div class="pllexislider normal">
10
- <ul class="no-bullet slides">
11
- <?php
12
- if ( isset($data_arr) && is_array($data_arr) ) {
13
- foreach ($data_arr as $data) {
14
- foreach ( $data as $k => $v) {
15
- $$k = $v;
16
- }
17
-
18
- /* Set link to User Instagram Profile */
19
- if ( $link_to && ( 'user_url' == $link_to ) ) {
20
- $link = $user_url;
21
- }
22
-
23
- /* Set link to Locally saved image */
24
- if ( $link_to && 'local_image_url' == $link_to ) {
25
- $link = $image;
26
- }
27
-
28
- /* Set link to Custom URL */
29
- if ( ( $link_to && 'custom_url' == $link_to ) && ( isset( $custom_url ) && $custom_url != '' ) ) {
30
- $link = $custom_url;
31
- }
32
-
33
- echo '<li>'. "\n";
34
- echo '<a target="_blank" href="'.$link.'"><img src="'.$image.'" alt="'.$text.'"></a>' . "\n";
35
- if ( $created_time ) {
36
- echo '<div class="instatime">'. human_time_diff( $created_time ) . ' ago</div>' . "\n";
37
- }
38
- echo '<div class="instadescription">' . "\n";
39
- echo '<p>by <a href="'. $user_url .'">'. $user_name .'</a></p>' . "\n";
40
- if ($text) {
41
- echo '<p>'.$text.'</p>' . "\n";
42
- }
43
- echo '</div>' . "\n";
44
- echo '</li>' . "\n";
45
-
46
- }
47
- }
48
- ?>
49
- </ul>
50
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/thumbs.php DELETED
@@ -1,33 +0,0 @@
1
-
2
- <div class="instag">
3
- <ul class="thumbnails no-bullet">
4
- <?php
5
- if ( isset( $data_arr ) && is_array( $data_arr ) ) {
6
- foreach ( $data_arr as $data ) {
7
- foreach ( $data as $k => $v ) {
8
- $$k = $v;
9
- }
10
-
11
- /* Set link to User Instagram Profile */
12
- if ( $link_to && 'user_url' == $link_to ) {
13
- $link = $user_url;
14
- }
15
-
16
- /* Set link to Locally saved image */
17
- if ( $link_to && 'local_image_url' == $link_to ) {
18
- $link = $image;
19
- }
20
-
21
- /* Set link to Custom URL */
22
- if ( ( $link_to && 'custom_url' == $link_to ) && ( isset( $custom_url ) && $custom_url != '' ) ) {
23
- $link = $custom_url;
24
- }
25
-
26
- echo '<li>'. "\n";
27
- echo '<a target="_blank" href="' . $link . '"><img src="' . $image . '" alt="' . $text . '"></a>' . "\n";
28
- echo '</li>' . "\n";
29
- }
30
- }
31
- ?>
32
- </ul>
33
- </div>