/hashimage.php

https://bitbucket.org/silentium/ep-hashimage · PHP · 444 lines · 311 code · 52 blank · 81 comment · 66 complexity · 79211ca43c7154be5b86850d929d7567 MD5 · raw file

  1. <?php
  2. /*
  3. Plugin Name: EP Hashimage
  4. Plugin URI: http://darkwhispering.com/wordpress-plugins
  5. Description: Display image by hashtag from twitter or instagram in your template, post/page or widget area using template tag, shortcode or the widget.
  6. Author: Mattias Hedman & Peder Fjällström
  7. Version: 4.0.1
  8. Author URI: http://darkwhispering.com
  9. */
  10. define('HASHIMAGE_VERSION', '4.0.1');
  11. if (!$_GET['asyncload']) {
  12. function plugin_init() {
  13. // Set default values
  14. add_option('ep_hashimage_async','true'); // For faster loading
  15. add_option('ep_hashimage_img_display','lightbox'); // Display method of retrived images
  16. add_option('ep_hashimage_refresh','false'); // Auto reload search every 15 min
  17. add_option('ep_hashimage_network','twitter'); // Network to search in twitter/instagram
  18. add_option('ep_hashimage_instagram_client_id',NULL); // Instagram api client_id
  19. // Default image sizes
  20. $default_img_sizes = array(
  21. 'thumb_h' => 200,
  22. 'thumb_w' => 200,
  23. 'widget_thumb_h' => 80,
  24. 'widget_thumb_w' => 80,
  25. 'lightbox_h' => 400,
  26. 'lightbox_w' => 600
  27. );
  28. add_option('ep_hashimage_img_sizes',$dedault_img_sizes);
  29. // Default twitter search networks
  30. $default_networks = array(
  31. 'instagram' => 'instagr.am',
  32. 'twitpic' => 'twitpic',
  33. 'twitter' => 'pic.twitter.com',
  34. 'yfrog' => 'yfrog',
  35. 'flickr' => 'flic.kr',
  36. 'plixi' => 'plixi'
  37. );
  38. add_option('ep_hashimage_networks',$default_networks);
  39. // Plugin version
  40. update_option('ep_hashimage_plugin_version',HASHIMAGE_VERSION);
  41. }
  42. add_action('init','plugin_init',10);
  43. }
  44. class Hashimage {
  45. function __construct($args = array())
  46. {
  47. // Setup settings array
  48. $default_settings = array(
  49. 'hashtag' => 'unicorn',
  50. 'limit' => '5',
  51. 'type' => 'plugin',
  52. 'output' => 'html',
  53. 'network' => get_option('ep_hashimage_network'),
  54. 'networks' => get_option('ep_hashimage_networks'),
  55. 'async' => get_option('ep_hashimage_async'),
  56. 'img_display' => get_option('ep_hashimage_img_display'),
  57. 'refresh' => get_option('ep_hashimage_refresh'),
  58. 'img_sizes' => get_option('ep_hashimage_img_sizes'),
  59. 'instagram_client_id' => get_option('ep_hashimage_instagram_client_id')
  60. );
  61. // Merge default settings with the new arguments from the user
  62. $this->settings = wp_parse_args($args, $default_settings);
  63. // Twitter Search URL
  64. $this->twitterUrl = 'http://search.twitter.com/search.json?q=&phrase=&ors=';
  65. // Check what networks within twitter we should use and add to the url
  66. $this->twitterUrl .= implode('+',$this->settings['networks']);
  67. // Add the hashtag
  68. $this->twitterUrl .= '&lang=all&include_entities=true&rpp=500&tag='.str_replace('#','',$this->settings['hashtag']);
  69. // Instagram API with hashtag and client_id
  70. $this->instagramUrl = 'https://api.instagram.com/v1/tags/'.str_replace('#','',$this->settings['hashtag']).'/media/recent?client_id='.$this->settings['instagram_client_id'];
  71. // Do the magic
  72. $this->_init();
  73. }
  74. /**
  75. * The heart of the plugin, here we do the heavy loading
  76. **/
  77. private function _init()
  78. {
  79. $twitterjson = '';
  80. $instagramjson = '';
  81. $image = array();
  82. // Check if we should load this asynct or not
  83. if (isset($_GET['asyncload']) || $this->settings['async'] === 'false')
  84. {
  85. if ($this->settings['network']['twitter'])
  86. {
  87. $twitterjson = json_decode($this->_fetchurl($this->twitterUrl, 600+rand(1,120)));
  88. }
  89. if ($this->settings['network']['instagram'])
  90. {
  91. $instagramjson = json_decode($this->_fetchurl($this->instagramUrl, 600+rand(1,120)));
  92. }
  93. }
  94. // Process the result from twitter
  95. if (isset($twitterjson) && $twitterjson->results) {
  96. foreach ($twitterjson->results as $results) {
  97. // If it is links to other networks
  98. if (isset($results->entities) && isset($results->entities->urls)) {
  99. foreach ($results->entities->urls as $url) {
  100. if (!empty($url->expanded_url) && !empty($url->url)) {
  101. $links[md5($url->expanded_url)]['img'] = $url->expanded_url;
  102. $links[md5($url->expanded_url)]['source'] = $url->url;
  103. }
  104. }
  105. }
  106. // If it is twitter media
  107. if (isset($results->entities) && isset($results->entities->media)) {
  108. foreach ($results->entities->media as $image) {
  109. if (!empty($image->media_url) && !empty($image->url)) {
  110. $images[md5($image->media_url)]['img'] = $image->media_url;
  111. $images[md5($image->media_url)]['source'] = $image->url;
  112. }
  113. }
  114. }
  115. }
  116. // Get the images from the links on twitter
  117. if ($links && $images) {
  118. $images = array_merge($this->_extractimages($links),$images);
  119. } else if (!$images) {
  120. $image = $links;
  121. }
  122. }
  123. // Process the results from instagram
  124. if (isset($instagramjson) && isset($instagramjson->data)) {
  125. foreach ($instagramjson->data as $result) {
  126. if (!empty($result->link) && !empty($result->images->standard_resolution->url)) {
  127. $images[md5($result->images->standard_resolution->url)]['img'] = $result->images->standard_resolution->url;
  128. $images[md5($result->images->standard_resolution->url)]['source'] = $result->link;
  129. }
  130. }
  131. }
  132. if ($images) {
  133. // Remove any doubles
  134. $images = array_map('unserialize', array_unique(array_map('serialize', $images)));
  135. // Remove images without img url or source url
  136. foreach ($images as $key => $image) {
  137. if(empty($image['img']) || empty($image['source'])) {
  138. unset($images[$key]);
  139. }
  140. }
  141. // If both twitter and instagram is used, lets shuffel the results
  142. if ($this->settings['network']['twitter'] && $this->settings['network']['instagram']) {
  143. shuffle($images);
  144. }
  145. // Limit the amount of images returned to the output after the limit
  146. $images = array_slice($images, 0, $this->settings['limit']);
  147. }
  148. // Build the output
  149. if ($this->settings['output'] === 'html') {
  150. $this->output = $this->_formathtml($images);
  151. } elseif ($this->settings['output'] === 'array') {
  152. $this->output = $images;
  153. }
  154. }
  155. /**
  156. * Fetch the url
  157. **/
  158. private function _fetchurl($url = null, $ttl = 86400){
  159. if ($url) {
  160. $option_name = 'hashimage_cache_'.md5($url);
  161. // Chec if cache of the urls allready exists, if not, get content of the url
  162. if (false === ($data = get_site_transient($option_name))) {
  163. $ch = curl_init();
  164. $options = array(
  165. CURLOPT_URL => $url,
  166. CURLOPT_RETURNTRANSFER => true,
  167. CURLOPT_CONNECTTIMEOUT => 10,
  168. CURLOPT_TIMEOUT => 10
  169. );
  170. curl_setopt_array($ch, $options);
  171. $data['chunk'] = curl_exec($ch);
  172. $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  173. curl_close($ch);
  174. if($http_code === 200){
  175. // Set the new cache
  176. set_site_transient($option_name, $data, $ttl);
  177. }
  178. }
  179. return $data['chunk'];
  180. }
  181. }
  182. /**
  183. * Extract the images from the data returned
  184. **/
  185. private function _extractimages($links){
  186. if($links){
  187. foreach($links as $link){
  188. // yfrog.com
  189. if (stristr($link['img'],'yfrog.com'))
  190. {
  191. $images[md5($link['img'])]['img'] = $this->_extractyfrog($link['img']);
  192. $images[md5($link['img'])]['source'] = $link['source'];
  193. }
  194. // plixi.com
  195. else if (stristr($link['img'],'plixi.com'))
  196. {
  197. $images[md5($link['img'])]['img'] = $this->_extractplixi($link['img']);
  198. $images[md5($link['img'])]['source'] = $link['source'];
  199. }
  200. // instagr.am
  201. else if (stristr($link['img'],'instagr.am'))
  202. {
  203. $images[md5($link['img'])]['img'] = $this->_extractinstagram($link['img']);
  204. $images[md5($link['img'])]['source'] = $link['source'];
  205. }
  206. // twitpic.com
  207. else if (stristr($link['img'],'twitpic.com'))
  208. {
  209. $images[md5($link['img'])]['img'] = $this->_extracttwitpic($link['img']);
  210. $images[md5($link['img'])]['source'] = $link['source'];
  211. }
  212. // flic.kr
  213. else if (stristr($link['img'],'flic.kr'))
  214. {
  215. $images[md5($link['img'])]['img'] = $this->_extractflickr($link['img']);
  216. $images[md5($link['img'])]['source'] = $link['source'];
  217. }
  218. }
  219. return $images;
  220. }
  221. }
  222. /**
  223. * Extract yfrog images
  224. **/
  225. private function _extractyfrog($link){
  226. return trim($link,'”."').':iphone';
  227. }
  228. /**
  229. * Extract twitpic images
  230. **/
  231. private function _extracttwitpic($link){
  232. $linkparts = explode('/',$link);
  233. return 'http://twitpic.com/show/large/'.$linkparts[3];
  234. }
  235. /**
  236. * Extract flickr images
  237. **/
  238. private function _extractflickr($link){
  239. $string = $this->_fetchurl($link);
  240. if(isset($string)){
  241. preg_match_all('!<img src="(.*?)" alt="photo" !', $string, $matches);
  242. if(isset($matches[1][0])){
  243. return $matches[1][0];
  244. }
  245. }
  246. }
  247. /**
  248. * Extract instagram images
  249. **/
  250. private function _extractinstagram($link){
  251. $link = trim($link);
  252. $search = 'instagr.am';
  253. $replace = 'instagram.com';
  254. $link = str_replace($search, $replace, $link);
  255. $string = $this->_fetchurl($link);
  256. if(isset($string)){
  257. preg_match_all('! class="photo" src="(.*?)" !', $string, $matches);
  258. if(isset($matches[1][0]) && !empty($matches[1][0])){
  259. return $matches[1][0];
  260. }
  261. }
  262. }
  263. /**
  264. * Extract plixi images
  265. **/
  266. private function _extractplixi($link){
  267. $string = $this->_fetchurl($link);
  268. if(isset($string)){
  269. preg_match_all('! src="(.*)" id="photo"!', $string, $matches);
  270. if($matches[1][0]){
  271. return $matches[1][0];
  272. }
  273. }
  274. }
  275. /**
  276. * Build the HTML code
  277. **/
  278. private function _formathtml($images = array())
  279. {
  280. $html = '';
  281. // Arguments for the async loding
  282. $jsargs = array(
  283. 'pluginpath' => plugins_url('hashimage.php',__FILE__),
  284. 'hashtag' => $this->settings['hashtag'],
  285. 'limit' => $this->settings['limit'],
  286. 'type' => $this->settings['type'],
  287. 'async' => $this->settings['async'],
  288. 'refresh' => $this->settings['refresh']
  289. );
  290. // If async is true, add the async arguments as json in a data attribute and display a loading img and text.
  291. if ($this->settings['async'] === 'true' && $_GET['asyncload'] != 'true')
  292. {
  293. $html .= "<ul class='hashimage-container' data-options='".json_encode($jsargs)."'>";
  294. $html .= '<p class="hashimage-loading"><img src="'.plugins_url('loading.gif',__FILE__).'" alt="Loading"> Loading hashimages...</p>';
  295. }
  296. // If async is false or this is the actual async request, build the html
  297. else
  298. {
  299. $html .= "<ul class='hashimage-container' data-options='".json_encode($jsargs)."'>";
  300. $html .= '<p class="hashimage-loading" style="sidplay:none;"><img src="'.plugins_url('loading.gif',__FILE__).'" alt="Loading"> Loading hashimages...</p>';
  301. if (!empty($images)) {
  302. foreach ($images as $image) {
  303. $html .= '<li>';
  304. // If image display method is lightbox
  305. if ($this->settings['img_display'] === 'lightbox')
  306. {
  307. // If widget
  308. if ($this->settings['type'] == 'widget' || $_GET['type'] == 'widget')
  309. {
  310. $html .= '<a href="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['lightbox_w'].'&amp;h='.$this->settings['img_sizes']['lightbox_h'].'&amp;zc=2" rel="lightbox-'.$this->settings['hashtag'].'"><img src="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['widget_thumb_w'].'&amp;h='.$this->settings['img_sizes']['widget_thumb_h'].'" alt="Image loaded with Hashimage" /></a>'."\n";
  311. }
  312. // If not widget
  313. else
  314. {
  315. $html .= '<a href="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['lightbox_w'].'&amp;h='.$this->settings['img_sizes']['lightbox_h'].'&amp;zc=2" rel="lightbox-'.$this->settings['hashtag'].'"><img src="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['thumb_w'].'&amp;h='.$this->settings['img_sizes']['thumb_h'].'" alt="Image loaded with Hashimage" /></a>'."\n";
  316. }
  317. }
  318. // If image display method is original source
  319. elseif($this->settings['img_display'] === 'source')
  320. {
  321. // If widget
  322. if ($this->settings['type'] == 'widget' || $_GET['type'] == 'widget')
  323. {
  324. $html .= '<a href="'.$image['source'].'" target="_blank"><img src="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['widget_thumb_w'].'&amp;h='.$this->settings['img_sizes']['widget_thumb_h'].'" alt="Image loaded with Hashimage" /></a>'."\n";
  325. }
  326. // If not widget
  327. else
  328. {
  329. $html .= '<a href="'.$image['source'].'" target="_blank"><img src="'.plugins_url('timthumb.php',__FILE__).'?src='.$image['img'].'&amp;w='.$this->settings['img_sizes']['thumb_w'].'&amp;h='.$this->settings['img_sizes']['thumb_h'].'" alt="Image loaded with Hashimage" /></a>'."\n";
  330. }
  331. }
  332. $html .= '</li>';
  333. }
  334. } else {
  335. $html .= '<li>No images found for your hashtag!</li>';
  336. }
  337. }
  338. $html .= '</ul>';
  339. return $html;
  340. }
  341. }
  342. function hashimage($args = array()){
  343. $hashimage = new Hashimage($args);
  344. return $hashimage->output;
  345. }
  346. /**
  347. * IF THIS IS AN ASYNC REQUEST
  348. **/
  349. if(!defined('ABSPATH')){
  350. require("../../../wp-load.php");
  351. $args = array (
  352. 'hashtag' => strip_tags($_GET['hashtag']),
  353. 'limit' => (int)$_GET['limit'],
  354. 'type' => $_GET['type']
  355. );
  356. echo hashimage($args);
  357. exit(0);
  358. }
  359. // Include widget
  360. include_once('widget.php');
  361. // Include shortcode
  362. include_once('shortcode.php');
  363. // Include settings page
  364. include_once('settings-page.php');
  365. //Frontpage JS and CSS
  366. function hashimage_js() {
  367. wp_enqueue_script("jquery");
  368. wp_register_script('hashimage_js', plugins_url('js/slimbox2.js', __FILE__));
  369. wp_register_script('hashimage_js_async', plugins_url('js/async.js', __FILE__));
  370. wp_enqueue_script('hashimage_js');
  371. wp_enqueue_script('hashimage_js_async');
  372. }
  373. add_action('wp_print_scripts','hashimage_js');
  374. function hashimage_css() {
  375. wp_register_style('hashimage_slimbox_css', plugins_url('css/slimbox2.css', __FILE__));
  376. wp_register_style('hashimage_css', plugins_url('css/style.css', __FILE__));
  377. wp_enqueue_style('hashimage_slimbox_css');
  378. wp_enqueue_style('hashimage_css');
  379. }
  380. add_action('wp_print_styles','hashimage_css');
  381. // IF the plugin is beeing deactivated
  382. function hashimage_deactivate() {
  383. global $wpdb;
  384. $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE %s", '%hashimage_cache%'));
  385. $wp_upload_dir = wp_upload_dir();
  386. $cachdir = $wp_upload_dir['basedir'].'/ep_hashimage/';
  387. foreach(glob($cachdir . '/*') as $file) {
  388. if(is_dir($file)) rrmdir($file); else unlink($file);
  389. }
  390. rmdir($cachdir);
  391. }
  392. register_deactivation_hook( __FILE__, 'hashimage_deactivate' );