Guest User

Untitled

a guest
Mar 16th, 2018
2,605
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.70 KB | None | 0 0
  1. <?php
  2.  
  3. class td_instagram {
  4.  
  5. private static $caching_time = 10800; // 3 hours
  6.  
  7. public static function render_generic($atts) {
  8.  
  9. // Instagram id is not set
  10. if (empty($atts['instagram_id'])) {
  11. return td_util::get_block_error('Instagram', 'Render failed - no data is received, please check the ID' );
  12. }
  13.  
  14. // prepare the data
  15. $instragram_data = array(
  16. 'user' => '',
  17. );
  18.  
  19. // get instagram data
  20. $instagram_data_status = self::get_instagram_data($atts, $instragram_data);
  21.  
  22. // check if we have an error and return that
  23. if ($instagram_data_status != 'instagram_fail_cache' and $instagram_data_status != 'instagram_cache_updated' and $instagram_data_status != 'instagram_cache') {
  24. return $instagram_data_status;
  25. }
  26.  
  27. // render the HTML
  28. $buffy = '<!-- td instagram source: ' . $instagram_data_status . ' -->';
  29.  
  30. // renders the block template
  31. $buffy .= self::render_block_template($atts, $instragram_data);
  32.  
  33. return $buffy;
  34. }
  35.  
  36. private static function render_block_template($atts, $instagram_data) {
  37.  
  38. // stop render when no data is received
  39. if ($instagram_data['user'] == '') {
  40. //return self::error('Render failed - no data is received, please check the ID: ' . $atts['instagram_id']);
  41. return td_util::get_block_error('Instagram', 'Render failed - no data is received, please check the ID: ' . $atts['instagram_id']);
  42. }
  43.  
  44. // debugging
  45. // echo '<pre>';
  46. // print_r($instagram_data);
  47. // echo '</pre>';
  48.  
  49.  
  50. ob_start();
  51.  
  52. // number of images per row - by default display 3 images
  53. $images_per_row = 3;
  54. if (!empty($atts['instagram_images_per_row'])) {
  55. $images_per_row = $atts['instagram_images_per_row'];
  56. }
  57.  
  58. // number of rows
  59. $number_of_rows = 1;
  60. if (!empty($atts['instagram_number_of_rows'])) {
  61. $number_of_rows = $atts['instagram_number_of_rows'];
  62. }
  63.  
  64. // number of total images displayed - images_row x number_of_rows
  65. $images_total_number = $images_per_row * $number_of_rows;
  66.  
  67. // image gap
  68. $image_gap = '';
  69. if (!empty($atts['instagram_margin'])) {
  70. $image_gap = ' td-image-gap-' . $atts['instagram_margin'];
  71. }
  72.  
  73. // profile picture
  74. $instagram_profile_picture = '';
  75. if (isset($instagram_data['user']['profile_pic_url'])) {
  76. $instagram_profile_picture = $instagram_data['user']['profile_pic_url'];
  77. }
  78.  
  79. // instagram followers
  80. $instagram_followers = 0;
  81. if (isset($instagram_data['user']['edge_followed_by']['count'])) {
  82. $instagram_followers = $instagram_data['user']['edge_followed_by']['count'];
  83. }
  84.  
  85. // instagram followers - check followers count data type
  86. $instagram_followers_type = gettype($instagram_followers);
  87. if ($instagram_followers_type == 'string') {
  88. // retrieve number from string
  89. $number_from_string = self::get_number_from_string($instagram_followers);
  90. if ($number_from_string !== false) {
  91. $instagram_followers = $number_from_string;
  92. } else {
  93. td_log::log(__FILE__, __FUNCTION__, 'Instagram followers is a string with no numbers included', $instagram_followers);
  94. $instagram_followers = 0;
  95. }
  96. } elseif ($instagram_followers_type == 'integer') {
  97. // do nothing, integer is ok
  98. } else {
  99. // for other types return 0
  100. td_log::log(__FILE__, __FUNCTION__, 'Instagram followers has an unsupported type', $instagram_followers);
  101. $instagram_followers = 0;
  102. }
  103.  
  104. // instagram followers - format the followers number (the number is not rounded because it may return unrealistic values)
  105. if ($instagram_followers >= 1000000) {
  106. // display 1.100.000 as 1.1m
  107. $instagram_followers = number_format_i18n($instagram_followers / 1000000, 1) . 'm';
  108. } elseif ($instagram_followers >= 10000) {
  109. // display 10.100 as 10.1k
  110. $instagram_followers = number_format_i18n($instagram_followers / 1000, 1) . 'k';
  111. } else {
  112. // default
  113. $instagram_followers = number_format_i18n($instagram_followers);
  114. }
  115.  
  116. ?>
  117. <!-- header section -->
  118. <?php
  119. if (empty($atts['instagram_header'])) {
  120. ?>
  121. <div class="td-instagram-header">
  122. <div class="td-instagram-profile-image"><img src="<?php echo $instagram_profile_picture ?>"/></div>
  123. <div class="td-instagram-meta">
  124. <div class="td-instagram-user"><a href="https://www.instagram.com/<?php echo self::strip_instagram_user($atts['instagram_id']) ?>" target="_blank">@<?php echo self::strip_instagram_user($atts['instagram_id']) ?></a></div>
  125. <div class="td-instagram-followers"><span><?php echo $instagram_followers . '</span> ' . __td('Followers', TD_THEME_NAME); ?></div>
  126. <a class="td-instagram-button" href="https://www.instagram.com/<?php echo self::strip_instagram_user($atts['instagram_id']) ?>" target="_blank"><?php echo __td('Follow', TD_THEME_NAME); ?></a>
  127. <div class="clearfix"></div>
  128. </div>
  129. </div>
  130. <?php
  131. }
  132. ?>
  133.  
  134. <!-- user shared images -->
  135. <?php
  136.  
  137. $user_shared_images = $instagram_data['user']["edge_owner_to_timeline_media"]["edges"];
  138.  
  139. if ( isset( $user_shared_images ) and is_array( $user_shared_images ) ) {
  140. ?>
  141. <div class="td-instagram-main td-images-on-row-<?php echo $images_per_row . $image_gap; ?>">
  142. <?php
  143. $image_count = 0;
  144. foreach ( $user_shared_images as $image ) {
  145. // display only if the code and thumbnail are set
  146. if ( isset( $image['node']['shortcode'] ) && isset( $image['node']['thumbnail_src'] ) ) {
  147. ?>
  148. <div class="td-instagram-element">
  149. <!-- image -->
  150. <a href="https://www.instagram.com/p/<?php echo $image['node']['shortcode'] ?>" target="_blank">
  151. <img class="td-instagram-image" src="<?php echo $image['node']['thumbnail_src'] ?>"/>
  152. </a>
  153. <!-- video icon -->
  154. <?php
  155. if ( $image['node']['is_video'] === true ) {
  156. ?>
  157. <span class="td-video-play-ico">
  158. <img width="40" class="td-retina" src="<?php echo td_global::$get_template_directory_uri . '/images/icons/ico-video-large.png' ?>" alt="video"/>
  159. </span>
  160. <?php
  161. }
  162. ?>
  163. </div>
  164. <?php
  165. }
  166. ?>
  167. <!-- number of images to display -->
  168. <?php
  169. $image_count ++;
  170. if ( $image_count == $images_total_number ) {
  171. break;
  172. }
  173. }
  174. ?>
  175. <div class="clearfix"></div>
  176. </div>
  177. <?php
  178. }
  179. return ob_get_clean();
  180. }
  181.  
  182.  
  183. /**
  184. * @param $str
  185. * @return bool|int
  186. * - bool: false - $str is not a string or we don't have a number
  187. * - integer - return the number
  188. */
  189. private static function get_number_from_string($str) {
  190. // no string received
  191. if (gettype($str) != 'string') {
  192. return false;
  193. }
  194. // retrieve the numbers
  195. $string_length = strlen($str);
  196. $id = '';
  197. for( $i = 0; $i <= $string_length; $i++ ) {
  198. $char = substr($str, $i, 1);
  199. if(is_numeric($char)) {
  200. $id .= $char;
  201. }
  202. }
  203. // we have a number
  204. if ($id != '') {
  205. return intval($id);
  206. }
  207. return false;
  208. }
  209.  
  210.  
  211. /**
  212. * @param $atts
  213. * @param $instragram_data - the precomputed instagram data
  214. * @return bool|string
  215. * - bool:true - we have the $instragram_data (from cache or from a real request)
  216. * - string - error message
  217. */
  218. private static function get_instagram_data($atts, &$instragram_data) {
  219.  
  220. $cache_key = 'td_instragram_' . strtolower($atts['instagram_id']);
  221. if (td_remote_cache::is_expired(__CLASS__, $cache_key) === true) {
  222. // cache is expired - do a request
  223. $instagram_get_data = self::instagram_get_json($atts, $instragram_data);
  224. // check the call response
  225. if ($instagram_get_data !== true) {
  226. // we have an error in the data retrieval process
  227. $instragram_data = td_remote_cache::get(__CLASS__, $cache_key);
  228. if ($instragram_data === false) { // miss and io error... shit / die
  229. //return self::error('Instagram data error: ' . $instagram_get_data);
  230. return td_util::get_block_error('Instagram', 'Instagram data error: ' . $instagram_get_data);
  231. }
  232.  
  233. td_remote_cache::extend(__CLASS__, $cache_key, self::$caching_time);
  234. return 'instagram_fail_cache';
  235. }
  236.  
  237. td_remote_cache::set(__CLASS__, $cache_key, $instragram_data, self::$caching_time); //we have a reply and we set it
  238. return 'instagram_cache_updated';
  239.  
  240. } else {
  241. // cache is valid
  242. $instragram_data = td_remote_cache::get(__CLASS__, $cache_key);
  243. return 'instagram_cache';
  244. }
  245. }
  246.  
  247. /**
  248. * @param $atts
  249. * @param $instagram_data
  250. * @return bool|string
  251. * - bool: true when data is retrieved
  252. * - string - error message
  253. */
  254. private static function instagram_get_json($atts, &$instagram_data){
  255.  
  256. $instagram_html_data = self::parse_instagram_html(self::strip_instagram_user($atts['instagram_id']));
  257.  
  258. if ($instagram_html_data === false) {
  259. td_log::log(__FILE__, __FUNCTION__, 'Instagram html data cannot be retrieved', $atts['instagram_id']);
  260. return 'Instagram html data cannot be retrieved';
  261. }
  262.  
  263. // try to decode the json
  264. $instagram_json = json_decode($instagram_html_data, true);
  265. if ($instagram_json === null and json_last_error() !== JSON_ERROR_NONE) {
  266. td_log::log(__FILE__, __FUNCTION__, 'Error decoding the instagram json', $instagram_json);
  267. return 'Error decoding the instagram json';
  268. }
  269.  
  270. // current instagram data is not set
  271. if (!isset($instagram_json['entry_data']['ProfilePage'][0]["graphql"]['user'])) {
  272. return 'Instagram data is not set, plese check the ID';
  273. }
  274.  
  275. $instagram_data['user'] = $instagram_json['entry_data']['ProfilePage'][0]["graphql"]['user'];
  276.  
  277. return true;
  278. }
  279.  
  280.  
  281. /**
  282. * @param $instagram_id
  283. * @return bool|string
  284. * - bool: false - no match was found, data not retrieved
  285. * - string - return the serialized data present in the page script
  286. */
  287. private static function parse_instagram_html($instagram_id) {
  288.  
  289. $data = td_remote_http::get_page('https://www.instagram.com/' . $instagram_id, __CLASS__);
  290. if ($data === false) {
  291. return false;
  292. }
  293.  
  294. // get the serialized data string present in the page script
  295. $pattern = '/window\._sharedData = (.*);<\/script>/';
  296. preg_match($pattern, $data, $matches);
  297.  
  298. if (!empty($matches[1])) {
  299. return $matches[1];
  300. } else {
  301. return false;
  302. }
  303.  
  304. }
  305.  
  306.  
  307. /**
  308. * Show an error if the user is logged in. It does not check for admin
  309. * @param $msg
  310. * @return string
  311. */
  312. private static function error($msg) {
  313. if (is_user_logged_in()) {
  314. return $msg;
  315. }
  316. return '';
  317. }
  318.  
  319. /**
  320. * @param $id - the instagram ID
  321. * @return string - user inserted instagram ID without @
  322. */
  323. public static function strip_instagram_user($id) {
  324. $pos = strpos($id, '@');
  325.  
  326. if ( $pos !== false ) {
  327. $id = substr($id, $pos+1);
  328. return $id;
  329. }
  330.  
  331. return $id;
  332. }
  333. }
Advertisement
Add Comment
Please, Sign In to add comment