<?php
class structure
{
 	private $structure;
 	private $variables;
 	private $contents;
 	
 	//Stel een aantal variabelen in
	public function __construct($cur_file, $match_name = NULL)
	{
	 	//Het bestand dat doorzocht wordt
		$this->variables['cur_file'] = $cur_file;
		
		//De naam van de capture group
		//Dit mag ook een array zijn, die de match functie
		$this->variables['match_name'] = $match_name;
		
		//De array met match regexes, welke op NULL staat zodat wij geen geheugen gaan gebruiken
		//Maar toch een regex kunnen toevoegen met []
		$this->variables['match_regexes'] = NULL;
		
		//De array met prepare regexes
		$this->variables['prep_regexes'] = NULL;
		
		//De array met prepare vervangingen, het is je eigen probleem als je hier niet genoeg dingen doorgeeft;)
		$this->variables['prep_replacements'] = NULL;
		
		//De array met modules
		$this->variables['modules'] = NULL;
		
		//De array in welke alle matches komen te staan, deze array wordt ook uiteindelijk teruggegeven met display()
		$this->structure[$cur_file] = array();
	}
	
	//Voeg functies toe om het resultaat te bewerken 
	//$func_use mag 'each' of 'once' zijn
	//'each' betekent dat deze functie moet worden uitgevoerd op ieder element in de array
	//'once' betekent dat deze functie slechts 1 keer per bestand wordt uitgevoerd 
	//(bijv. om een paar bestanden toe te voegen die moeilijk zijn te vinden via het script zelf)
		
	//Iedere module krijgt 3 argumenten mee.
	//De eerste kan 2 dingen zijn:
	//1. Als de $func_use 'each' is, is het het huidige bestand
	//2. Als de $func_use 'once' is, is het de complete structure array
	//De andere zijn alle variabelen van het huidige structure object en het huidige structure object zelf ($this)
	//(in die volgorde)
	//Je hoeft echter niet persee iets te doen met deze argumenten
	public function add_module($func_name, $func_use = 'each')
	{
		$this->variables['modules'][] = array('func_name' => $func_name, 'func_use' => $func_use);
	}
	
	//Een 'match regex' toevoegen, welke zegmaar de structuur zullen aangeven
	public function add_match($regex)
	{
	 	//Omdat preg_match %'tjes voor en na een regex wil hebben, kijken we hier even of die er wel zijn
	 	if(!preg_match('/^%/', $regex))
	 	{
			$regex = '%'.$regex;
		}
		
		if(!preg_match('/%$/', $regex))
		{
			$regex = $regex.'%';
		}
		
		//En we voegen de regex toe aan de variables array
		$this->variables['match_regexes'][] = $regex;
	}
	
	//Een 'voorbereid regex' toevoegen, welke op de inhoud los kunnen worden gelaten om bijvoorbeeld commentaren uit PHP script te halen
 	//Een voorbeeld regex + vervanging (deze regel haalt alle PHP comments uit een bestand)
 	//$contents = preg_replace('%\/\/.*\r\n|\/\*(?:.*?\r*?\n*?)*?\*\/%', '', $contents);
	public function add_prepare($regex, $replacement)
	{
	 	//Als de regex al %en heeft, voeg ze niet toe
	 	//In dit geval gebruik ik / om de regex aan te geven, omdat dat hier duidelijker is (t.o.v '%%$%')
		if(!preg_match('/^%/', $regex))
	 	{
			$regex = '%'.$regex;
		}
		
		if(!preg_match('/%$/', $regex))
		{
			$regex = $regex.'%';
		}
		
		$this->variables['prep_regexes'][] = $regex;
		$this->variables['prep_replacements'][] = $replacement;
	}
	
