403Webshell
Server IP : 207.135.97.11  /  Your IP : 172.19.0.1
Web Server : LiteSpeed
System : Linux 6d372a2d2e33 5.14.0-611.24.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jan 23 11:42:43 UTC 2026 x86_64
User : nobody ( 65534)
PHP Version : 8.3.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/html/ed.net.au/wp-content/plugins/post-views-counter/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/ed.net.au/wp-content/plugins/post-views-counter/includes/class-traffic-signals.php
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
	exit;

/**
 * Post_Views_Counter_Traffic_Signals class.
 *
 * @class Post_Views_Counter_Traffic_Signals
 */
class Post_Views_Counter_Traffic_Signals {

	/**
	 * Class constructor.
	 *
	 * @return void
	 */
	public function __construct() {
		// early exit if traffic signals are disabled
		if ( ! $this->is_enabled() )
			return;

		// actions
		add_action( 'admin_init', [ $this, 'register_signals_column' ] );
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_signals_assets' ] );
		add_action( 'pvc_after_update_post_views_count', [ $this, 'invalidate_signal_cache' ], 10, 1 );
		add_action( 'pvc_flush_cached_counts', [ $this, 'flush_all_signals_cache' ] );
		add_action( 'pvc_reset_counts', [ $this, 'flush_all_signals_cache' ] );
		add_action( 'transition_post_status', [ $this, 'invalidate_signal_cache_on_status_change' ], 10, 3 );
		add_action( 'deleted_post', [ $this, 'invalidate_signal_cache' ], 10, 1 );
	}

	/**
	 * Check if traffic signals are enabled.
	 *
	 * Allows filters to disable traffic signals when needed.
	 * Example: add_filter( 'pvc_enable_traffic_signals', '__return_false' );
	 *
	 * @return bool True if enabled, false otherwise
	 */
	private function is_enabled() {
		/**
		 * Filter whether traffic signals should be enabled.
		 *
		 * Filters can use this to disable traffic signals and prevent duplicates.
		 *
		 * @param bool $enabled Whether traffic signals are enabled (default: true)
		 */
		return apply_filters( 'pvc_enable_traffic_signals', true );
	}

	/**
	 * Register traffic signals column for post types.
	 *
	 * @return void
	 */
	public function register_signals_column() {
		// check if traffic signals are enabled
		if ( ! $this->is_enabled() )
			return;

		// get main instance
		$pvc = Post_Views_Counter();

		// is posts views column active?
		if ( ! $pvc->options['display']['post_views_column'] )
			return;

		// get post types
		$post_types = $pvc->options['general']['post_types_count'];

		// any post types?
		if ( ! empty( $post_types ) ) {
			foreach ( $post_types as $post_type ) {
				if ( $post_type !== 'attachment' ) {
					add_filter( 'manage_' . $post_type . '_posts_columns', [ $this, 'add_traffic_signal_column' ], 10, 1 );
					add_filter( 'manage_edit-' . $post_type . '_columns', [ $this, 'add_traffic_signal_column' ], 20 );
					add_action( 'manage_' . $post_type . '_posts_custom_column', [ $this, 'render_traffic_signal_column' ], 10, 2 );
				}
			}
		}
	}

	/**
	 * Add traffic signals column to post list.
	 *
	 * @param array $columns Existing columns
	 * @return array Modified columns
	 */
	public function add_traffic_signal_column( $columns ) {
		// find position of views column
		$views_position = array_search( 'post_views', array_keys( $columns ), true );

		$signal_column = [
			'traffic_signal' => '<span class="pvc-signal-header" title="' . esc_attr__( 'Traffic Signals', 'post-views-counter' ) . '"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M14.828 14.828 21 21"/><path d="M21 16v5h-5"/><path d="m21 3-9 9-4-4-6 6"/><path d="M21 8V3h-5"/></svg><span class="screen-reader-text">' . esc_html__( 'Traffic Signals', 'post-views-counter' ) . '</span></span>'
		];

		if ( $views_position !== false ) {
			// insert after views column
			$before = array_slice( $columns, 0, $views_position + 1, true );
			$after = array_slice( $columns, $views_position + 1, null, true );

			$columns = array_merge( $before, $signal_column, $after );
		}

		return $columns;
	}

	/**
	 * Render traffic signal column content.
	 *
	 * @param string $column_name Column name
	 * @param int    $post_id Post ID
	 * @return void
	 */
	public function render_traffic_signal_column( $column_name, $post_id ) {
		if ( $column_name !== 'traffic_signal' ) {
			return;
		}

		// check if user can see stats
		if ( apply_filters( 'pvc_admin_display_post_views', true, $post_id ) === false ) {
			return;
		}

		// get signal status
		$signal = $this->detect_signal( $post_id );

		if ( $signal === null ) {
			// smart silence - no unusual activity
			printf(
				'<span class="pvc-signal" role="tooltip" aria-label="%s" data-microtip-position="top"><span class="pvc-insight pvc-insight-silence"></span></span>',
				esc_attr__( 'No unusual activity detected.', 'post-views-counter' )
			);
		} else {
			// anomaly detected - generic signal
			printf(
				'<span class="pvc-signal" role="tooltip" aria-label="%s" data-microtip-position="top" data-microtip-size="medium"><span class="pvc-insight pvc-insight-anomaly"></span></span>',
				esc_attr__( 'Unusual traffic pattern detected. More insights available in Post Views Counter Pro.', 'post-views-counter' )
			);
		}
	}

