<?php
// REDIRECT ENGINE


// performs redirect restriction
function pc_do_redirect_restr() {
	include_once(PC_DIR . '/functions.php');
	global $pc_restr_wizard;
	
	// main redirect page
	$orig_redirect_val = get_option('pg_redirect_page');
	$redirect_url = pc_man_redirects('pg_redirect_page');
	
	// blocked users redirect page
	$blocked_users_url = pc_man_redirects('pg_blocked_users_redirect');
	$final_redirect_url = (pc_user_logged(false) && $blocked_users_url) ? $blocked_users_url : $redirect_url;
	
	// only if redirect option is setted and redirect URL is different from current one (to avoid loops)
	if(empty($final_redirect_url) || $final_redirect_url == pc_curr_url()) {return false;}



	//////////////////////////////////////////////////////////////
	// complete website lock
	if(get_option('pg_complete_lock') && pc_user_check('all', '', true) !== 1) { // use pc_user_check to let WP users to test restrictions
		global $post;
		
		$excluded_pages = (filter_var($orig_redirect_val, FILTER_VALIDATE_INT)) ? array($orig_redirect_val) : array();
		$excluded_pages = array_merge($excluded_pages, (array)get_option('pg_complete_lock_excluded_pages', array()));
		
		// PC-FILTER - add page IDS to exclude from complete site lock - page IDs array
		$excluded_pages = apply_filters('pc_complete_lock_exceptions', $excluded_pages);
		
		// exceptions check
		foreach((array)$excluded_pages as $pag_id) {				
			if($pag_id == $post->ID) {
				$exception_page = true;
				break;		
			}
			
			// WPML integration - if current page is translation of an exception
			elseif(pc_wpml_translated_pag_id($pag_id) == $post->ID) {
				$exception_page = true;
				break;	
			}
		}
		
		if(!isset($exception_page)) {
			pc_redirect($final_redirect_url);
		}	
	}
	
	
	
	//////////////////////////////////////////////////////////////
	// single page/post redirect
	else if(is_page() || is_single()) {
		global $post;				
		
		// PC-ACTION - forces page restriction - passes false and page object
		if(apply_filters('pc_forced_page_restriction', false, $post)) {
			pc_redirect($final_redirect_url);		
		}
		
		$post_restr = $pc_restr_wizard->get_entity_full_restr('post', $post->ID);
		if(isset($post_restr['redirect']) && $pc_restr_wizard->user_passes_restr($post_restr['redirect']) !== 1) {
			pc_redirect($final_redirect_url);
		}
	}
	
	
	
	//////////////////////////////////////////////////////////////
	// if is category or archive
	else if(is_category() || is_archive()) {
		$term_id = get_query_var('cat');
		
		// PC-ACTION - forces term restriction - passes false and term ID
		if(apply_filters('pc_forced_term_restriction', false, $term_id)) {
			pc_redirect($final_redirect_url);
		}
		
		$term_data = pc_term_obj_from_term_id($term_id);
		$term_restr = $pc_restr_wizard->get_entity_full_restr('term', $term_id, $term_data);

		if(isset($term_restr['redirect']) && $pc_restr_wizard->user_passes_restr($term_restr['redirect']) !== 1) {
			pc_redirect($final_redirect_url);
		}
	}
	
	
	
	//////////////////////////////////////////////////////////////
	// WooCommerce category
	if(function_exists('is_product_category') && is_product_category()) {
		$term_slug = get_query_var('product_cat');
		$term_data = get_term_by('slug', $term_slug, 'product_cat');

		if($term_data) {
			$term_restr = $pc_restr_wizard->get_entity_full_restr('term', $term_id, $term_data);

			if(isset($term_restr['redirect']) && $pc_restr_wizard->user_passes_restr($term_restr['redirect']) !== 1) {
				pc_redirect($final_redirect_url);
			}
		}
	}


	
	//////////////////////////////////////////////////////////////
	//// PC-FILTER custom restriction (URL based) - associative array('url' => array('allowed' => , 'blocked' => ))
	// URL passes through preg_match, then supports regular expressions
	$restrictet_urls = apply_filters('pc_custom_restriction', array());
	if(is_array($restrictet_urls) && count($restrictet_urls)) {
		$curr_url = pc_curr_url();
		
		foreach((array)$restrictet_urls as $url => $val) {
			if(!isset($val['allowed']) || empty($val['allowed'])) {continue;}
			$blocked = (isset($val['blocked'])) ? $val['blocked'] : ''; 
			
			// differentiate between URL and regexp
			if(filter_var($url, FILTER_VALIDATE_URL)) {
				
				// strip arguments if are not included in restricted URL
				if(strpos($url, '?') === false && strpos($curr_url, '?') !== false) {
					$raw = explode('?', $curr_url);
					$curr_url = $raw[0];	
				}
				
				if($url == $curr_url) {
					if(pc_user_check($val['allowed'], $blocked, true) !== 1) {
						pc_redirect($final_redirect_url);
					}		
				}
			}
			
			else {
				// sanitize for patterns
				if(substr($url, 0, 1) != '/') {$url = '/'. $url;}
				if(substr($url, -1) != '/') {$url .= '/';}
				
				if(preg_match((string)$url, $curr_url)) {
					if(pc_user_check($val['allowed'], $blocked, true) !== 1) {
						pc_redirect($final_redirect_url);
					}	
				}
			}
		}	
	}
}
add_action('template_redirect', 'pc_do_redirect_restr', 1);



