<?php

require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php';
require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-ftpext.php';

define('FS_METHOD', 'Log');

// If we're using DIRECT ONLY
//add_filter('request_filesystem_credentials', '_cred' );
//function _cred() {return true;}

add_filter('install_plugin_complete_actions', '_actions_dump');
function _actions_dump() { $GLOBALS['wp_filesystem']->dump_total_calls();  $GLOBALS['wp_filesystem']->dump_log(); }

class WP_Filesystem_Log extends WP_Filesystem_FtpExt {

	var $_log = array();
	var $func_calls = array();

	function WP_Filesystem_Log($one = null, $two = null, $three = null) {
		parent::WP_Filesystem_FTPExt($one, $two, $three);

	}

	function log($function, $args, $caller) {
		static $id = 0;
		$id++;
		
		if ( isset($this->func_calls[ $function ]) )
			$this->func_calls[ $function ]++;
		else
			$this->func_calls[ $function ] = 1;
		
		if ( $function == 'put_contents' )
			$args[1] = htmlentities(substr($args[1], 0, 20) . '....');
		
		$this->_log[$id] = compact('function', 'args', 'caller');
		return $id;
	}
	function set_result($id, $res) {
		if ( is_string($res) && strlen($res) > 20 )
			$res = substr($res, 0, 20) . '....';
		$this->_log[$id]['res'] = $res;
	}
	
	function dump_log() {
		var_dump($this->_log);
	}
	function dump_total_calls() {
		asort($this->func_calls);
		var_dump($this->func_calls);
	}
	function __destruct() {
		//$this->dump_log();
	}

	function connect() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function get_contents() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function get_contents_array() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function put_contents() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function cwd() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function chdir() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function chgrp() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function chmod() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function chown() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function owner() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function getchmod() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}
	
	function group() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function copy() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function move() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function delete() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function exists() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function is_file() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function is_dir() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function is_readable() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function is_writable() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function atime() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function mtime() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}
	function size() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function touch() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function mkdir() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function rmdir() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}

	function dirlist() {
		$function = __FUNCTION__;
		$args = func_get_args();
		$_caller = debug_backtrace();
		$_caller = $_caller[1];
		$caller = (isset($_caller['class']) ? $_caller['class'] . $_caller['type'] : '') . $_caller['function'];
		if ( isset($_caller['line']) )
			$caller .= '()#L' . $_caller['line'];
		if ( isset($_caller['file']) )
			$caller .= ' of ' . basename($_caller['file']);
		$id = $this->log($function, $args, $caller);
		$result = call_user_func_array( 'parent::' . $function, $args);
		$this->set_result($id, $result);
		return $result;
	}
}