	/**
	 * Detect traffic signal using simple Month-over-Month comparison.
	 *
	 * @param int $post_id Post ID
	 * @return array|null Signal data or null if no anomaly
	 */
	private function detect_signal( $post_id ) {
		// check cache first
		$cache_key = 'pvc_signal_' . $post_id;
		$cache_group = 'post_views_counter';
		$cached = wp_cache_get( $cache_key, $cache_group );

		if ( $cached !== false ) {
			return $cached;
		}

		// get current month views
		$current_date = new DateTime();
		$current_period = $current_date->format( 'Ym' );

		$current_total = (int) pvc_get_post_views( $post_id, $current_period );

		// minimum views threshold
		if ( $current_total < 10 ) {
			wp_cache_set( $cache_key, null, $cache_group, HOUR_IN_SECONDS );
			return null;
		}

		// get previous month views (same number of days as current month-to-date)
		$prev_date = clone $current_date;
		$prev_date->modify( '-1 month' );
		$prev_year = $prev_date->format( 'Y' );
		$prev_month = $prev_date->format( 'm' );
		$prev_last_day = (int) $prev_date->format( 't' );
		$current_day = (int) $current_date->format( 'd' );
		// compare against the same number of days from last month (clamp to last day)
		$end_day = min( $current_day, $prev_last_day );

		$prev_start = (int) ( $prev_year . $prev_month . '01' );
		$prev_end = (int) ( $prev_year . $prev_month . str_pad( (string) $end_day, 2, '0', STR_PAD_LEFT ) );

		$prev_total = (int) pvc_get_post_views(
			$post_id,
			'',
			[
				'type'         => 0,
				'period_range' => [ $prev_start, $prev_end ]
			]
		);

		// need both periods to compare
		if ( $prev_total < 10 ) {
			wp_cache_set( $cache_key, null, $cache_group, HOUR_IN_SECONDS );
			return null;
		}

		// calculate change percentage
		$change_percent = ( ( $current_total - $prev_total ) / $prev_total ) * 100;

		// threshold: 25% change (up or down)
		if ( abs( $change_percent ) > 25 ) {
			$result = [
				'anomaly' => true,
				'change_percent' => round( $change_percent )
			];
		} else {
			$result = null;
		}

		// cache for 1 hour
		wp_cache_set( $cache_key, $result, $cache_group, HOUR_IN_SECONDS );

		return $result;
	}

	/**
	 * Enqueue traffic signals assets on post list screens.
	 *
	 * @param string $hook Current admin page hook
	 * @return void
	 */
	public function enqueue_signals_assets( $hook ) {
		// check if traffic signals are enabled
		if ( ! $this->is_enabled() )
			return;

		// only on post list screens
		if ( ! in_array( $hook, [ 'edit.php', 'upload.php' ], true ) )
			return;

		$screen = get_current_screen();
		$pvc = Post_Views_Counter();
		$post_types = (array) $pvc->options['general']['post_types_count'];

		// check if traffic signals should be displayed
		if ( ! $screen || ! $screen->post_type )
			return;

		// check if this post type has view counting enabled
		if ( ! in_array( $screen->post_type, $post_types, true ) )
			return;

		// enqueue Microtip CSS for tooltips
		wp_enqueue_style( 'pvc-microtip', POST_VIEWS_COUNTER_URL . '/assets/microtip/microtip.min.css', [], '1.0.0' );
		
		// enqueue admin-columns CSS for signal icons (if not already enqueued by modal)
		if ( ! wp_style_is( 'pvc-admin-columns', 'enqueued' ) ) {
			wp_enqueue_style( 'pvc-admin-columns', POST_VIEWS_COUNTER_URL . '/css/admin-columns.css', [], $pvc->defaults['version'] );
		}
	}

	/**
	 * Invalidate signal cache when view counts update.
	 *
	 * @param int $post_id Post ID
	 * @return void
	 */
	public function invalidate_signal_cache( $post_id ) {
		$cache_key = 'pvc_signal_' . $post_id;
		$cache_group = 'post_views_counter';
		wp_cache_delete( $cache_key, $cache_group );
	}

	/**
	 * Flush all signals cache (called on period resets, cache flushes).
	 *
	 * @return void
	 */
	public function flush_all_signals_cache() {
		// WordPress doesn't support wildcard cache deletion
		// We rely on natural cache expiration (1 hour) for bulk invalidation
		
		// For persistent object caches (Redis, Memcached), implement via plugin-specific flush
		if ( wp_using_ext_object_cache() ) {
			do_action( 'pvc_flush_signals_cache' );
		}
	}

	/**
	 * Invalidate signal cache when post status changes.
	 *
	 * @param string  $new_status New post status
	 * @param string  $old_status Old post status
	 * @param WP_Post $post Post object
	 * @return void
	 */
	public function invalidate_signal_cache_on_status_change( $new_status, $old_status, $post ) {
		// only invalidate if status actually changed
		if ( $new_status !== $old_status ) {
			$this->invalidate_signal_cache( $post->ID );
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit