b0y-101 Mini Shell


Current Path : E:/www/b-group.old/spfin - Copy/application/nu/
File Upload :
Current File : E:/www/b-group.old/spfin - Copy/application/nu/parsingHTML.class.php

<?php
/**
 * Logiciel : HTML2PDF - classe ParsingHTML
 * 
 * Convertisseur HTML => PDF, utilise fpdf de Olivier PLATHEY 
 * Distribu� sous la licence GPL. 
 *
 * @author		Laurent MINGUET <webmaster@spipu.net>
 * @version		3.11 - 28/08/2008
 */
 
if (!defined('__CLASS_PARSINGHTML__'))
{
	define('__CLASS_PARSINGHTML__', true);
	
	class parsingHTML
	{
		var $html	= '';			// code HTML � parser
		var $code	= array();		// code HTML pars�
		var $num	= 0;			// num�ro de table
		var $level	= 0;			// niveaux de table
		
		/**
		 * Constructeur
		 *
		 * @return	null
		 */
		function parsingHTML()
		{
			$this->num		= 0;
			$this->level	= array($this->num);
			$this->html		= '';
			$this->code		= array();	
		}
		
		/**
		 * D�finir le code HTML � parser
		 *
		 * @param	string code html
		 * @return	null
		 */
		function setHTML($html)
		{
			$html = preg_replace('/<!--(.*)-->/isU', '', $html);
			$this->html = $html;	
		}
		
		/**
		 * parser le code HTML
		 *
		 * @return	null
		 */
		function parse()
		{
			$parents = array();
			// r�cup�rer le code � parser
			$content = $this->html;
						
			// chercher les balises HTML du code
			$tmp = array();
			$this->searchCode($content, $tmp);
			
			// identifier les balises une � une
			$pre_in = false;
			$pre_br = array(
						'name' => 'br',
						'close' => false,
						'param' => array(
							'style' => array(),
							'num'	=> 0
						)
					);

			$todos = array();
			foreach($tmp as $part)
			{
				// si c'est un texte
				if ($part[0]=='txt')
				{
					// si un texte est pr�sent
					if (trim($part[1])!=='')
					{
						// enregistrer l'action correspondante
						if (!$pre_in)
						{
							// remplacer tous les espaces, tabulations, saufs de ligne multiples par de simples espaces
							$part[1] = preg_replace('/([\s]+)/is', ' ', $part[1]);
						
							$todos[] = array(
											'name'	=> 'write',
											'close'	=> false,
											'param' => array('txt' => $part[1]),
										);
						}
						else
						{
							$part[1] = str_replace("\r", '', $part[1]);
							$part[1] = explode("\n", $part[1]);
							
							foreach($part[1] as $txt)
							{
								$txt = str_replace("\t", '        ', $txt);
								$txt = str_replace(' ', '&nbsp;', $txt);
								$todos[] = array(
												'name'	=> 'write',
												'close'	=> false,
												'param' => array('txt' => $txt),
											);
								$todos[] = $pre_br;
							}
						}
					}
				}
				// sinon, analyser le code
				else
				{
					$res = $this->analiseCode($part[1]);

					if ($res)
					{
						if (!in_array($res['name'], array('br', 'hr', 'img', 'input', 'link', 'option')))
						{
							if ($res['close'])
							{
								if (count($parents)<1)
									HTML2PDF::makeError(3, __FILE__, __LINE__, $res['name']);
								else if ($parents[count($parents)-1]!=$res['name'])
									HTML2PDF::makeError(4, __FILE__, __LINE__, $parents);
								else
									unset($parents[count($parents)-1]);
							}
							else
							{
								$parents[count($parents)] = $res['name'];						
							}
						}
						if ($res['name']=='pre' || $res['name']=='code')
						{
							$pre_in = !$res['close'];
						}
						$todos[] = $res;
					}
				}	
			}

			// pour chaque action identifi�e, il faut nettoyer le d�but des textes
			// en fonction des balises qui le pr�c�dent.
			for($k=0; $k<count($todos); $k++)
			{
				//si c'est un texte
				if ($todos[$k]['name']=='write')
				{
					// et qu'une balise sp�cifique le pr�c�de => on nettoye les espaces du d�but du texte
					if ($k>0 && in_array($todos[$k-1]['name'], array('table', 'tr', 'td', 'th', 'br', 'div', 'hr', 'p')))
						$todos[$k]['param']['txt'] = preg_replace('/^([\s]*)([^\s])/isU', '$2', 	$todos[$k]['param']['txt']);

					// et qu'une balise sp�cifique le suit => on nettoye les espaces de la fin du texte
					if ($k<count($todos)-1 && in_array($todos[$k+1]['name'], array('table', 'tr', 'td', 'th', 'br', 'div', 'hr')))
						$todos[$k]['param']['txt'] = preg_replace('/([^\s])([\s]*)$/isU', '$1', 	$todos[$k]['param']['txt']);
				}
			}
			if (count($parents)) HTML2PDF::makeError(5, __FILE__, __LINE__, $parents);
			
			// liste des actions sauv�e
			$this->code = $todos;
		}
		
		/**
		 * parser le code HTML
		 *
		 * @param	string	contenu � parser.
		 * @param	&array	tableau de retour des donn�es
		 * @return	null
		 */
		function searchCode($content, &$tmp)
		{
			// s�parer les balises du texte
			$tmp = array();
			preg_match_all('/(<[^>]+>)|([^<]+)+/isU', $content, $parse);

			// pour chaque �l�ment trouv� :
			$str = '';
			for($k=0; $k<count($parse[0]); $k++)
			{
				// si une balise a �t� d�tect�e
				if ($parse[1][$k])
				{
					// sauvegarde du texte pr�c�dent si il existe
					if ($str!=='')	$tmp[] = array('txt',$str);

					// sauvegarde de la balise
					$tmp[] = array('code',trim($parse[1][$k]));
					
					// initialisation du texte suivant
					$str = ''; 	
				}
				else
				{
					// ajout du texte � la fin de celui qui est d�j� d�tect�
					$str.= $parse[2][$k];
				}
			}
			// si un texte est pr�sent � la fin, on l'enregistre
			if ($str!='') $tmp[] = array('txt',$str); 
		}
		
		/**
		 * analyse une balise HTML
		 *
		 * @param	string	code HTML � identifier
		 * @return	array	action correspondante
		 */
		function analiseCode($code)
		{
			// nom de la balise et ouverture ou fermeture
			$balise = '<([\/]{0,1})([_a-z0-9]+)([\/>\s]+)';
			preg_match('/'.$balise.'/isU', $code, $match);
			$close	= ($match[1]=='/' ? true : false);
			$name	= strtolower($match[2]);
			
			// param�tres obligatoires en fonction du nom de la balise
			$param	= array();
			$param['style'] = '';
			if ($name=='img')	{ $param['alt'] = '';	$param['src'] = ''; }
			if ($name=='a')		{ $param['href'] = '';	}
			
			// lecture des param�tres du type nom=valeur
			$prop = '([a-zA-Z0-9_]+)=([^"\'\s>]+)';
			preg_match_all('/'.$prop.'/is', $code, $match);
			for($k=0; $k<count($match[0]); $k++)
				$param[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);

			// lecture des param�tres du type nom="valeur"
			$prop = '([a-zA-Z0-9_]+)=["]([^"]*)["]';
			preg_match_all('/'.$prop.'/is', $code, $match);
			for($k=0; $k<count($match[0]); $k++)
				$param[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);

			// lecture des param�tres du type nom='valeur'
			$prop = "([a-zA-Z0-9_]+)=[']([^']*)[']";
			preg_match_all('/'.$prop.'/is', $code, $match);
			for($k=0; $k<count($match[0]); $k++)
				$param[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);
		
			// mise en conformit� en style de chaque param�tre
			$color	= "#000000";
			$border	= null;
			foreach($param as $key => $val)
			{
				$key = strtolower($key);
				switch($key)
				{
					case 'width':
						unset($param[$key]);
						$param['style'] = 'width: '.$val.'px; '.$param['style'];
						break;	

					case 'height':
						unset($param[$key]);
						$param['style'] = 'height: '.$val.'px; '.$param['style'];	
						break;	

					case 'bgcolor':
						unset($param[$key]);
						$param['style'] = 'background: '.$val.'; '.$param['style'];					
						break;	

					case 'bordercolor':
						unset($param[$key]);
						$color = $val;
						break;	

					case 'border':
						unset($param[$key]);
						if (preg_match('/^[0-9]$/isU', $val)) $val = $val.'px';
						$border = $val;
						break;
					
					case 'cellpadding':
					case 'cellspacing':
						if (preg_match('/^([0-9]+)$/isU', $val)) $param[$key] = $val.'px';
						break;
						
					case 'colspan':
					case 'rowspan':
						$val = preg_replace('/[^0-9]/isU', '', $val);
						if (!$val) $val = 1;
						$param[$key] = $val;
						break;
				}
			}
			if ($border!==null)
			{
				if ($border)	$param['style'] = 'border: solid '.$border.' '.$color.'; '.$param['style'];
				else			$param['style'] = 'border: none'; 
			}
			
			// lecture des styles - d�composition
			$styles = explode(';', $param['style']);
			$param['style'] = array();
			foreach($styles as $style)
			{
				$tmp = explode(':', $style);
				if (count($tmp)==2)	$param['style'][trim(strtolower($tmp[0]))] = preg_replace('/[\s]+/isU', ' ', trim($tmp[1]));
			}
			
			// d�termination du niveau de table pour les ouverture, avec ajout d'un level
			if ($name=='table' && !$close)
			{
				$this->num++;
				$this->level[count($this->level)] = $this->num;
			} 
			
			// attribution du niveau de table o� se trouve l'�l�ment
			if (!isset($param['num'])) $param['num'] = $this->level[count($this->level)-1];

			// pour les fins de table : suppression d'un level
			if ($name=='table' && $close)
			{
				unset($this->level[count($this->level)-1]);			
			} 

			// retour de l'action identifi�e
			return array('name' => $name, 'close' => $close ? 1 : 0, 'param' => $param);
		}
		
		// r�cup�rer un niveau complet d'HTML entre une ouverture de balise et la fermeture correspondante
		function getLevel($k)
		{
			// si le code n'existe pas : fin
			if (!isset($this->code[$k])) return '';
			
			// quelle balise faudra-t-il d�tecter
			$detect = $this->code[$k]['name'];
			
			$level = 0;		// niveau de profondeur
			$end = false;	// etat de fin de recherche
			$code = '';		// code extrait
			
			// tant que c'est pas fini, on boucle
			while (!$end)
			{
				// action courante
				$row = $this->code[$k];
				
				// si write => on ajoute le texte
				if ($row['name']=='write')
				{
					$code.= $row['param']['txt'];	
				}
				// sinon, c'est une balise html
				else
				{
					$not = false; // indicateur de non prise en compte de la balise courante
					
					// si c'est la balise que l'on cherche
					if ($row['name']==$detect)
					{
						if ($level==0) { $not = true; }					// si on est � la premiere balise : on l'ignore
						$level+= ($row['close'] ? -1 : 1);				// modification du niveau en cours en fonction de l'ouvertre / fermeture
						if ($level==0) { $not = true; $end = true; }	// si on est au niveau 0 : on a finit
					}
					
					// si on doit prendre en compte la balise courante
					if (!$not)
					{
						// ecriture du code HTML de la balise
						$code.= '<'.($row['close'] ? '/' : '').$row['name'];
						foreach($row['param'] as $key => $val)
						{
							if ($key=='style')
							{
								$tmp = '';
								if (isset($val['text-align'])) unset($val['text-align']);
								foreach($val as $ks => $vs) $tmp.= $ks.':'.$vs.'; ';
								$val = $tmp;
								if (trim($val)) $code.= ' '.$key.'="'.$tmp.'" ';
							}
							else
							{
								$code.= ' '.$key.'="'.$val.'" ';
							}	
						}
						$code.= ' >';
					}
				}
				
				// on continue tant qu'il y a du code � analyser...
				if (isset($this->code[$k+1]))
					$k++;
				else
					$end = true;	
			}
			
			// retourne la position finale et le code HTML extrait
			return array($k, $code);
		}
	}
}
?>

Copyright © 2019 by b0y-101