<?php
require_once 'Quicty/phplib/php_htmltag_braker_0.03/php_htmltag_braker.php';

class HtmlParser {

var $html_source;
var $tag_tree;

function HtmlParser($html) {
	$this->html_source = $this->split_html($html);
	$this->tag_tree = $this->make_tag_tree();
}

function get_root() {
	return $this->tag_tree;
}

function get_html($html_no=0) {
	return $this->tag_tree['html'][$html_no]['values'];
}

function get_head($head_no=0,$html_no=0) {
	$html = $this->get_html($html_no);
	$head = $html['head'][$head_no]['values'];
	return $head;
}

function get_head_elements($element_name,$head_no=0,$html_no=0) {
	$head = $this->get_head($head_no,$html_no);
	return $head[$element_name];
}

function get_head_element_by_no($element_name,$element_no='all',$head_no=0,$html_no=0) {
	$head = $this->get_head($head_no,$html_no);
	if($element_no=='all') {
		$result = $head[$element_name];
	} elseif(is_numeric($element_no)) {
		$result = $head[$element_name][$element_no];
	}
	return $result;
}

function get_head_element_by_type($element_name,$type,$head_no=0,$html_no=0) {
	$head = $this->get_head($head_no,$html_no);
	$elements = $head[$element_name];
	foreach($elements as $element) {
		if($element['attributes']['type']==$type) {
			$result = $element;
			break;
		}
	}
	return $result;
}

function get_body($body_no=0,$html_no=0) {
	$html = $this->get_html($html_no);
	$body = $html['body'][$body_no]['values'];
	return $body;
}

function get_body_elements($element_name,$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	return $body[$element_name];
}

function get_body_element_by_no($element_name,$element_no='all',$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body[$element_name];
	if($element_no=='all') {
		$result = $elements;
	} elseif(is_numeric($element_no)) {
		$result = $this->search_element_by_no($elements,$element_name,$element_no);
	}
	return $result;
}

function get_div_by_no($element_no='all',$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body['div'];
	if($element_no=='all') {
		$result = $elements;
	} elseif(is_numeric($element_no)) {
		$result = $this->search_element_by_no($elements,'div',$element_no);
	}
	return $result;
}

function search_element_by_no($elements,$element_name,$element_no,$counter=0) {
	foreach($elements as $element) {
		if($counter==$element_no)
			return $element;
		if(isset($element['values'][$element_name])) {
			$counter++;
			$next_elements = $element['values'][$element_name];
			$result = $this->search_element_by_no($next_elements,$element_name,$element_no,$counter);
			if(is_array($result)) {
				return $result;
			} else {
				$counter = $result;
			}
		} else {
			$counter++;
		}
	}
	return $counter;
}

function get_body_element_by_id($element_name,$element_id,$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body[$element_name];
	$result = $this->search_element_by_id($elements,$element_name,$element_id);
	return $result;
}

function get_div_by_id($element_id,$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body['div'];
	$result = $this->search_element_by_id($elements,'div',$element_id);
	return $result;
}

function search_element_by_id($elements,$element_name,$element_id) {
	foreach($elements as $element) {
		if($element['attributes']['attributes']['id']==$element_id)
			return $element;
		if(isset($element['values'][$element_name])) {
			$next_elements = $element['values'][$element_name];
			$result = $this->search_element_by_id($next_elements,$element_name,$element_id);
			if(is_array($result) and $result['attributes']['attributes']['id']==$element_id) {
				return $result;
			}
		}
	}
	return false;
}

function count_body_elements_have_id($element_name,$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body[$element_name];
	$result = $this->search_element_has_id($elements,$element_name);
	return $result;
}

function count_div_have_id($body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body['div'];
	$result = $this->search_element_has_id($elements,'div');
	return $result;
}


function search_element_has_id($elements,$element_name) {
	$id_set = array();
	foreach($elements as $element) {
		if(isset($element['attributes']['attributes']['id']))
			$id_set[] = $element['attributes']['attributes']['id'];
		if(isset($element['values'][$element_name])) {
			$next_elements = $element['values'][$element_name];
			$result = $this->search_element_has_id($next_elements,$element_name);
			if(count($result)>0)
				$id_set = array_merge($id_set,$result);
		}
	}
	return $id_set;
}

function count_body_elements_have_class($element_name,$body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body[$element_name];
	$result = $this->search_element_has_class($elements,$element_name);
	return $result;
}

function count_div_have_class($body_no=0,$html_no=0) {
	$body = $this->get_body($body_no,$html_no);
	$elements = $body['div'];
	$result = $this->search_element_has_class($elements,'div');
	return $result;
}

function search_element_has_class($elements,$element_name) {
	$class_set = array();
	foreach($elements as $element) {
		if(isset($element['attributes']['attributes']['class']))
			$class_set[$element['attributes']['attributes']['class']]++;
		if(isset($element['values'][$element_name])) {
			$next_elements = $element['values'][$element_name];
			$result = $this->search_element_has_class($next_elements,$element_name);
			if(count($result)>0) {
				foreach($class_set as $key=>$value) {
					if(isset($result[$key]))
						$class_set[$key] += $result[$key];
				}
				foreach($result as $key=>$value) {
					if(!isset($class_set[$key]))
						$class_set[$key] = $result[$key];
				}
			}
		}
	}
	return $class_set;
}


//

function get_root_blocks_name() {
	$source = $this->get_root();
	return $this->get_blocks_name($source);
}

function get_html_blocks_name($html_no=0) {
	$source = $this->get_html($html_no);
	return $this->get_blocks_name($source);
}

function get_head_blocks_name($head_no=0,$html_no=0) {
	$source = $this->get_head($head_no,$html_no);
	return $this->get_blocks_name($source);
}

function get_body_blocks_name($body_no=0,$html_no=0) {
	$source = $this->get_body($body_no,$html_no);
	return $this->get_blocks_name($source);
}

function get_blocks_name($source) {
	if(isset($source[0]['values']))$source = $source[0]['values'];
	foreach($source as $key=>$block) {
		$blocks[$key]++;
	}
	return $blocks;
}



//-------------------------------------------------------------

function make_tag_tree($block_tag_name='') {
	$temp_tags = array();
	while(count($this->html_source)>0) {
		$tag = array_shift($this->html_source);
		if(!trim($tag)) continue;
		$attributes = $this->get_attributes($tag);
		switch($attributes['type']) {
			case 'open':
				//echo 'open:'.$attributes['name']."\n";
				$this_block_tag_name = $attributes['name'];
				$this_block['attributes'] = $attributes;
				$this_block['values'] = $this->make_tag_tree($this_block_tag_name);
				$temp_tags[$this_block_tag_name][] = $this_block;
				break;
			case 'close':
				//echo 'close:'.$attributes['name']."\n";
				if($attributes['name']==$block_tag_name) {
					return $temp_tags;
				}
				break;
			case 'single':
				//echo 'single:'.$attributes['source']."\n";
				$temp_tags[$attributes['name']][] = $attributes;
		}
	}
	return $temp_tags;
}

function get_attributes($tag) {
	$single_tags = array('area','br','frame','hr','img','input','meta','link','object','pram');
	$result['source'] = $tag;
	$tag = $this->replace_html_entities($tag);
	if(substr($tag,0,1)!='<') {
		$result['name'] = 'text';
		$result['type'] = 'single';
		$result['attributes'] = array('value'=>$tag);
	} elseif(substr($tag,0,5)=='<?xml') {
		$result['name'] = 'xml';
		$result['type'] = 'single';
		$result['attributes'] = array('value'=>$tag);
	} elseif(substr($tag,0,9)=='<!DOCTYPE') {
		$result['name'] = 'doctype';
		$result['type'] = 'single';
		$result['attributes'] = array('value'=>$tag);
	} elseif(preg_match("/<!--.*-->/",$tag)) {
		$result['name'] = 'remark';
		$result['type'] = 'single';
		$result['attributes'] = array('value'=>$tag);
	} elseif(preg_match("/<!--.*/",$tag)) {
		$result['name'] = 'remark';
		$result['type'] = 'open';
		$result['attributes'] = array('value'=>$tag);
	} elseif(preg_match("/.*-->/",$tag)) {
		$result['name'] = 'remark';
		$result['type'] = 'close';
		$result['attributes'] = array('value'=>$tag);
	} else {
		$attributes = anly_html_get_attribute ($tag);
		$result['name'] = strtolower ($attributes[0]);
		if(substr($tag,0,2)=='</') {
			$result['type'] = 'close';
			$result['name'] = substr($result['name'],1);
		} elseif(substr($tag,-2)=='/>') {
			$result['type'] = 'single';
		} elseif(in_array($result['name'],$single_tags)) {
			$result['type'] = 'single';
		} else {
			$result['type'] = 'open';
		}
		$result['attributes'] = $attributes;
	}
	return $result;
}


function split_html($html) {
	return anly_html_split($html);
}

function get_tag_attributes($tag) {
	return anly_html_get_attribute ($tag);
}

function replace_html_entities($data) {
	$search = array (
		'@([\r\n])[\s]+@',	// 空白文字を削除
		'@&(quot|#34);@i',	// HTML エンティティを置換
		'@&(amp|#38);@i',
		'@&(lt|#60);@i',
		'@&(gt|#62);@i',
		'@&(nbsp|#160);@i',
		'@&(iexcl|#161);@i',
		'@&(cent|#162);@i',
		'@&(pound|#163);@i',
		'@&(copy|#169);@i'
	);
	
	$replace = array (
		'\1',
		'"',
		'&',
		'<',
		'>',
		' ',
		chr(161),
		chr(162),
		chr(163),
		chr(169)
	);
	return preg_replace($search, $replace, $data);
}

} // end of HtmlParser class

?>
