WP Instagram Widget - Version 2.0.0

Version Description

  • Ability to track tags / hashtags instead of just usernames (e.g. #cheese)
  • New filter for custom link class
  • Bundle German language (props jensteichert)
  • Other minor fixes and formatting
Download this release

Release Info

Developer scottsweb
Plugin Icon 128x128 WP Instagram Widget
Version 2.0.0
Comparing to
See all releases

Version 2.0.0

assets/languages/wp-instagram-widget-de_DE.mo ADDED
Binary file
assets/languages/wp-instagram-widget-de_DE.po ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: WP Instagram Widget\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2015-09-25 08:13-0000\n"
6
+ "PO-Revision-Date: 2017-06-27 20:45+0200\n"
7
+ "Language-Team: @scottsweb <translate@scott.ee>\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
12
+ "X-Poedit-KeywordsList: __;_e;_x;esc_html_e;esc_html__;esc_attr_e;esc_attr__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_x:1,2c;_n:1,2;_n_noop:1,2;__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
13
+ "X-Poedit-Basepath: ../..\n"
14
+ "X-Poedit-SourceCharset: utf-8\n"
15
+ "X-Generator: Poedit 2.0.2\n"
16
+ "Last-Translator: \n"
17
+ "Language: de\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: wp-instagram-widget.php:53 wp-instagram-widget.php:117
21
+ msgid "Instagram"
22
+ msgstr "Instagram"
23
+
24
+ #: wp-instagram-widget.php:54
25
+ msgid "Displays your latest Instagram photos"
26
+ msgstr "Zeig deine neusten Instagram Bilder an"
27
+
28
+ #: wp-instagram-widget.php:117
29
+ msgid "Follow Me!"
30
+ msgstr "Folg mir!"
31
+
32
+ #: wp-instagram-widget.php:125
33
+ msgid "Title"
34
+ msgstr "Titel"
35
+
36
+ #: wp-instagram-widget.php:126
37
+ msgid "Username"
38
+ msgstr "Nutzername"
39
+
40
+ #: wp-instagram-widget.php:127
41
+ msgid "Number of photos"
42
+ msgstr "Anzahl der Bilder"
43
+
44
+ #: wp-instagram-widget.php:128
45
+ msgid "Photo size"
46
+ msgstr "Bild Größe"
47
+
48
+ #: wp-instagram-widget.php:130
49
+ msgid "Thumbnail"
50
+ msgstr "Vorschaubild"
51
+
52
+ #: wp-instagram-widget.php:131
53
+ msgid "Small"
54
+ msgstr "Klein"
55
+
56
+ #: wp-instagram-widget.php:132
57
+ msgid "Large"
58
+ msgstr "Groß"
59
+
60
+ #: wp-instagram-widget.php:133
61
+ msgid "Original"
62
+ msgstr "Original"
63
+
64
+ #: wp-instagram-widget.php:136
65
+ msgid "Open links in"
66
+ msgstr "Links öffnen in"
67
+
68
+ #: wp-instagram-widget.php:138
69
+ msgid "Current window (_self)"
70
+ msgstr "Aktuelles Fenster (_self)"
71
+
72
+ #: wp-instagram-widget.php:139
73
+ msgid "New window (_blank)"
74
+ msgstr "Neues Fenster (_blank)"
75
+
76
+ #: wp-instagram-widget.php:142
77
+ msgid "Link text"
78
+ msgstr "Link Text"
79
+
80
+ #: wp-instagram-widget.php:169
81
+ msgid "Unable to communicate with Instagram."
82
+ msgstr "Die Kommunikation mit Instagram ist fehlgeschlagen."
83
+
84
+ #: wp-instagram-widget.php:172
85
+ msgid "Instagram did not return a 200."
86
+ msgstr "Instagram hat keinen 200 zurückgegeben."
87
+
88
+ #: wp-instagram-widget.php:179 wp-instagram-widget.php:184
89
+ #: wp-instagram-widget.php:188
90
+ msgid "Instagram has returned invalid data."
91
+ msgstr "Instagram hat falsche Daten zurückgegeben."
92
+
93
+ #: wp-instagram-widget.php:206
94
+ msgid "Instagram Image"
95
+ msgstr "Instagram Bild"
96
+
97
+ #: wp-instagram-widget.php:239
98
+ msgid "Instagram did not return any images."
99
+ msgstr "Instagram hat keine Bilder zurückgegeben."
assets/languages/wp-instagram-widget-en_GB.mo ADDED
Binary file
assets/languages/wp-instagram-widget-en_GB.po ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: WP Instagram Widget\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2017-09-21 10:19+0100\n"
6
+ "PO-Revision-Date: 2017-09-21 10:19+0100\n"
7
+ "Last-Translator: Scott Evans @scottsweb <translate@scott.ee>\n"
8
+ "Language-Team: @scottsweb <translate@scott.ee>\n"
9
+ "Language: en_GB\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
14
+ "X-Poedit-KeywordsList: __;_e;_x;esc_html_e;esc_html__;esc_attr_e;esc_attr__;"
15
+ "_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_x:1,2c;_n:1,2;_n_noop:1,2;"
16
+ "__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
17
+ "X-Poedit-Basepath: ../..\n"
18
+ "X-Poedit-SourceCharset: utf-8\n"
19
+ "X-Generator: Poedit 2.0.1\n"
20
+ "X-Poedit-SearchPath-0: .\n"
21
+
22
+ #: wp-instagram-widget.php:53 wp-instagram-widget.php:138
23
+ msgid "Instagram"
24
+ msgstr ""
25
+
26
+ #: wp-instagram-widget.php:56
27
+ msgid "Displays your latest Instagram photos"
28
+ msgstr ""
29
+
30
+ #: wp-instagram-widget.php:138
31
+ msgid "Follow Me!"
32
+ msgstr ""
33
+
34
+ #: wp-instagram-widget.php:146
35
+ msgid "Title"
36
+ msgstr ""
37
+
38
+ #: wp-instagram-widget.php:147
39
+ msgid "@username or #tag"
40
+ msgstr ""
41
+
42
+ #: wp-instagram-widget.php:148
43
+ msgid "Number of photos"
44
+ msgstr ""
45
+
46
+ #: wp-instagram-widget.php:149
47
+ msgid "Photo size"
48
+ msgstr ""
49
+
50
+ #: wp-instagram-widget.php:151
51
+ msgid "Thumbnail"
52
+ msgstr ""
53
+
54
+ #: wp-instagram-widget.php:152
55
+ msgid "Small"
56
+ msgstr ""
57
+
58
+ #: wp-instagram-widget.php:153
59
+ msgid "Large"
60
+ msgstr ""
61
+
62
+ #: wp-instagram-widget.php:154
63
+ msgid "Original"
64
+ msgstr ""
65
+
66
+ #: wp-instagram-widget.php:157
67
+ msgid "Open links in"
68
+ msgstr ""
69
+
70
+ #: wp-instagram-widget.php:159
71
+ msgid "Current window (_self)"
72
+ msgstr ""
73
+
74
+ #: wp-instagram-widget.php:160
75
+ msgid "New window (_blank)"
76
+ msgstr ""
77
+
78
+ #: wp-instagram-widget.php:163
79
+ msgid "Link text"
80
+ msgstr ""
81
+
82
+ #: wp-instagram-widget.php:199
83
+ msgid "Unable to communicate with Instagram."
84
+ msgstr ""
85
+
86
+ #: wp-instagram-widget.php:203
87
+ msgid "Instagram did not return a 200."
88
+ msgstr ""
89
+
90
+ #: wp-instagram-widget.php:211 wp-instagram-widget.php:219
91
+ #: wp-instagram-widget.php:223
92
+ msgid "Instagram has returned invalid data."
93
+ msgstr ""
94
+
95
+ #: wp-instagram-widget.php:254
96
+ msgid "Instagram Image"
97
+ msgstr ""
98
+
99
+ #: wp-instagram-widget.php:286
100
+ msgid "Instagram did not return any images."
101
+ msgstr ""
index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /** silence is golden **/
readme.md ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![WP Instagram Widget](http://cloud.scott.ee/images/wp-instagram-widget.png)
2
+
3
+ # WP Instagram Widget
4
+
5
+ * Status: ✅ Active
6
+ * Contributors: [@scottsweb](http://twitter.com/scottsweb)
7
+ * Description: WP Instagram widget is a no fuss WordPress widget to showcase your latest Instagram pics.
8
+ * Author: [Scott Evans](http://scott.ee)
9
+ * Author URI: [http://scott.ee](http://scott.ee)
10
+ * License: GNU General Public License v2.0
11
+ * License URI: [http://www.gnu.org/licenses/gpl-2.0.html](http://www.gnu.org/licenses/gpl-2.0.html)
12
+
13
+ ## About
14
+
15
+ WP Instagram widget is a no fuss WordPress widget to showcase your latest Instagram pics. It does not require you to provide your login details or sign in via oAuth.
16
+
17
+ The widget is built with the following philosophy:
18
+
19
+ * Use sensible and simple markup
20
+ * Provide no styles/css - it is up to you to style the widget to your theme and taste
21
+ * Cache where possible - filters are provided to adjust cache timings
22
+ * Require little setup - avoid oAuth for example
23
+
24
+ ## Installation
25
+
26
+ To install this plugin:
27
+
28
+ * Upload the `wp-instagram-widget` folder to the `/wp-content/plugins/` directory
29
+ * Activate the plugin through the 'Plugins' menu in WordPress
30
+ * That's it!
31
+
32
+ Alternatively you can search for the plugin from your WordPress dashboard and install from there.
33
+
34
+ Visit [WordPress.org for a comprehensive guide](http://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation) on in how to install WordPress plugins.
35
+
36
+ ## Hooks & Filters
37
+
38
+ The plugin has five filters. The first allows you adjust that cache time for retrieving the images from Instagram:
39
+
40
+ ```
41
+ add_filter('null_instagram_cache_time', 'my_cache_time');
42
+
43
+ function my_cache_time() {
44
+ return HOUR_IN_SECONDS;
45
+ }
46
+ ```
47
+
48
+ The second allows you to filter video results from the widget:
49
+
50
+ ```
51
+ add_filter('wpiw_images_only', '__return_true');
52
+ ```
53
+
54
+ The rest allow you to add custom classes to each list item, link or image:
55
+
56
+ ```
57
+ add_filter( 'wpiw_item_class', 'my_instagram_class' );
58
+ add_filter( 'wpiw_a_class', 'my_instagram_class' );
59
+ add_filter( 'wpiw_img_class', 'my_instagram_class' );
60
+ add_filter( 'wpiw_linka_class', 'my_instagram_class' );
61
+
62
+ function my_instagram_class( $classes ) {
63
+ $classes = "instagram-image";
64
+ return $classes;
65
+ }
66
+ ```
67
+
68
+ In version 1.3 you also have two new hooks for adding custom output before and after the widget:
69
+
70
+ ```
71
+ wpiw_before_widget
72
+ wpiw_after_widget
73
+ ```
74
+
75
+ In version 1.4 and above you can also customise the image loop completely by creating a `parts/wp-instagram-widget.php` file in your theme.
76
+
77
+ In version 1.9.6 you can now use a filter to change the location of your custom template part: `wpiw_template_part`.
78
+
79
+ ## Frequently Asked Questions
80
+
81
+ ...
82
+
83
+ ## Changelog
84
+
85
+ ####2.0.0
86
+ * Ability to track tags / hashtags instead of just usernames (e.g. #cheese)
87
+ * New filter for custom link class
88
+ * Bundle German language (props jensteichert)
89
+ * Other minor fixes and formatting
90
+
91
+ ####1.9.8
92
+ * Return more items when using filter for images only
93
+
94
+ ####1.9.7
95
+ * Fix double trailing slash on custom text link
96
+
97
+ ####1.9.6
98
+ * Trailing slash all URLs to support Instagram app on iOS
99
+ * Support selective refresh in 4.5
100
+ * New filter for `wpiw_template_part`
101
+
102
+ ####1.9.5
103
+ * Another fix for image URL handling, I think we have all the edge cases now!
104
+
105
+ ####1.9.4
106
+ * IMPORTANT: You must be on WordPress 4.4 or later to upgrade to this version of the plugin. This fixes a bug with PHP versions < 5.4.7. If you are on a version of WordPress older than 4.4 and you notice images are not loading then I recommend rolling your version of the widget back to this version: https://github.com/scottsweb/wp-instagram-widget/blob/c66550eded59bd51f508f304a85a3e031ac4044c/wp-instagram-widget.php
107
+
108
+ ####1.9.3
109
+ * Fix issues introduced in the last version (apologies). Certain CDN URLs are still in use
110
+
111
+ ####1.9.2
112
+ * Better handling of all image and video image URLs props @thegallagher
113
+
114
+ ####1.9.1
115
+ * Fix bug with some image URLs
116
+
117
+ ####1.9
118
+ * WordPress.com VIP checked
119
+ * Updated CDN matching to ensure correct image sizes are served at all times
120
+ * Shortened the transient key - should mean we bump into the character limit less often
121
+ * Remove use of `extract`
122
+
123
+ ####1.8.1
124
+ * Apologies for all the recent updates, all good things though!
125
+ * Update plugin text domain ready for translate.wordpress.org
126
+ * Introduce an 'original' image size if you want to use non-square originals
127
+ * Introduce new filter for `<ul>` class `wpiw_list_class`
128
+
129
+ ####1.8
130
+ * Bring back image captions
131
+ * Fix small PHP error in 1.7
132
+
133
+ ####1.7
134
+ * Bring back image sizes
135
+ * Use thumbnails that are square (originals are in the data returned and can be used)
136
+ * Remove @ from usernames
137
+
138
+ ####1.6
139
+ * Compatibility with 4.3
140
+
141
+ ####1.5.1
142
+ * Invalidate old transients
143
+
144
+ ####1.5
145
+ * Remove null framework support
146
+ * Fix breaking change by Instagram whilst maintaining old style support
147
+ * Remove thumbnail size option
148
+
149
+ ####1.4
150
+ * Introduce class filters
151
+ * Only set a transient if images are returned
152
+ * Optional template part for complete output control
153
+
154
+ ####1.3.1
155
+ * Force lowercase usernames
156
+ * Correct hook name
157
+
158
+ ####1.3
159
+ * Option to open links in new window
160
+ * Support for video items (with filter to disable this)
161
+ * New actions for adding custom output to the widget
162
+ * Support for https://
163
+ * Correctly escape attributes
164
+
165
+ ####1.2.1
166
+ * Change transient name due to data change
167
+
168
+ ####1.2
169
+ * Better error handling
170
+ * Encode emoji as they cause transient issues
171
+
172
+ ####1.1
173
+ * Fix issue with Instagram feed
174
+ * Add composer.json
175
+
176
+ ####1.0
177
+ * Initial release
178
+
readme.txt ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === WP Instagram Widget ===
2
+ Contributors: scottsweb, codeforthepeople
3
+ Tags: instagram, widget, photos, photography, hipster, sidebar, widgets, simple
4
+ Requires at least: 4.4
5
+ Tested up to: 4.8.2
6
+ Stable tag: 2.0.0
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ WP Instagram widget is a no fuss WordPress widget to showcase your latest Instagram pics.
11
+
12
+ == Description ==
13
+
14
+ WP Instagram widget is a no fuss WordPress widget to showcase your latest Instagram pics. It does not require you to provide your login details or sign in via oAuth.
15
+
16
+ The widget is built with the following philosophy:
17
+
18
+ * Use sensible and simple markup
19
+ * Provide no styles/css - it is up to you to style the widget to your theme and taste
20
+ * Cache where possible - filters are provided to adjust cache timings
21
+ * Require little setup - avoid oAuth for example
22
+
23
+ [a plugin by Scott Evans](http://scott.ee/ "WordPress designer and developer")
24
+
25
+ == Installation ==
26
+
27
+ To install this plugin:
28
+
29
+ 1. Upload the `wp-instagram-widget` folder to the `/wp-content/plugins/` directory
30
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
31
+ 1. That's it!
32
+
33
+ Alternatively you can search for the plugin from your WordPress dashboard and install from there.
34
+
35
+ == Frequently Asked Questions ==
36
+
37
+ = Hooks & Filters =
38
+
39
+ The plugin has five filters. The first allows you adjust that cache time for retrieving the images from Instagram:
40
+
41
+ `add_filter('null_instagram_cache_time', 'my_cache_time');
42
+
43
+ function my_cache_time() {
44
+ return HOUR_IN_SECONDS;
45
+ }
46
+ `
47
+
48
+ The second allows you to filter video results from the widget:
49
+
50
+ `add_filter('wpiw_images_only', '__return_true');`
51
+
52
+ The rest allow you to add custom classes to each list item, link or image:
53
+
54
+ `add_filter( 'wpiw_item_class', 'my_instagram_class' );
55
+ add_filter( 'wpiw_a_class', 'my_instagram_class' );
56
+ add_filter( 'wpiw_img_class', 'my_instagram_class' );
57
+ add_filter( 'wpiw_linka_class', 'my_instagram_class' );
58
+
59
+ function my_instagram_class( $classes ) {
60
+ $classes = "instagram-image";
61
+ return $classes;
62
+ }
63
+ `
64
+
65
+ In version 1.3 you also have two new hooks for adding custom output before and after the widget:
66
+
67
+ `wpiw_before_widget`
68
+ `wpiw_after_widget`
69
+
70
+ In version 1.4 and above you can also customise the image loop completely by creating a `parts/wp-instagram-widget.php` file in your theme.
71
+
72
+ In version 1.9.6 you can now use a filter to change the location of your custom template part: `wpiw_template_part`.
73
+
74
+ == Screenshots ==
75
+
76
+ 1. Instagram widget on the front end
77
+ 2. Instagram widget in the theme customiser
78
+
79
+ == Changelog ==
80
+
81
+ = 2.0.0 =
82
+ * Ability to track tags / hashtags instead of just usernames (e.g. #cheese)
83
+ * New filter for custom link class
84
+ * Bundle German language (props jensteichert)
85
+ * Other minor fixes and formatting
86
+
87
+ = 1.9.8 =
88
+ * Return more items when using filter for images only
89
+
90
+ = 1.9.7 =
91
+ * Fix double trailing slash on custom text link
92
+
93
+ = 1.9.6 =
94
+ * Trailing slash all URLs to support Instagram app on iOS
95
+ * Support selective refresh in 4.5
96
+ * New filter for `wpiw_template_part`
97
+
98
+ = 1.9.5 =
99
+ * Another fix for image URL handling, I think we have all the edge cases now!
100
+
101
+ = 1.9.4 =
102
+ * IMPORTANT: You must be on WordPress 4.4 or later to upgrade to this version of the plugin. This fixes a bug with PHP versions < 5.4.7. If you are on a version of WordPress older than 4.4 and you notice images are not loading then I recommend rolling your version of the widget back to this version: https://github.com/scottsweb/wp-instagram-widget/blob/c66550eded59bd51f508f304a85a3e031ac4044c/wp-instagram-widget.php
103
+
104
+ = 1.9.3 =
105
+ * Fix issues introduced in the last version (apologies). Certain CDN URLs are still in use
106
+
107
+ = 1.9.2 =
108
+ * Better handling of all image and video image URLs props @thegallagher
109
+
110
+ = 1.9.1 =
111
+ * Fix bug with some image URLs
112
+
113
+ = 1.9 =
114
+ * WordPress.com VIP checked
115
+ * Updated CDN matching to ensure correct image sizes are served at all times
116
+ * Shortened the transient key - should mean we bump into the character limit less often
117
+ * Remove use of `extract`
118
+
119
+ = 1.8.1 =
120
+ * Apologies for all the recent updates, all good things though!
121
+ * Update plugin text domain ready for translate.wordpress.org
122
+ * Introduce an 'original' image size if you want to use non-square originals
123
+ * Introduce new filter for <ul> class `wpiw_list_class`
124
+
125
+ = 1.8 =
126
+ * Bring back image captions
127
+ * Fix small PHP error in 1.7
128
+
129
+ = 1.7 =
130
+ * Bring back image sizes
131
+ * Use thumbnails that are square (originals are in the data returned and can be used)
132
+ * Remove @ from usernames
133
+
134
+ = 1.6 =
135
+ * Compatibility with 4.3
136
+
137
+ = 1.5.1 =
138
+ * Invalidate old transients
139
+
140
+ = 1.5 =
141
+ * Remove null framework support
142
+ * Fix breaking change by Instagram whilst maintaining old style support
143
+ * Remove thumbnail size option
144
+
145
+ = 1.4 =
146
+ * Introduce class filters
147
+ * Only set a transient if images are returned
148
+ * Optional template part for complete output control
149
+
150
+ = 1.3.1 =
151
+ * Force lowercase usernames
152
+ * Correct hook name
153
+
154
+ = 1.3 =
155
+ * Option to open links in new window
156
+ * Support for video items (with filter to disable this)
157
+ * New actions for adding custom output to the widget
158
+ * Support for https://
159
+ * Correctly escape attributes
160
+
161
+ = 1.2.1 =
162
+ * Change transient name due to data change
163
+
164
+ = 1.2 =
165
+ * Better error handling
166
+ * Encode emoji as they cause transient issues
167
+
168
+ = 1.1 =
169
+ * Fix issue with Instagram feed
170
+ * Add composer.json
171
+
172
+ = 1.0 =
173
+ * Initial release
wp-instagram-widget.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: WP Instagram Widget
4
+ Plugin URI: https://github.com/scottsweb/wp-instagram-widget
5
+ Description: A WordPress widget for showing your latest Instagram photos.
6
+ Version: 2.0.0
7
+ Author: Scott Evans
8
+ Author URI: https://scott.ee
9
+ Text Domain: wp-instagram-widget
10
+ Domain Path: /assets/languages/
11
+ License: GPLv2 or later
12
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
13
+
14
+ Copyright © 2013 Scott Evans
15
+
16
+ This program is free software; you can redistribute it and/or modify
17
+ it under the terms of the GNU General Public License as published by
18
+ the Free Software Foundation; either version 2 of the License, or
19
+ (at your option) any later version.
20
+
21
+ This program is distributed in the hope that it will be useful,
22
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ GNU General Public License for more details.
25
+
26
+ */
27
+
28
+ function wpiw_init() {
29
+
30
+ // define some constants.
31
+ define( 'WP_INSTAGRAM_WIDGET_JS_URL', plugins_url( '/assets/js', __FILE__ ) );
32
+ define( 'WP_INSTAGRAM_WIDGET_CSS_URL', plugins_url( '/assets/css', __FILE__ ) );
33
+ define( 'WP_INSTAGRAM_WIDGET_IMAGES_URL', plugins_url( '/assets/images', __FILE__ ) );
34
+ define( 'WP_INSTAGRAM_WIDGET_PATH', dirname( __FILE__ ) );
35
+ define( 'WP_INSTAGRAM_WIDGET_BASE', plugin_basename( __FILE__ ) );
36
+ define( 'WP_INSTAGRAM_WIDGET_FILE', __FILE__ );
37
+
38
+ // load language files.
39
+ load_plugin_textdomain( 'wp-instagram-widget', false, dirname( WP_INSTAGRAM_WIDGET_BASE ) . '/assets/languages/' );
40
+ }
41
+ add_action( 'init', 'wpiw_init' );
42
+
43
+ function wpiw_widget() {
44
+ register_widget( 'null_instagram_widget' );
45
+ }
46
+ add_action( 'widgets_init', 'wpiw_widget' );
47
+
48
+ Class null_instagram_widget extends WP_Widget {
49
+
50
+ function __construct() {
51
+ parent::__construct(
52
+ 'null-instagram-feed',
53
+ __( 'Instagram', 'wp-instagram-widget' ),
54
+ array(
55
+ 'classname' => 'null-instagram-feed',
56
+ 'description' => esc_html__( 'Displays your latest Instagram photos', 'wp-instagram-widget' ),
57
+ 'customize_selective_refresh' => true,
58
+ )
59
+ );
60
+ }
61
+
62
+ function widget( $args, $instance ) {
63
+
64
+ $title = empty( $instance['title'] ) ? '' : apply_filters( 'widget_title', $instance['title'] );
65
+ $username = empty( $instance['username'] ) ? '' : $instance['username'];
66
+ $limit = empty( $instance['number'] ) ? 9 : $instance['number'];
67
+ $size = empty( $instance['size'] ) ? 'large' : $instance['size'];
68
+ $target = empty( $instance['target'] ) ? '_self' : $instance['target'];
69
+ $link = empty( $instance['link'] ) ? '' : $instance['link'];
70
+
71
+ echo $args['before_widget'];
72
+
73
+ if ( ! empty( $title ) ) { echo $args['before_title'] . wp_kses_post( $title ) . $args['after_title']; };
74
+
75
+ do_action( 'wpiw_before_widget', $instance );
76
+
77
+ if ( '' !== $username ) {
78
+
79
+ $media_array = $this->scrape_instagram( $username );
80
+
81
+ if ( is_wp_error( $media_array ) ) {
82
+
83
+ echo wp_kses_post( $media_array->get_error_message() );
84
+
85
+ } else {
86
+
87
+ // filter for images only?
88
+ if ( $images_only = apply_filters( 'wpiw_images_only', false ) ) {
89
+ $media_array = array_filter( $media_array, array( $this, 'images_only' ) );
90
+ }
91
+
92
+ // slice list down to required limit.
93
+ $media_array = array_slice( $media_array, 0, $limit );
94
+
95
+ // filters for custom classes.
96
+ $ulclass = apply_filters( 'wpiw_list_class', 'instagram-pics instagram-size-' . $size );
97
+ $liclass = apply_filters( 'wpiw_item_class', '' );
98
+ $aclass = apply_filters( 'wpiw_a_class', '' );
99
+ $imgclass = apply_filters( 'wpiw_img_class', '' );
100
+ $template_part = apply_filters( 'wpiw_template_part', 'parts/wp-instagram-widget.php' );
101
+
102
+ ?><ul class="<?php echo esc_attr( $ulclass ); ?>"><?php
103
+ foreach( $media_array as $item ) {
104
+ // copy the else line into a new file (parts/wp-instagram-widget.php) within your theme and customise accordingly.
105
+ if ( locate_template( $template_part ) !== '' ) {
106
+ include locate_template( $template_part );
107
+ } else {
108
+ echo '<li class="' . esc_attr( $liclass ) . '"><a href="' . esc_url( $item['link'] ) . '" target="' . esc_attr( $target ) . '" class="' . esc_attr( $aclass ) . '"><img src="' . esc_url( $item[$size] ) . '" alt="' . esc_attr( $item['description'] ) . '" title="' . esc_attr( $item['description'] ) . '" class="' . esc_attr( $imgclass ) . '"/></a></li>';
109
+ }
110
+ }
111
+ ?></ul><?php
112
+ }
113
+ }
114
+
115
+ $linkclass = apply_filters( 'wpiw_link_class', 'clear' );
116
+ $linkaclass = apply_filters( 'wpiw_linka_class', '' );
117
+
118
+ switch ( substr( $username, 0, 1 ) ) {
119
+ case '#':
120
+ $url = '//instagram.com/explore/tags/' . str_replace( '#', '', $username );
121
+ break;
122
+
123
+ default:
124
+ $url = '//instagram.com/' . str_replace( '@', '', $username );
125
+ break;
126
+ }
127
+
128
+ if ( '' !== $link ) {
129
+ ?><p class="<?php echo esc_attr( $linkclass ); ?>"><a href="<?php echo trailingslashit( esc_url( $url ) ); ?>" rel="me" target="<?php echo esc_attr( $target ); ?>" class="<?php echo esc_attr( $linkaclass ); ?>"><?php echo wp_kses_post( $link ); ?></a></p><?php
130
+ }
131
+
132
+ do_action( 'wpiw_after_widget', $instance );
133
+
134
+ echo $args['after_widget'];
135
+ }
136
+
137
+ function form( $instance ) {
138
+ $instance = wp_parse_args( (array) $instance, array( 'title' => __( 'Instagram', 'wp-instagram-widget' ), 'username' => '', 'size' => 'large', 'link' => __( 'Follow Me!', 'wp-instagram-widget' ), 'number' => 9, 'target' => '_self' ) );
139
+ $title = $instance['title'];
140
+ $username = $instance['username'];
141
+ $number = absint( $instance['number'] );
142
+ $size = $instance['size'];
143
+ $target = $instance['target'];
144
+ $link = $instance['link'];
145
+ ?>
146
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title', 'wp-instagram-widget' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /></label></p>
147
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>"><?php esc_html_e( '@username or #tag', 'wp-instagram-widget' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'username' ) ); ?>" type="text" value="<?php echo esc_attr( $username ); ?>" /></label></p>
148
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>"><?php esc_html_e( 'Number of photos', 'wp-instagram-widget' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="text" value="<?php echo esc_attr( $number ); ?>" /></label></p>
149
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>"><?php esc_html_e( 'Photo size', 'wp-instagram-widget' ); ?>:</label>
150
+ <select id="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" class="widefat">
151
+ <option value="thumbnail" <?php selected( 'thumbnail', $size ) ?>><?php esc_html_e( 'Thumbnail', 'wp-instagram-widget' ); ?></option>
152
+ <option value="small" <?php selected( 'small', $size ) ?>><?php esc_html_e( 'Small', 'wp-instagram-widget' ); ?></option>
153
+ <option value="large" <?php selected( 'large', $size ) ?>><?php esc_html_e( 'Large', 'wp-instagram-widget' ); ?></option>
154
+ <option value="original" <?php selected( 'original', $size ) ?>><?php esc_html_e( 'Original', 'wp-instagram-widget' ); ?></option>
155
+ </select>
156
+ </p>
157
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'target' ) ); ?>"><?php esc_html_e( 'Open links in', 'wp-instagram-widget' ); ?>:</label>
158
+ <select id="<?php echo esc_attr( $this->get_field_id( 'target' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'target' ) ); ?>" class="widefat">
159
+ <option value="_self" <?php selected( '_self', $target ) ?>><?php esc_html_e( 'Current window (_self)', 'wp-instagram-widget' ); ?></option>
160
+ <option value="_blank" <?php selected( '_blank', $target ) ?>><?php esc_html_e( 'New window (_blank)', 'wp-instagram-widget' ); ?></option>
161
+ </select>
162
+ </p>
163
+ <p><label for="<?php echo esc_attr( $this->get_field_id( 'link' ) ); ?>"><?php esc_html_e( 'Link text', 'wp-instagram-widget' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'link' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'link' ) ); ?>" type="text" value="<?php echo esc_attr( $link ); ?>" /></label></p>
164
+ <?php
165
+
166
+ }
167
+
168
+ function update( $new_instance, $old_instance ) {
169
+ $instance = $old_instance;
170
+ $instance['title'] = strip_tags( $new_instance['title'] );
171
+ $instance['username'] = trim( strip_tags( $new_instance['username'] ) );
172
+ $instance['number'] = ! absint( $new_instance['number'] ) ? 9 : $new_instance['number'];
173
+ $instance['size'] = ( ( 'thumbnail' === $new_instance['size'] || 'large' === $new_instance['size'] || 'small' === $new_instance['size'] || 'original' === $new_instance['size'] ) ? $new_instance['size'] : 'large' );
174
+ $instance['target'] = ( ( '_self' === $new_instance['target'] || '_blank' === $new_instance['target'] ) ? $new_instance['target'] : '_self' );
175
+ $instance['link'] = strip_tags( $new_instance['link'] );
176
+ return $instance;
177
+ }
178
+
179
+ // based on https://gist.github.com/cosmocatalano/4544576.
180
+ function scrape_instagram( $username ) {
181
+
182
+ $username = trim( strtolower( $username ) );
183
+
184
+ if ( false === ( $instagram = get_transient( 'instagram-a7-' . sanitize_title_with_dashes( $username ) ) ) ) {
185
+
186
+ switch ( substr( $username, 0, 1 ) ) {
187
+ case '#':
188
+ $url = 'https://instagram.com/explore/tags/' . str_replace( '#', '', $username );
189
+ break;
190
+
191
+ default:
192
+ $url = 'https://instagram.com/' . str_replace( '@', '', $username );
193
+ break;
194
+ }
195
+
196
+ $remote = wp_remote_get( $url );
197
+
198
+ if ( is_wp_error( $remote ) ) {
199
+ return new WP_Error( 'site_down', esc_html__( 'Unable to communicate with Instagram.', 'wp-instagram-widget' ) );
200
+ }
201
+
202
+ if ( 200 !== wp_remote_retrieve_response_code( $remote ) ) {
203
+ return new WP_Error( 'invalid_response', esc_html__( 'Instagram did not return a 200.', 'wp-instagram-widget' ) );
204
+ }
205
+
206
+ $shards = explode( 'window._sharedData = ', $remote['body'] );
207
+ $insta_json = explode( ';</script>', $shards[1] );
208
+ $insta_array = json_decode( $insta_json[0], true );
209
+
210
+ if ( ! $insta_array ) {
211
+ return new WP_Error( 'bad_json', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
212
+ }
213
+
214
+ if ( isset( $insta_array['entry_data']['ProfilePage'][0]['user']['media']['nodes'] ) ) {
215
+ $images = $insta_array['entry_data']['ProfilePage'][0]['user']['media']['nodes'];
216
+ } else if ( isset( $insta_array['entry_data']['TagPage'][0]['tag']['media']['nodes'] ) ) {
217
+ $images = $insta_array['entry_data']['TagPage'][0]['tag']['media']['nodes'];
218
+ } else {
219
+ return new WP_Error( 'bad_json_2', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
220
+ }
221
+
222
+ if ( ! is_array( $images ) ) {
223
+ return new WP_Error( 'bad_array', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
224
+ }
225
+
226
+ $instagram = array();
227
+
228
+ foreach ( $images as $image ) {
229
+
230
+ $image['thumbnail_src'] = preg_replace( '/^https?\:/i', '', $image['thumbnail_src'] );
231
+ $image['display_src'] = preg_replace( '/^https?\:/i', '', $image['display_src'] );
232
+
233
+ // handle both types of CDN url.
234
+ if ( ( strpos( $image['thumbnail_src'], 's640x640' ) !== false ) ) {
235
+ $image['thumbnail'] = str_replace( 's640x640', 's160x160', $image['thumbnail_src'] );
236
+ $image['small'] = str_replace( 's640x640', 's320x320', $image['thumbnail_src'] );
237
+ } else {
238
+ $urlparts = wp_parse_url( $image['thumbnail_src'] );
239
+ $pathparts = explode( '/', $urlparts['path'] );
240
+ array_splice( $pathparts, 3, 0, array( 's160x160' ) );
241
+ $image['thumbnail'] = '//' . $urlparts['host'] . implode( '/', $pathparts );
242
+ $pathparts[3] = 's320x320';
243
+ $image['small'] = '//' . $urlparts['host'] . implode( '/', $pathparts );
244
+ }
245
+
246
+ $image['large'] = $image['thumbnail_src'];
247
+
248
+ if ( true === $image['is_video'] ) {
249
+ $type = 'video';
250
+ } else {
251
+ $type = 'image';
252
+ }
253
+
254
+ $caption = __( 'Instagram Image', 'wp-instagram-widget' );
255
+ if ( ! empty( $image['caption'] ) ) {
256
+ $caption = $image['caption'];
257
+ }
258
+
259
+ $instagram[] = array(
260
+ 'description' => $caption,
261
+ 'link' => trailingslashit( '//instagram.com/p/' . $image['code'] ),
262
+ 'time' => $image['date'],
263
+ 'comments' => $image['comments']['count'],
264
+ 'likes' => $image['likes']['count'],
265
+ 'thumbnail' => $image['thumbnail'],
266
+ 'small' => $image['small'],
267
+ 'large' => $image['large'],
268
+ 'original' => $image['display_src'],
269
+ 'type' => $type,
270
+ );
271
+ } // End foreach().
272
+
273
+ // do not set an empty transient - should help catch private or empty accounts.
274
+ if ( ! empty( $instagram ) ) {
275
+ $instagram = base64_encode( serialize( $instagram ) );
276
+ set_transient( 'instagram-a7-' . sanitize_title_with_dashes( $username ), $instagram, apply_filters( 'null_instagram_cache_time', HOUR_IN_SECONDS * 2 ) );
277
+ }
278
+ }
279
+
280
+ if ( ! empty( $instagram ) ) {
281
+
282
+ return unserialize( base64_decode( $instagram ) );
283
+
284
+ } else {
285
+
286
+ return new WP_Error( 'no_images', esc_html__( 'Instagram did not return any images.', 'wp-instagram-widget' ) );
287
+
288
+ }
289
+ }
290
+
291
+ function images_only( $media_item ) {
292
+
293
+ if ( 'image' === $media_item['type'] ) {
294
+ return true;
295
+ }
296
+
297
+ return false;
298
+ }
299
+ }