array(), 'footer' => array() ); /** Wordpress to_do scripts, used both by mergescripts and admin_bar */ private $to_do; /** Used for save the handles want to deregister both by mmerge_scripts and check_cache method */ private $deregister = array('style' => array(), 'script' => array()); /** Handles that ara not detected by wp_print_scripts, we get it from wp_header and wp_footer we compare the rest_of_handles option with the registered handles generated by wordpress */ private $restOfHandles = array('header' => array(), 'footer' => array()); /** Check whether the method is already executed. This is to prevent the method from executed by other plugins */ private $is_executed = array('merge_styles' => false, 'merge_scripts' => false, 'footer_scripts' => false, 'header_scripts' => false ); public function __construct () { $this->options = get_option(APHMS_OPTION); // echo '
'; print_r($this->options );
	}
	
	public function init()
	{
		add_action('init', array($this, 'run_plugin'));
		add_filter('script_loader_src', array($this, 'remove_query_string'));
		add_filter('style_loader_src', array($this, 'remove_query_string'));
	}
	
	public function remove_query_string( $src )
	{
		if (strpos($src, $this->options['script_file_name'])
			|| strpos($src, $this->options['style_file_name'])) {
			$src = remove_query_arg('ver', $src);
		}	
		return $src;
	}
	
	public function run_plugin()
	{
		$admin_bar = is_admin_bar_showing();
		if (is_admin()
			|| (is_user_logged_in() && !$admin_bar)
			|| ($admin_bar && $this->options['manage_scripts']))
		{
			return;
		}
		
		if (isset($this->options['merge_scripts'])) {
			
			add_action( 'wp_print_scripts', array( $this, 'merge_scripts' ), 999 );
			add_action( 'wp_head', array( $this, 'deregister_script' ), 7 );
			add_action( 'wp_footer', array( $this, 'deregister_script' ) );
		}
		
		if (isset($this->options['merge_styles'])) {
			add_action( 'wp_print_styles', array( $this, 'merge_styles' ), 10 );
		}
	}

	public function merge_styles()
	{
		if ($this->is_executed['merge_styles'])
			return;
		
		if (!$this->options['merge_styles'])
			return;
		
		global $wp_styles;

		$queues = $wp_styles->queue;
		$wp_styles->all_deps($queues);	
		$this->to_do = $wp_styles->to_do;
		
		//File Name
		$file 			= Aphms_Helper::merge_file_path('style');
		$use_cache		= $this->check_cache('style');
		// $use_cache		= false;
		
		if (!$use_cache)
		{
			$merged_style 	= '';
			$list_handles 	= array();
			// echo '
'; print_r($this->to_do);
			foreach( $this->to_do as $handle) 
			{
				if (!key_exists($handle, $wp_styles->registered))
					continue;
				
				$file_path = $this->file_path($wp_styles->registered[$handle]->src);
				
				/**	We have to save the handle outside the file_exists to make sure all handle are saved,
					this is useful for cheching cache
				*/
				$list_handles[] = $handle;
				if (file_exists($file_path))
				{
					require_once 'minifier/minify/src/Minify.php';
					require_once 'minifier/minify/src/CSS.php';
					require_once 'minifier/minify/src/Exception.php';
					require_once 'minifier/minify/Converter.php';
					
					$this->deregister['style'][] = $handle;
					$minifier = new MatthiasMullie\Minify\CSS($file_path);
					$minifier->setToPath( $file['file_path'] );
					$merged_style .=  $minifier->minify();
				}
			}
			
			if ($merged_style) {
				file_put_contents($file['file_path'], '/* APH Merge Scripts v'.APHMS_PLUGIN_VERSION.' */' . "\r\n" . $merged_style);
			}
			// echo '
'; print_r($list_handles);
			// update current handles
			$this->options['curr_handles']['style']['time'] = time();
			$this->options['curr_handles']['style']['handles'] = $list_handles;
			update_option(APHMS_OPTION, $this->options);
		}

		foreach ($this->deregister['style'] as $handle)
		{
			wp_deregister_style($handle);
		}
		
		$time = @$this->options['style_query_string'] ? '?rand=' . time() : '';
		wp_enqueue_style('merged-script',  $file['file_url'] . $time, '', APHMS_PLUGIN_VERSION);
		
		$this->is_executed['merge_styles'] = true;
	}
	
	public function merge_scripts($position)
	{
		if ($this->is_executed['merge_scripts'])
			return;
		
		if ($this->options['merge_scripts'] == 0)
			return;
		
		global $wp_scripts;

		$wp_scripts->all_deps($wp_scripts->queue);	
		$this->to_do  	= $wp_scripts->to_do;

		/* Used for either merged  path or enqueue url */
		$file = Aphms_Helper::merge_file_path('script');
		
		// Check cache
		$use_cache	= $this->check_cache('script');
		// $use_cache	= false;
		
		if (!$use_cache)
		{
			$merged_script	= '';
			$list_handles 	= array();

			// Loop javascript files and save to $merged_script variable
			foreach( $this->to_do as $handle) 
			{
				if ($this->skip_handle($handle) || !key_exists($handle, $wp_scripts->registered))
					continue;
				
				$obj = $wp_scripts->registered[$handle];
						
				// wp_localize_script
				$localize = '';
				if (@key_exists('data', $obj->extra))
					$localize = $obj->extra['data'] . ';';
				
				$file_path = $this->file_path($obj->src);
				
				/**	We have to save the handle outside the file_exists to make sure all handle are saved,
					this is useful for cheching cache
				*/
				$list_handles[] = $handle;	
				if (file_exists($file_path))
				{					
					$merged_script .= '/* Handle: ' . $handle . ' */' . "\r\n\r\n" . $localize . file_get_contents($file_path) . ';' . "\r\n\r\n";
					$this->deregister['script'][] = $handle;
				}
			}
		
			// Merge rest of scripts
			foreach( $this->options['rest_of_handles']['script'] as $pos => $handles) 
			{
				foreach ($handles as $handle => $arr)
				{
					if (in_array($handle, $this->to_do) || $this->skip_handle($handle))
						continue;
					
					// wp_localize_script
					$localize = '';
					if (@key_exists('data', $arr['extra']))
						$localize = $arr['extra']['data'] . ';';
					
					$file_path = $this->file_path($arr['src']);
					if (file_exists($file_path))
					{
						$list_handles[] = $handle;
						$merged_script .= '/* Handle: ' . $handle . ' */' . "\r\n\r\n" . $localize . file_get_contents($file_path) . ';' . "\r\n\r\n";
						$this->deregister['script'][] = $handle;
					}
				}
			}
			
			// Save $merged_script into file
			if ($merged_script) {
				$this->write_js_file($merged_script, $file);
			}
			
			// update current handles
			$this->options['curr_handles']['script']['time'] = time();
			$this->options['curr_handles']['script']['handles'] = $list_handles;
			update_option(APHMS_OPTION, $this->options);
		}
		
		foreach ($this->deregister['script'] as $handle)
		{
			wp_deregister_script($handle);
		}
		
		$location = $this->options['merge_scripts'] == 2 ? true : false;
		$time = $this->options['script_query_string'] ? '?rand=' . time() : '';
		wp_enqueue_script('merged-script',  $file['file_url'] . $time, '', APHMS_PLUGIN_VERSION, $location);
		
		$this->is_executed['merge_scripts'] = true;
	}
	
	private function write_js_file($merged_script, $file)
	{
		if ($this->options['minify_script']) {
			
			require_once 'minifier/minify/src/Minify.php';
			require_once 'minifier/minify/src/JS.php';
			require_once 'minifier/minify/src/Exception.php';
					
			$minifier = new MatthiasMullie\Minify\JS($merged_script);
			$merged_script = $minifier->minify();
		}
		
		$merged_script = '/*! APH Merge Scripts v'.APHMS_PLUGIN_VERSION.' */' . "\r\n" . $merged_script;
		file_put_contents($file['file_path'], $merged_script);
		
		if ($this->options['minify_script'] == 2)
		{
			if (function_exists('exec'))
			{
				$plugin_dir = 'wp-content' . APHMS_DS . 'plugins' . APHMS_DS . APHMS_PLUGIN_DIR_NAME;
				$yui_jar = $plugin_dir . APHMS_DS . 'includes' . APHMS_DS . 'minifier/' . APHMS_DS . 'yuicompressor' . APHMS_DS . 'yuicompressor.jar';
				$cmd = 'java -jar ' . $yui_jar . ' ' . $file['file_rel_path'] . ' -o ' . $file['file_rel_path'];
						
				@exec($cmd . ' 2>&1');
			}
		}
	}
	
	/**
		Check cache make sure that all handles are processed
	*/
	private function check_cache($type)
	{
		if (!$this->options['curr_handles'][$type]['time'] 
			|| !$this->options['curr_handles'][$type]['handles']
		)
			return false;
		
		// Check whether the merged file exists
		$file = Aphms_Helper::merge_file_path($type);
		if (!file_exists($file['file_path']))
			return false;
		
		// Check whether cache is expired
		$date = $this->options['curr_handles'][$type]['time'];
		$expired = strtotime('+'.$this->options['cache_age'].' day', $date);
					
		if ($expired < time())
			return false;
		
		
		$list_of_handles = array_merge($this->to_do, 
											array_keys($this->options['rest_of_handles'][$type]['header']),
											array_keys($this->options['rest_of_handles'][$type]['footer'])
										);
		/* if ($type == 'script')
		{
			echo '
'; print_r($list_of_handles);
			echo '
'; print_r($this->options['curr_handles'][$type]['handles']);
		} */
		foreach($list_of_handles as $handle)
		{
			/**
				As we save the handle of merged files into curr_handles, then we need to make sure 
				that all of list handles (curr handles (to_do) + handles saved by user in the admin bar)
				are exists in the curr_handles, if not, don't use the cache
			*/
			if (!in_array($handle, $this->options['curr_handles'][$type]['handles'])) {
				return false;
			}
			$deregister[] = $handle;
		}
		
		// USE CACHE
		foreach($list_of_handles as $handle) {
			$this->deregister[$type] = $deregister;
		}
		return true;
	}

	/**
		File path
		Find relative path of each style or script
	*/
	private function file_path($src)
	{
		$clean_hash = $clean = strtok($src,'?');
		
		$site_url =  site_url();
		$parse_site_url = parse_url($site_url);
		$parse_url = parse_url($clean_hash);
		
		$site_path = '';
		if (key_exists('path', $parse_site_url))
		{
			$site_path = $parse_site_url['path'];
		}
		
		if (key_exists('host', $parse_url))
		{
			// Exclude external script
			if ($parse_site_url['host'] != $parse_url['host'])
				return false;
			
			$file_path = substr ($parse_url['path'], strlen($site_path));
			$file_path = ltrim ($file_path, '/');
		} 
		else 
		{
			$file_path = ltrim($parse_url['path'], '/');
		}
		return $file_path;
	}
	
	private function skip_handle($handle)
	{
		$excluded_script = $this->options['excluded_handles'];

		if (in_array($handle, $excluded_script))
			return true;
		else 
			return false;
	}
	
	/**
		Used in the init method to deregister th scripts earlier
	*/
	public function deregister_script()
	{
		if ($this->options['merge_scripts'] == 0)
			return;
		
		foreach( $this->options['rest_of_handles']['script'] as $pos => $handles) 
		{
			foreach ($handles as $handle => $arr)
			{
				if (!in_array($handle, $this->options['excluded_handles'])) {
					wp_deregister_script($handle);
				}
			}
		}
	}
}