<?php
/*	GALLERY IMAGES FETCHER
	USES BUILDER HUB CLASS TO SETUP PARAMETERS - DIRECTLY RETURNS IMAGES ARRAY
*/

include_once('gg_builder_sources_hub.php');
class gg_img_fetcher extends gg_builder_hub {
	
	/* INHERITED 
	public $gid; // (int) gallery ID
	public $src; // (string) images source type
	public $gall_params = array(); // (array) associative array containing gallery arguments to show images (eg. username, psw)
	*/
	
	
	public $page = 1; // image picker page
	public $per_page = 26; // how many images to show per page
	public $search = ''; // how many images to show per page
	public $extra = array(); // additional parameters to fetch images
	
	private $tot_images; // how many images that source contains
	public $get = array(); // variable containing data to return
	public $errors = array(); // contains all errors faced in the fetched instance
    

	/* CONSTRUCT - recall parameters and eventually query gallery type - then fetches images 
	 *
	 * @param (string) $search - string used to match images performing searches (where available)
	 * @param (string/array) $extra - extra value or associative array of values to fetch images in specific sources
	 *
	 * @return (array) associative array containing fetch result
	 	array('img' => $to_show, 'pag' => $page, 'tot_pag' =>$tot_pag, 'more' => $more, 'tot' => $img_num)		
	*/
	public function __construct($gid, $type, $page = 1, $per_page = 26, $search = '', $extra = array()) {
		parent::__construct($gid, $type);
		
		// setup vars
		$this->page = $page;
		$this->per_page = $per_page;
		$this->search = $search;
		$this->extra = $extra;
		
		
		$images = (array)$this->fetch_by_type();
		$img_num = (empty($this->tot_images)) ? count($images) : $this->tot_images;
		

		// calculate total pages
		$tot_pag = ceil($img_num / $per_page);
		
		// can show more?
		$shown = $per_page * $page;
		$more = ($shown >= $img_num) ? false : true; 
		
		// images array offset
		if(!in_array($this->src, array('wp', 'wp_cat', 'rml', 'ngg', 'flickr'))) {
			$to_show = array();
			$offset = $per_page * ($page - 1);
			for($a=$offset; $a <= ($offset + $per_page); $a++) {
				$index = $a -1;
				if(isset($images[$index])) { $to_show[] = $images[$index]; }	
			}
		}
		else {
			$to_show = $images;
		}
		
		$this->get = array('img' => $to_show, 'pag' => $page, 'tot_pag' =>$tot_pag, 'more' => $more, 'tot' => $img_num);
		return true;
	}
    
    
    
    /* use cURL to get external url contents */
    public static function get_remote_contents($url, $followlocation = false) {
        $data = wp_remote_get($url, array(
            'timeout' 		=> 8, 
            'redirection' 	=> 3,
            //'User-Agent' 	=> 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
        ));

        // nothing got - use cURL 
        if(is_wp_error($data) || 200 != wp_remote_retrieve_response_code($data) || empty($data['body'])) {
            @ini_set( 'memory_limit', '256M');
            $ch = curl_init();

            //curl_setopt($ch, CURLOPT_AUTOREFERER, true);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_USERAGENT, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_URL, $url);

            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);

            // followlocation only if needed
            if($followlocation) {
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
            }
            else {
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, gg_static::use_followlocation());
            }

            $data = curl_exec($ch);

