<?php
/**
 * FeedSync Session Class
 *
 *
 * @package FeedSync
 * @subpackage Session
 * @since 3.5.94
 */


class FS_Session {

	private $db;

	private $table;

	public function __construct() {

		global $current_version;

		$this->db = new FS_Session_Database;

		$this->table = fsdb()->sessions;

		if ( 'feedsync_update_version' === get_ajax_action() && version_compare( $current_version, '3.6', '<=' ) ) {

			$this->backup_default_php_sessions();
		}

		// overwrite the session methods to store data in db vs session file.
		session_set_save_handler(
			array( $this, "open_session" ),
			array( $this, "close_session" ),
			array( $this, "read_session" ),
			array( $this, "write_session" ),
			array( $this, "destroy_session" ),
			array( $this, "garbage_collector" )
		);

		session_start();
	}

	public function backup_default_php_sessions() {
                
		// Get all the current session data from the server's storage
		$session_path = ini_get( 'session.save_path' );
		$session_files = scandir( $session_path );

		if ( empty( $_COOKIE['PHPSESSID'] ) ) {
			return;
		}

		$file = 'sess_' . $_COOKIE['PHPSESSID'];

		if ( file_exists( $session_path . '/' . $file ) ) {
			$session_data = file_get_contents( $session_path . '/' . $file );
			$session_id = substr( $file, 5 );

			$access = time();

			// Insert the session data into the database table
			$this->db->query( "INSERT IGNORE INTO " . $this->table . " (id, access, data) VALUES (?, ?, ?)" );
			$this->db->bind( 'sis', $session_id, $access, $session_data );

			if ( $this->db->execute() ) {
                                
				return;
			}
		}
	}


	/**
	 * This is executed when the session is being opened.
	 *
	 * @return void
	 */
	public function open_session() {

		if ( $this->db ) {

			return true;
		}

		return false;
	}

	/**
	 *  This is executed after the session write callback has been called.
	 *
	 * @return void
	 */
	public function close_session() {

		if ( $this->db->close() ) {

			return true;
		}

		return false;
	}

	/**
	 * This callback is called internally by PHP when the session starts.
	 *
	 * @param mixed $id
	 * @return void
	 */
	public function read_session( $id ) {
		$this->db->query( 'SELECT data FROM ' . $this->table . ' WHERE id = ?' );
		$this->db->bind( 's', $id );

		if ( $this->db->execute() ) {
			if ( $this->db->rowCount() > 0 ) {
				$row = $this->db->single();
				return $row['data'];
			}
		}

		return '';
	}

	/**
	 * This is called when the session needs to be saved and closed
	 *
	 * @param mixed $id
	 * @param mixed $data
	 * @return void
	 */
	public function write_session( $id, $data ) {
		$access = time();
		$this->db->query( 'REPLACE INTO ' . $this->table . ' (id, access, data) VALUES (?, ?, ?)' );
		$this->db->bind( 'sis', $id, $access, $data );

		if ( $this->db->execute() ) {
                        
			return true;
		}

		return false;
	}

	/**
	 * This is executed when a session is destroyed.
	 *
	 * @param mixed $id
	 * @return void
	 */
	public function destroy_session( $id ) {
		$this->db->query( 'DELETE FROM ' . $this->table . ' WHERE id = ?' );
		$this->db->bind( 's', $id );

		if ( $this->db->execute() ) {
			return true;
		}

		return false;
	}

	/**
	 * garbage collector : Callback is invoked internally by PHP periodically in order to purge old session data.
	 *
	 * @param int $max
	 * @return void
	 */
	public function garbage_collector( $max ) {
		$old = time() - $max;
		$this->db->query( 'DELETE FROM ' . $this->table . ' WHERE access < ?' );
		$this->db->bind( 'i', $old );

		if ( $this->db->execute() ) {
			return true;
		}

		return false;
	}
}