	//Verwerk de array met bestanden
	public function process()
	{
	 	//Bereidt de inhoud voor
	 	$this->prepare();
	 	//Zoek de matches
	 	$this->match();
	 	
	 	//Mits er modules zijn toegevoegd
	 	if(!is_null($this->variables['modules']))
	 	{
			//Voer de modules uit
			foreach($this->variables['modules'] as $module)
			{
			 	//Als deze module op ieder gevonden bestand moet worden losgelaten
			 	if($module['func_use'] == 'each')
				{ 
				 	//En mits er wel gevonden bestanden zijn
				 	if($this->structure[$this->variables['cur_file']] != NULL)
				 	{
					 	$tmp_structure = NULL;
						//Voeren we deze module uit op ieder gevonden bestand
					 	foreach($this->structure[$this->variables['cur_file']] as $tmp_file)
					 	{
					 	 	$tmp = $module['func_name']($tmp_file, $this->variables, $this);
					 	 	if(!is_null($tmp))
					 	 	{
								$tmp_structure[$tmp_file] = $tmp;
							}
							else
							{
								$tmp_structure[] = $tmp_file;
							}
						}
						
						$this->structure[$this->variables['cur_file']] = $tmp_structure;
					}
				}
				//Als deze module op de hele array moet worden uitgevoerd
				elseif($module['func_use'] == 'once')
				{
				 	//Voeren we deze module uit op de array van gevonden bestanden
					$this->structure[$this->variables['cur_file']] = $module['func_name']($this->structure[$this->variables['cur_file']], $this->variables, $this);
				}
			}
		}
	}
	
	//Een functie om de array weer te geven
	public function display($func_name = NULL)
	{
	 	//Als er een functie op is gegeven
		if(!is_null($func_name))
		{
		 	if($func_name == 'array')
		 	{
		 		//Een speciale 'functie', welke ENKEL de array teruggeeft
				return $this->structure[$this->variables['cur_file']];
			}
			else
			{
			 	//De functie die op is gegeven
				return $func_name($this->structure);
			}
		}
		else
		{
		 	//Een standaard teruggave, welke een 'mooie' array weergeeft
			return '<pre>'.print_r($this->structure, true).'</pre>';
		}
	}
	
	//Debug functie om protected/private variabelen te kunnen bekijken
	public function debug($var)
	{
		return $this->$var;
	}
	
	//Bereidt de inhoud van het bestand voor (optioneel uiteraard)
	private function prepare()
	{
	 	$this->contents = $this->get_contents($this->variables['cur_file']);
	 	
	 	//Mits er voorbereid regexen en vervangingen zijn toegevoegd
	 	if(!is_null($this->variables['prep_regexes']) && !is_null($this->variables['prep_replacements']))
	 	{
	 	 	//Zoek in de tekst naar de regex, en vervang deze
			$this->contents = preg_replace($this->variables['prep_regexes'], $this->variables['prep_replacements'], $this->contents);
		}
	}
	
	//De methode om matches te vinden
	private function match()
	{
	 	//Voor iedere match regex die er is opgegeven
	 	foreach($this->variables['match_regexes'] as $regex)
	 	{
		 	if(is_int(stripos($regex, '(?P<'.$this->variables['match_name'].'>')))
		 	{
		 	 	//Als er een capture groep is opgegeven, gebruik die
				preg_match_all($regex, $this->contents, $matches);
				$tmp_structure = NULL;
				
				if(isset($matches[$this->variables['match_name']][0]))
				{
					foreach($matches[$this->variables['match_name']] as $tmp)
					{
						$this->structure[$this->variables['cur_file']][] = $tmp;
					}
				}
			}
			else
			{
			 	//anders, geef gewoon alle matches terug
				preg_match_all($regex, $this->contents, $matches);
				
				foreach($matches[0] as $match)
				{
					$this->structure[$this->variables['cur_file']][] = $match;
				}
			}
		}
		
		//Als er geen matches zijn gevonden, geef een 'mooie' waarde terug
		if(!isset($this->structure[$this->variables['cur_file']][0]))
		{
			$this->structure[$this->variables['cur_file']] = NULL;
		}
	}
	
	//Inhoud van het bestand ophalen
	private function get_contents($file)
	{	
	 	//Om gewoon zeker te weten dat we niet een niet bestaand bestand proberen te openen
		if(file_exists($file))
		{
			return file_get_contents($file);
		}
		else
		{
			return NULL;
		}
	}
}
?>