/* Performs the redirect - also sets last restricted page's URL for login redirect */
function pc_redirect($redir_url, $no_lru = false) {
	include_once(PC_DIR . '/functions.php');
	
	if(get_option('pg_redirect_back_after_login') && pc_curr_url() && !$no_lru) {
		$_SESSION['pc_last_restricted'] = pc_curr_url();
	}	
	
	header('location: '. $redir_url);
	die();	
}





/* CHECK IF USER CAN ACCESS A RESTRICTED PAGE
 *
 * @param subj = subject to analyze (category or page)
 * @subj_data = data object of the subject
 */
function pc_redirect_check($subj, $subj_data, $taxonomy = false) {
	
	if($subj == 'page') {
		$allowed = get_post_meta($subj_data->ID, 'pg_redirect', true);
		
		// if has restrictions - ignore parents
		if($allowed && is_array($allowed)) {
			$allowed = trim(implode(',', $allowed));
			
			if($allowed == 'unlogged') {
				include_once(PC_DIR . '/functions.php');
				
				// where to move users to a custom page
				$custom_unl_redir = get_post_meta($subj_data->ID, 'pg_unlogged_redirect', true);
				if($custom_unl_redir) {
					$GLOBALS['pc_unlogged_custom_redirect'][$subj_data->ID] = get_permalink( pc_wpml_translated_pag_id($custom_unl_redir));	
				}
				
				return (pc_user_check('unlogged', '', true) === 1) ? true : false;	
			}
			
			return (!empty($allowed) && pc_user_check($allowed, '', true) !== 1) ? false : true;
		}
		
		// parent page
		else {
			if($subj_data->post_parent) {
				$parent = get_post($subj_data->post_parent);
				return pc_redirect_check('page', $parent); // recursive	
			}
			else {return true;}
		}
	}
	
	// category
	else {
		$allowed = get_option('taxonomy_'.$subj_data->term_id.'_pg_redirect');
		
		// if has restrictions - ignore parentss
		if($allowed) {
			return (pc_user_check($allowed, '', true) !== 1) ? false : true;
		}
		
		// parent category
		else {
			if(isset($subj_data->category_parent) && $subj_data->category_parent) {
				$parent = get_term_by('id', $subj_data->category_parent,  $taxonomy);
				
				// recursive
				return pc_redirect_check('category', $parent, $taxonomy);	
			}
			else {return true;}
		}
	}
}



/////////////////////////////////////////////////////////////////////