            // store last URL if followlocation has been performed
            if(strpos($url, 'pinterest.com') !== false || $followlocation) {
                $GLOBALS['gg_curl_true_url'] = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); 
            }

            curl_close($ch);
            return $data;
        }
        else {
            return $data['body'];	
        }
    }
	
	
	
	/* physically fetch images */
	private function fetch_by_type() {	
        $images = array();
        $max_img_size = get_option('gg_fetched_img_max_size', 'max');
        
		switch($this->src) {
			default : 
                return $images; 
                break;
			  
			
			// Wordpress global images
			case 'wp' :
				$query_images_args = array(
					'post_type' => 'attachment', 'post_mime_type' =>'image', 'post_status' => 'inherit', 
					'offset' => (($this->page - 1) * $this->per_page),
					'posts_per_page' => $this->per_page
				);
				
				if(!empty($this->search)) {
					$query_images_args['s'] = $this->search;
				}
				$query_images = new WP_Query($query_images_args);
			
				foreach($query_images->posts as $image) { 
					if(trim($image->guid) != '') {
						$images[] = array(
							'id'	=> $image->ID,
							'path'	=> trim(gg_static::img_id_to_path($image->ID)),
							'url' 	=> trim($image->guid),
							'author'=> '',  
							'title'	=> $image->post_title,
							'descr'	=> $image->post_content
						);
					}
				}
				
				$this->tot_images = $query_images->found_posts;
				return $images;
				break;
			
			
			
			// Wordpress category images
			case 'wp_cat' :
				$query_images_args = array(
					'post_type' => 'post', 'post_status' => 'publish', 'meta_key' => '_thumbnail_id', 
					'offset' => (($this->page - 1) * $this->per_page),
					'posts_per_page' => $this->per_page,
					'cat' => $this->extra 
				);
				$query_images = new WP_Query($query_images_args);
				
				foreach($query_images->posts as $post) {
					$img_id = (int)get_post_thumbnail_id( $post->ID );	
					if(is_int($img_id) && !isset($images[$img_id])) {  // avoid duplicates
						$image = get_post($img_id);
						
						if(isset($image->ID)) {
							$images[] = array(
								'id'	=> $image->ID,
								'path'	=> trim(gg_static::img_id_to_path($img_id)),
								'url' 	=> trim($image->guid),
								'author'=> '', 
								'title'	=> $image->post_title,
								'descr'	=> $image->post_content,
								'link' 	=> site_url().'?p='.$post->ID
							);
						}
					}
				}

				$this->tot_images = $query_images->found_posts;
				return $images;
				break;
			
			
			
			// Custom post type's taxonomy images
			case 'cpt_tax' :
				$cpt_arr = explode('|||', $this->extra['cpt_tax']);
				$term = $this->extra['term'];
				
				$query_images_args = array(
					'post_type' => $cpt_arr[0], 
					'post_status' => 'publish', 
					'meta_key' => '_thumbnail_id', 
					'offset' => (($this->page - 1) * $this->per_page),
					'posts_per_page' => $this->per_page
				);
				
				if($term) {
					$query_images_args['tax_query'] = array(
						array(
							'taxonomy' => $cpt_arr[1],
							'field' => 'id',
							'terms' => $term,
							'include_children' => true
						)
					);	
				} else {
					$query_images_args['taxonomy'] = $cpt_arr[1];
				}
					 	 
				$query_images = new WP_Query($query_images_args);
				
				foreach($query_images->posts as $post) {
					$img_id = (int)get_post_thumbnail_id( $post->ID );	
					if(is_int($img_id) && !isset($images[$img_id])) {  // avoid duplicates
						$image = get_post($img_id);
						
						if(isset($image->ID)) {
							$images[] = array(
								'id'	=> $image->ID,
								'path'	=> gg_static::img_id_to_path($img_id),
								'url' 	=> $image->guid,
								'author'=> '', 
								'title'	=> $image->post_title,
								'descr'	=> $image->post_content,
								'link' 	=> site_url().'?p='.$post->ID
							);
						}
					}
				}

				$this->tot_images = $query_images->found_posts;
				return $images;
				break;
				
			
			
			// GG album images
			case 'gg_album' :
                include_once(GG_DIR .'/classes/gg_local_images.php');
                $fm = new gg_local_images();

                // startup engine
                $fm_response = $fm->is_ready();
                if($fm_response !== true) {
                    // translators: 1: opening <a> tag with URL to configuration page, 2: closing </a> tag.
                    $this->errors[] = sprintf(
                        esc_html__('Initialization error, %1$splease configure this source%2$s before creating galleries.','gg_ml'),
                        '<a href="'. esc_url(admin_url('edit.php?post_type=gg_galleries&page=gg_album_manager')) .'">',
                        '</a>'
                    );
                    return $images;
                }
                
                // get images
				$raw_images = $fm->list_files($this->extra);
				if(!is_array($raw_images)) {
                    $this->errors[] = $raw_images;
                    return $images;        
                }
				
				// process values
				foreach($raw_images as $img_data) {
                    $processed_data = gg_static::maybe_get_iptc_tags($img_data['path']);
                    $title = $processed_data['title'];
                    
                    // images search    
					if(!empty($this->search) && strpos(strtolower($title), strtolower($this->search)) === false) { 
                        continue;    
                    }
					
                    $images[] = array(
                        'path'	=> str_replace(trailingslashit(get_option('gg_albums_basepath', $fm->suggested_path)), '', $img_data['path']), 
                        'url' 	=> str_replace(trailingslashit(get_option('gg_albums_baseurl', $fm->suggested_url)), '', $img_data['url']), 
                        'author'=> $processed_data['author'],
                        'title'	=> $title,
                        'descr'	=> $processed_data['descr'],
                        'tags'  => $processed_data['tags'],
                    );	
				}

				return $images;
				break;
			
			
			
			// Flickr images
			case 'flickr' : 
				$subj_url 	= get_post_meta($this->gid, 'gg_username', true);
				$subj 		= gg_gall_static::flickr_subj($subj_url);
                
                $subj_id    = explode('/', untrailingslashit($subj_url ));
				$subj_id 	= end($subj_id);
                
				switch($subj) {
					case 'set' : 
						$api_url = 'https://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos&api_key=98d15fe4ecf8fc21d95b4a7b5cac7227&photoset_id='.urlencode($subj_id).'&extras=url_m%2C+url_h%2C+url_o%2Cdescription&format=json&nojsoncallback=1&media=photos&page='. $this->page .'&per_page='. $this->per_page;
						break;
						
					case 'photostream' : 
						$api_url = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=98d15fe4ecf8fc21d95b4a7b5cac7227&user_id='.urlencode($subj_id).'&privacy_filter=public+photos&extras=url_m%2C+url_h%2C+url_o%2C+owner_name%2Cdescription&page='. $this->page .'&per_page='. $this->per_page .'&media=photos&format=json&nojsoncallback=1';
						break;
						
					case 'tag' :
						$api_url = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=98d15fe4ecf8fc21d95b4a7b5cac7227&tags='.urlencode($subj_id).'&privacy_filter=public+photos&extras=url_m%2C+url_h%2C+url_o%2C+owner_name%2Cdescription&page='. $this->page .'&per_page='. $this->per_page .'&media=photos&format=json&nojsoncallback=1';
						break;
						
					default : 
                        $api_url = ''; 
                        break;	
				}
                
				$json = self::get_remote_contents($api_url);
				if($json === false ) {
                    $this->errors[] = esc_html__('Error connecting to Flickr', 'gg_ml');
                    return $images;
                    break;
                }
                
				$data = json_decode($json, true);
			
				if(!is_array($data) || !$subj_id) {
                    $this->errors[] = 'Flickr '. esc_html__('Connection Error - check your URL', 'gg_ml');
                    return $images;
                    break;
                }
				if($data['stat'] != 'ok') {
                    $this->errors[] = 'Flickr - '. esc_html__('Invalid data - check your URL', 'gg_ml');
                    return $images;
                    break;
                }
				
				// images array basing on subject
				$img_data = ($subj == 'set') ? $data['photoset']['photo'] : $data['photos']['photo'];
				if(!is_array($img_data)) {
                    return $images;
                }
				
				foreach($img_data as $image) {
					if(isset($image['url_o']) && $max_img_size == 'max') {
                        $img_url = $image['url_o'];
                    }
					elseif(isset($image['url_h']) && in_array($max_img_size, array('max', 'big'))) {
                        $img_url = $image['url_h'];
                    } 
					else {
                        $img_url = $image['url_m'];
                    }
			
					$images[] = array(
						'url' 	=> $img_url, 
						'author'=> ($subj == 'set') ? $data['photoset']['ownername'] : $image['ownername'],
						'title'	=> gg_static::clean_emoticons($image['title']),
						'descr'	=> gg_static::clean_emoticons($image['description']['_content'])
					);
				}
				
				// total images
				$total = ($subj == 'set') ? $data['photoset']['total'] : $data['photos']['total'];
				
				$this->tot_images = $total;
				return $images;
				break;
			
			
			
			// Pinterest board images
			case 'pinterest':

				// get username + board
				$arr = explode('/', untrailingslashit(get_post_meta($this->gid, 'gg_username', true)));
				$un_n_board = $arr[ (count($arr) - 2) ] .'/'. $arr[ (count($arr) - 1) ];
				
				$to_fetch = 'https://api.pinterest.com/v3/pidgets/boards/'. $un_n_board .'/pins/';
				$json = json_decode((string)self::get_remote_contents($to_fetch), true);
				
				if(!isset($json['data']) || !isset($json['data']['pins'])) {
					return $images;	
				}
				
				foreach($json['data']['pins'] as $image) {
                    if($image['is_video'] || !isset($image['images']['564x'])) {
                        continue;    
                    }
                    
					$images[] = array(
						'url' 	=> $image['images']['564x']['url'],
						'author'=> $image['pinner']['full_name'],
						'title'	=> $image['domain'], 
						'descr'	=> gg_static::clean_emoticons(strip_tags($image['description']))
					);
				}
				
				return $images;
				break;
			
			
			// Instagram images
			case 'instagram' :
				return $images;
				
				/*
				$profile_url = get_post_meta($this->gid, 'gg_username', true);
				
				// Instagram v6.6 retrocompatibility - transform username into board URL
				if(!filter_var($profile_url, FILTER_VALIDATE_URL)) {
					$profile_url = 'https://www.instagram.com/'. $profile_url .'/';	
				}
				$profile_url .= '?__a=1'; 
				
				// retrieve instagram profile
				//$json = self::get_remote_contents($profile_url, true);
				if($json === false ) {die( esc_html__('Error connecting to Instagram', 'gg_ml') .' ..');}

				var_dump( esc_attr($json) );

				$data = json_decode($json);
				$images_array = $data->graphql->user->edge_owner_to_timeline_media->edges;

				$images = array();
				if(is_array($images_array)) {
					foreach($images_array as $image) {
						$image = $image->node;
						$txt_index = $image->edge_media_to_caption->edges;

						$images[] = array(
							'url' 	=> $image->display_url, 
							'author'=> $image->owner->username,
							'title'	=> '',
							'descr'	=> (is_array($txt_index) && count($txt_index)) ? preg_replace('~[\r\n]+~', '<br/>', $txt_index[0]->node->text) : ''
						);
					}
				}
				
				return $images;*/
				break;
			

			
			// Google Drive album images
			case 'g_drive' :
				include_once(GG_DIR .'/classes/source_helpers/gdrive_integration.php');
				$gdrive = new gg_gdrive_integration( get_post_meta($this->gid, 'gg_connect_id', true) );
				$images = $gdrive->get_images($this->extra, $this->search);

				if($images === false) {
                    $this->errors[] = 'GDrive '. esc_html__('Connection error', 'gg_ml');
                    return $images;
                    break;
                }
				if(!is_array($images)) {
                    $this->errors[] = 'GDrive '. $images;
                    return $images;
                    break;
                }
				
				return $images;
				break;
			
			
			
			// OneDrive album images
			case 'onedrive' :
				/*include_once(GG_DIR .'/classes/source_helpers/onedrive_integration.php');
				$onedrive = new gg_onedrive_integration( get_post_meta($this->gid, 'gg_connect_id', true) );
				$images = $onedrive->get_images($this->extra, $this->search);

				if($images === false) {die('<strong>'. esc_html__('Connection error', 'gg_ml') .'</strong>');}
				if(!is_array($images)) {die('<strong>'. $images .'</strong>');}
				
				return $images;*/
                return $images;
				break;
			
			
			
			// twitter images
			case 'twitter' :
                return $images;
				break;
			
                

			// tumblr images
			case 'tumblr' :
				// get clean domain
				$normalized = strtolower(untrailingslashit(get_post_meta($this->gid, 'gg_username', true)));
				$domain = str_replace(array('https://www.tumblr.com/dashboard/blog/', 'http://', 'https://', 'www.'), '', $normalized);
				
				for($a=0; $a <= 2; $a++) {
					$api_url = 'https://api.tumblr.com/v2/blog/'.$domain.'/posts?api_key=pcCK9NCjhSoA0Yv9TGoXI0vH6YzLRiqKPul9iC6OQ6Pr69l2MV&offset='. ($a * 20) .'&limit=20';
					
					$json = self::get_remote_contents($api_url);
					if($json === false) {
                        $this->errors[] = esc_html__('Error connecting to Tumblr', 'gg_ml');
                        return $images;
                        break;
                    }
					
					$data = json_decode($json, true);
					if(isset($data['meta']['status']) && ($data['meta']['status'] == 401 || $data['meta']['status'] == 404)) {
				        
                        $this->errors[] = 'Tumblr '. esc_html__('Connection Error - Check your blog URL', 'gg_ml');
                        return $images;
                        break;
					}
					
					// retrieve images - loop to get also multi-image posts
					$author = (isset($data['response']['blog']['title'])) ? $data['response']['blog']['title'] : '';
                    
					foreach($data['response']['posts'] as $post) {
						if(isset($post['photos'])) {
							// title
							$title = (isset($post['summary'])) ? $post['summary'] : '';
							
							// find main description
							if(isset($post['caption']) && !empty($post['caption'])) {
								$descr = $post['caption'];
							} else {
								$descr = (isset($post['excerpt'])) ? $post['excerpt'] : '';	
							}
	
							foreach ($post['photos'] as $img) {
								if(!empty($img['caption'])){ $descr = gg_static::clean_emoticons($img['caption']);}
								
								$images[] = array(
									'url' 	=> $img['original_size']['url'], 
									'author'=> $author,
									'title'	=> $title,
									'descr'	=> strip_tags(gg_static::clean_emoticons($descr), '<a>')
								);	
							}
						}
					}
				}
				
				return $images;
				break;
			


			// Real Media Library images
			case 'rml' :
				$folder_id = $this->extra;
				
				$query_images_args = array(
					'post_type' => 'attachment', 
					'post_mime_type' =>'image', 
					'post_status' => 'inherit', 
					'offset' => (($this->page - 1) * $this->per_page),
					'posts_per_page' => $this->per_page,
					
					'rml_folder' => $folder_id,
                	'orderby' => 'rml' // Enable custom order
				);
				
				if(!empty($this->search)) {
					$query_images_args['s'] = $this->search;
				}
				$query_images = new WP_Query($query_images_args);
			
				foreach($query_images->posts as $image) { 
					if(!empty($image->guid)) {
						$images[] = array(
							'id'	=> $image->ID,
							'path'	=> trim(gg_static::img_id_to_path($image->ID)),
							'url' 	=> trim($image->guid),
							'author'=> '',  
							'title'	=> $image->post_title,
							'descr'	=> $image->post_content
						);
					}
				}
				
				$this->tot_images = $query_images->found_posts;
				return $images;
				break;
				

			
			// nextGEN gallery images
			case 'ngg' :
				global $wpdb;
				$table_name = $wpdb->prefix ."ngg_pictures";
				
				// get ngg gallery basepath
				$base = gg_gall_static::get_ngg_galleries($this->extra); 
				if(!$base) {
                    $this->errors[] = esc_html__('Gallery does not exist. Check in nextGen Gallery panel', 'gg_ml');
                    return $images;
                    break;
                }
			
				// search part
				$search_q = (empty($this->search)) ? '' : "AND alttext LIKE '%". addslashes($this->search) ."%'";
				
				//get total
				$wpdb->query($wpdb->prepare("SELECT pid FROM ". $table_name ." WHERE galleryid = %d ".$search_q, $this->extra));
				$tot = $wpdb->num_rows;
				
				// get images
				$query = $wpdb->get_results("
					SELECT pid, filename, description, alttext FROM ". $table_name ." 
					WHERE galleryid = '". (int)$this->extra ."' ".$search_q."
					ORDER BY sortorder ASC, pid DESC
					LIMIT ". (int)(($this->page - 1) * $this->per_page) .", ". (int)$this->per_page ."", 
					ARRAY_A);
				
				if(is_array($query)) {
					foreach ($query as $img) {
						$images[] = array(
							'url' 	=> WP_CONTENT_URL .'/'. $base .'/'. $img['filename'], 
							'path' 	=> $base .'/'. $img['filename'],
							'author'=> '',
							'title'	=> (isset($img['alttext'])) ? $img['alttext'] : '', 
							'descr'	=> (isset($img['description'])) ? $img['description'] : '',
                            'tags'  => implode(',', wp_get_object_terms($img['pid'], 'ngg_tag', 'fields=names'))
						);
					}
				}

				$this->tot_images = $tot;
				return $images;
				break;
			
			
			
			// rss feed images
			case 'rss' :
				if(!function_exists('simplexml_load_string')) {
                    $this->errors[] = esc_html__("Your server doesn't support SimpleXML", 'gg_ml');
                    return $images;
                    break;
                }
				
				$url = get_post_meta($this->gid, 'gg_username', true);
				$feed = self::get_remote_contents($url, 'g_feed_api');
				if($feed === false) {
                    $this->errors[] = esc_html__('Error retrieving the feed', 'gg_ml');
                    return $images;
                    break;
                }
				
				// check to catch media:content easier
				if(strpos($feed, 'media:content') !== false) {
					$feed = str_replace('media:content', 'ggimage', $feed);	
				}
				
				$xml = simplexml_load_string($feed);
                if(!is_array($xml->channel->item)) {
                    return $images;
                }
                
				foreach ($xml->channel->item as $item) {
					if(isset($item->ggimage)) {
						$img_url = $item->ggimage->attributes()->url;
					} 
                    else {
                        $img_url = '';
                        
                        // grabs url from an IMG HTML tag string
                        preg_match_all('/img[^>]*src *= *["\']?([^"\']*)/i', $item->description, $output, PREG_PATTERN_ORDER);
                        if(isset($output[0][0])) {
                            $raw_url = $output[0][0];	
                            $img_url = substr($raw_url, 9);
                        }
					}
					
                    
                    // empty - check enclosure tag with "photo" or "IMAGE" type (feed made with zapier for Instagram or Facebook)
                    if(empty($img_url) && property_exists($item, 'enclosure')) {
                        $enclosure = (array)$item->enclosure;

                        if(isset($enclosure['@attributes'])) {
                            $encl = $enclosure['@attributes'];

                            if(isset($encl['url']) && isset($encl['type']) && in_array(strtolower($encl['type']), array('image', 'photo'))) {
                                $img_url = $encl['url'];        
                            }
                        }    
                    }
                    
                    
					// check url catched to avoid bad values
					if(!filter_var($img_url, FILTER_VALIDATE_URL)) {
						preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $img_url, $matched);	
						
                        if(is_array($matched) && isset($matched[0]) && is_array($matched[0]) && !empty($matched[0])) {
                            $img_url = $matched[0][0];
                        }
					}
                    
					
					if(!empty($img_url)) {
						$images[] = array(
							'url' 	=> $img_url, 
							'author'=> '',
							'title'	=> gg_static::clean_emoticons($item->title), 
							'descr'	=> substr(strip_tags($item->description), 0, 300) // only first 300 chars
						);
					}
				}
				
				return $images;
				break;
		}
	}
	
}

