<?php
/**
 * Post/Page/CPT visiting assigned Segments
 *
 * @link       https://personalizewp.com/
 * @since      3.2.0 Merged into PWP
 * @since      1.0.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Segments
 */

namespace PersonalizeWP\Segments;

use PersonalizeWP\Segments\Base;
use PersonalizeWP\Model\Activity;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * Page/Post/URL Segments
 *
 * Handles Activities with type `home`, `post`, `tax`
 */
class Page_URL extends Base {

	/**
	 * Types of Activity to process
	 *
	 * @var array
	 */
	protected $activity_types = array( 'home', 'post', 'tax' );

	/**
	 * Types of Segment to process
	 *
	 * @var array
	 */
	protected $segment_types = array( 'page' );

	/**
	 * Process a `page` type Activity for Segments
	 *
	 * @param Activity $activity Activity object
	 *
	 * @return void
	 */
	public function process_activity( $activity ) {

		// Double check
		if ( ! empty( $activity ) && ! in_array( $activity->activity_type, $this->activity_types, true ) ) {
			return;
		}

		if ( ! isset( $this->segments ) ) {
			$this->segments = $this->get_segments();
		}

		if ( empty( $this->segments ) ) {
			return;
		}

		// Clean Up URL, removing domain & query parameters
		$url = wp_parse_url( $activity->url, PHP_URL_PATH );
		foreach ( $this->segments as $segment ) {
			// Not tracking any page/URL.
			if ( empty( $segment['conditions'] ) ) {
				continue;
			}

			$args = [
				'activity'   => $activity,
				'conditions' => json_decode( $segment['conditions'], true ),
				'operator'   => $segment['operator'],
				'url'        => $url,
			];
			if ( $this->activity_has_matched_conditions( $args ) ) {
				$this->assign_contact_to_segment( $segment['ID'], $activity->contact_id );
			}
		}
	}

	/**
	 * Test condition against Page URL criteria, full URL, URL regex, or CPT ID match.
	 *
	 * @since 2.3.0
	 *
	 * @param array $args {
	 *     Array of args to use for matching the condition.
	 *
	 *     @type Activity $activity  Activity object
	 *     @type mixed    $condition Index of all conditions, or URL/regex to compare
	 *     @type mixed    $options   CPT ID, (legacy) URL condition to match, or URL options/qualifier
	 *     @type string   $url       URL Path of Activity
	 * }
	 *
	 * @return boolean
	 */
	protected function condition_has_matched_criteria( $args ) {

		// Note: Condition is stored as options as the 'condition' is just an array index.
		list( 'activity' => $activity, 'condition' => $condition, 'options' => $options, 'url' => $url ) = $args;

		$options = trim( $options );

		// In legacy format 'options' mapped to 'condition', so 'options' will contain numeric ID or string URL, and 'condition' is always a numeric index.
		// In updated format 'options' can contain either numeric ID, or string of 'url' or 'regex'. 'condition' is numeric for ID, string for URL.

		if (
			( is_numeric( $condition ) || 0 === (int) $condition ) &&
			is_numeric( $options )
		) {
			// Supporting direct object ID condition.
			$condition = (int) $options;
			$options   = null;
		} elseif (
			( is_numeric( $condition ) || 0 === (int) $condition ) &&
			! in_array( $options, array( 'regex', 'url' ), true )
		) {
			// Supporting legacy URL based condition, without newer url/regex qualifier.
			$condition = $options;
			$options   = null;
		}

		// Matching CPT ID, when it's a CPT type activity
		if ( 'post' === $activity->activity_type && ! empty( $condition ) &&
			isset( $activity->object_id ) && (int) $activity->object_id === (int) $condition ) {

			return true;
		}

		$is_url   = empty( $options ) || 'url' === $options;
		$is_regex = 'regex' === $options;

		// Check for simplier string match. Must fully match the URL. Note: case in-sensitive matching.
		if ( $is_url && strtolower( $url ) === strtolower( $condition ) ) {
			return true;
		}
		// With sites having many subdomains or TLD, we need to use regex.
		if ( $is_regex && 1 === preg_match( '/' . $condition . '/i', $url ) ) {
			return true;
		}
		return false;
	}
}