// CUSTOM URL-BASED RESTRICTIONS (settings driven)
function pc_url_based_restrictions($restrictions) {
	if(is_admin()) {return $restrictions;}
	
	$urls = (array)get_option('pg_cr_url', array());
	if(empty($urls)) {return $restrictions;}
	
	$allow = (array)get_option('pg_cr_allow', array()); 
	$block = (array)get_option('pg_cr_block', array()); 
	
	$a = 0;
	foreach($urls as $url) {
		if(isset($allow[$a]) && !empty($allow[$a])) {
			$restrictions[$url] = array(
				'allowed' => implode(',', $allow[$a]), 
				'blocked' => implode(',', $block[$a])
			);	
		}
		$a++;
	}
	
	return $restrictions;
}
add_filter('pc_custom_restriction', 'pc_url_based_restrictions', 100);



///////////////////////////////////////////////////////////////////////



// REMOVE RESTRICTED TERMS / POSTS FROM WP_QUERY
function pc_query_filter($query) {
	include_once(PC_DIR . '/functions.php');
	global $pc_restr_wizard;
	
	if(isset($GLOBALS['pc_is_fetching_posts_restr'])) {return $query;}
	if(($query->is_admin && !defined('DOING_AJAX')) || $query->is_single || $query->is_page || !isset($GLOBALS['pc_query_filter_post_array'])) {return $query;}
	
	// PC-FILTER - alterate posts restriction cache - passes array defined in classes/posts_restr_cache.php
	$pr = apply_filters('pc_posts_restr', $GLOBALS['pc_query_filter_post_array']);
	if(empty($pr)) {return $query;}
	
	
	// check one by one
	$to_remove = array();
	foreach($pr as $post_id => $restr) {
		if($pc_restr_wizard->user_passes_restr($restr) !== 1) {
			$to_remove[] = $post_id;		
		}
	}
	
	
	// apply
	if(!empty($to_remove)) {
		$query->set('post__not_in', $to_remove);	
	}
	
	return $query;
}
add_filter('pre_get_posts', 'pc_query_filter', 9999);



////////////////////////////////////////////////////////////////////////////////////////////////////



// REMOVE TERMS FROM CATEGORIES WIDGET
function pc_widget_categories_args_filter($cat_args) {
	include_once(PC_DIR . '/functions.php');
	global $pc_query_filter_post_array;
	
	// remove restricted terms
	$exclude_cats = pc_query_filter_cat_array(); 
	if(count($exclude_cats) > 0) {
		if (isset($cat_args['exclude']) && $cat_args['exclude']) {
			$cat_args['exclude'] = $cat_args['exclude'] . ',' . implode(',', $exclude_cats);
		} else {
			$cat_args['exclude'] = implode(',', $exclude_cats);
		}
	}
	   
	return $cat_args;
}
add_filter('widget_categories_args', 'pc_widget_categories_args_filter', 10, 1 );



// create an array of restricted terms
function pc_query_filter_cat_array() {
	
	// be sure class is initialized
	if(!isset($GLOBALS['pc_restr_wizard'])) {
		include_once(PC_DIR .'/classes/restrictions_wizard.php');
		pc_init_restr_wizard();	
	}
	global $pc_restr_wizard;
	

	if(isset($GLOBALS['pc_query_filter_cat_array'])) {
		return $GLOBALS['pc_query_filter_cat_array']; // cache	
	}
	
	$exclude_array = array();
	$args = array( 'hide_empty' => 0);
	$terms = get_terms( pc_affected_tax(), $args );
	
	foreach($terms as $term) { 
		$term_restr = $pc_restr_wizard->get_entity_full_restr('term', $term->term_id, $term);
		if(!is_array($term_restr) || !isset($term_restr['redirect'])) {continue;}

		if($pc_restr_wizard->user_passes_restr($term_restr['redirect']) !== 1) {
			$exclude_array[] = '-'.$term->term_id;
		}	
	}
	
	// PC-FILTER - these categories will be hidden from queries - passes array of already restricted categories ID (negative numbers)
	$exclude_array = apply_filters('pc_cats_wp_query_filter', $exclude_array);
	
	$GLOBALS['pc_query_filter_cat_array'] = $exclude_array;
	return $exclude_array;	
}

