Scripts

Statische string functies (PHP Compacten)

Sommige functies voor string bewerkening ontbreken gewoon. Ik heb een aantal handige functies geschreven om strings te manipuleren. Vooral met het oog op tags, erg handig. De classe is een classe voor de verzameling. Het classe object is niet nodig om de functies te laten werken. Echter zijn er verwijzingen in de class naar zichzelf, om dit te laten werken, deze ook aanpassen Ik zal kort de functies bespreken: match_by_tag function match_by_tag($strText, $strTagOpen, $strTagClose, &$arrMatch, $iLimit = null) Match een tag, in een stringtext. Deze tag begint met een string (). De gevonden posities worden in een referentiele array opgeslagen. Elke match voegt een array toe aan de $arrMatch, elke subarray bestaat uit de volgende onderdelen: beginpostie van de string, eindpositie van de string, totale lengte van de tag, totale lengte van de tag zonder tagopen en tag close. convert_by_tag Deze werkt ongeveer hetzelfde als match_by_tag, echter kan er gelijk aangegeven worden of er wat met de data tussen de tag open en tag-close gedaan moet worden. $strAction kan de volgende waarden bevatten: STRIP, HTMLENTITIES, HTML_ENTITIES_DECODE Welke respectievelijk zorgt voor verwijderen, html omzetten naar hun string versie (< wordt &bd; (ofzo)), en string html omzetten naar hun tekens. strip_out_and_save_by_tag Soms wil je bepaalde data veilig stellen voordat je bewerkingen uit gaat voeren. Met deze functie wordt de data tussen strTagOpen en strTagClose vervangen door een unieke tag (die niet in de string voorkomt). De unieke tag komt op de plek van de gematchte string, de string wordt opgeslagen in de reference array. $arrData[iets van een unieke key] = 'string gematched door twee quotes'; insert_saved_by_tag De functie maakt de voorgaande functie ongedaan. Het is in feite niet meer dan een string_replace. first_position Soms wil je weten welke string er als eerste voorkomt uit een set. Hiervoor heb ik first_position ontwikkeld. Deze geeft een array terug met de positie van de string op index 0. En de gevonden string op index 1. last_position Als voorgaande, maar wordt het laatste voorkomen van een string gezocht. compact_php Misschien wel de mooiste van allemaal. Deze functie haalt alle spaties, enters, tabs en commentaar uit je code. Hierdoor wordt je code niet alleen compacter (mijn ervaring ongeveer 50%), maar ook wat minder toegankelijk. Als je aan het debuggen gaat, is het niet handig, daar alles op enkele regels staat. De functie heeft wel even tijd nodig (ongeveer 30 seconden om 300.000 karakters te verwerken (output: 170.000 karakters). compact_xml Niet zo heel nuttig, is ook niet ver doorontwikkeld. generate_unique_tag Deze functie genereert een unieke string voor een bepaalde tekst. Er kan een tekst meegegeven worden waarin de tag niet voor mag komen of een array. In geval van de array wordt er gekeken naar de keys. Nou, dat was dat, nu de code! Updates 18-07-2007: Offset toegevoegd aan match_by_tag en convert_by_tag

statische-string-functies-php-compacten
[b]voorbeeld.xml[/b]
[code]
<?xml version="1.0"?>

<voorbeeld>
		
	<item>Text</item>
	<![CDATA[
		<a href="text">Testing href</a>
	
	]]>
	<item>Text</item>
	<!-- Comment -->
</voorbeeld>
[/code]

[b]voorbeeld.php[/b]
[code]
<?
include('STATIC_STRING.class.php');
$data = file_get_contents('voorbeeld.xml');

header("Content-type: text/html");

echo "Originele data:<br />";
echo $data;
echo "<br /><hr /><br />";

// Converteer cdata
$data = STATIC_STRING::convert_by_tag($data, '<![CDATA[', ']]>', 'HTMLENTITIES', true);

echo "Geconverteerd cdata:<br />";
echo $data;
echo "<br /><hr /><br />";


// Verwijder comment
$data = STATIC_STRING::convert_by_tag($data, '<!--', '-->', 'STRIP', true);

echo "Zonder commentaar:<br />";
echo $data;
echo "<br /><hr /><br />";

// Verkrijg tags
$arrMatch = array();
STATIC_STRING::match_by_tag($data, '<', '>', $arrMatch);

echo "Gevonden elementen:<br />";
foreach($arrMatch as $positionData)
{
	// Zonder open tag, dus positie + 1, index 3 is binnenlengte
	echo substr($data, $positionData[0]+1, $positionData[3])."<br />";
}
echo "<br /><hr /><br />";


echo "voorbeeld.php compressie:<br />";

$data = file_get_contents('voorbeeld.php');
echo "Huidige lengte: ".strlen($data)."<br />";

// Compact phpcode
$data = STATIC_STRING::compact_php($data);

echo "Compressie lengte: ".strlen($data)."<br /><hr/>";
echo "Compressie code:<br />".htmlentities($data);
echo "<br /><hr /><br />";

echo "STATIC_STRING.class.php compressie:<br />";

$data = file_get_contents('STATIC_STRING.class.php');
echo "Huidige lengte: ".strlen($data)."<br />";

// Compact phpcode
$data = STATIC_STRING::compact_php($data);

echo "Compressie lengte: ".strlen($data)."<br /><hr/>";
echo "Compressie code:<br />".htmlentities($data);
echo "<br /><hr /><br />";
?>
[/code]


[b]STATIC_STRING.class.php[/b]
[code]
<?

class STATIC_STRING
{
	/**
	 * Returns the start and endpostion of each matched set. Array(Array(iStartpos, iEndPos, $iTotalLength, $iInternalLength), Array(iStartpos, iEndpos, $iTotalLength, $iInternalLength))
	 *
	 * @param string $strText
	 * @param string $strTagOpen
	 * @param string $strTagClose
	 * @param array $arrMatch
	 */
	function match_by_tag($strText, $strTagOpen, $strTagClose, &$arrMatch, $iOffset = 0, $iLimit = null)
	{
		$iCount = 0;
		$iStartPos = 0;
		$iCurrentPos = $iOffset;

		// Determine the length of both tags
		$iTagOpenLength = strlen($strTagOpen);
		$iTagCloseLength = strlen($strTagClose);

		// Walk through the text, using the substr function, to find the first occurance
		// Save the first occurance position in the iStartpos
		// If the currentposition is outside the textrange, the loop will quit
		while ($iCurrentPos < strlen($strText)
				&& ($iStartPos = strpos($strText, $strTagOpen, $iCurrentPos)) !== false
				&& ($iLimit == null || $iCount < $iLimit) )
		{
			// Update the current pos, set it to the startposition plus the length of the startstring
		    $iCurrentPos = $iStartPos + $iTagOpenLength;

		    // Try to match the endstring, if not successful, match it to the end of the text
		    $iEndPos = strpos($strText, $strTagClose, $iCurrentPos);
		    if ($iEndPos === false) $iEndPos = strlen($strText);

		    // Update the current position
		    $iCurrentPos = $iEndPos + $iTagCloseLength;

		    $arrMatch[] = array($iStartPos, $iCurrentPos, 
		    				$iCurrentPos - $iStartPos, // Total length
		    				$iCurrentPos - $iStartPos - $iTagOpenLength - $iTagCloseLength); // Internal length
		    $iCount++;
		}
	}

	/**
	 * Convert a string matched by an open and close tag.
	 *
	 * @param string $strText
	 * @param string $strTagOpen
	 * @param string $strTagClose
	 * @param string $strAction = Strip, HTMLENTITIES, HTML_ENTITY_DECODE
	 * @return string
	 */
	function convert_by_tag($strText, $strTagOpen, $strTagClose, $strAction, $blnRemoveTag = true, $iOffset = 0, $iLimit = null)
	{
		$iTagOpenLength = strlen($strTagOpen);
		$iTagCloseLength = strlen($strTagClose);

		$strConverted = "";

		// Use the STATIC_STRING::match_by_tag function
		$arrMatches = array();
		STATIC_STRING::match_by_tag($strText, $strTagOpen,  $strTagClose, $arrMatches, $iOffset, $iLimit);

		// Check if there where any matches, else return the input text
		if(count($arrMatches) > 0)
		{
			// Use the current pos variable to cache the current position in the string
			$iCurrentPos = 0;

			// Walk through the matches
			foreach($arrMatches as $arrPositions)
			{
				if($blnRemoveTag)
				{
					// Without the tags
					//  the current position till the occurance of the open string (length = openstringpos - currentpos)
					//   the opentag is thus removed
					$strConverted .= substr($strText, $iCurrentPos, $arrPositions[0] - $iCurrentPos);
				}
				elseif($iCurrentPos == 0)
				{
					// Do nothing special
					$strConverted .= substr($strText, 0, $arrPositions[0] + $iTagOpenLength);
				}
				else
				{
					// Go back the length of the closing char(cannot when iCurrentpos = 0), to keep it in the converted string
					// The length is the openstringpos - currentpos + openstringlength + closestringlength
					$strConverted .= substr($strText, 
											$iCurrentPos - $iTagCloseLength, 
											$arrPositions[0] - $iCurrentPos + $iTagCloseLength + $iTagOpenLength);
				}

				$strMatch = substr($strText, $arrPositions[0] + $iTagOpenLength, $arrPositions[3]);

				switch(strtoupper($strAction))
				{
					case 'STRIP':
						break;
					case 'HTMLENTITIES':
						$strConverted .= htmlentities($strMatch);
						break;
					case 'HTML_ENTITY_DECODE':
						$strConverted .= html_entity_decode($strMatch);
						break;
				}

				// The currentpos will be updated to the position after the closetag
				// thus: startpos + length
				$iCurrentPos = $arrPositions[0] + $arrPositions[2];
			}

			// Put the text behind
			if($blnRemoveTag)
			{
				$strConverted .= substr($strText, $iCurrentPos);
			}
			else  
			{
				$strConverted .= substr($strText, $iCurrentPos - $iTagCloseLength);
			}
		}
		else {
			$strConverted = $strText;
		}

		return $strConverted;
	}

	/**
	 * Strip a match out of string. Save the match in a referenced array and return the stripped text
	 * The unique tags can be replaced again by InsertMatchedTagsFromArray
	 *
	 * @param string $strText
	 * @param string reference $arrData
	 * @param string $strTagOpen
	 * @param string $strTagClose
	 * @return strText stripped of the tags, replaced with unique tags.
	 */
	function strip_out_and_save_by_tag($strText, &$arrData, $strTagOpen, $strTagClose, $iOffset = 0, $iLimit = null)
	{
		$arrMatch = array();
		
		STATIC_STRING::match_by_tag($strText, $strTagOpen, $strTagClose, $arrMatch, $iOffset, $iLimit);
		
		if($arrMatch > 0)
		{
			// Save the new string in here
			$iPos = 0;
			$strStrippedText = "";
			
			foreach($arrMatch as $stringPos)
			{
				// Join the new output and the oldstring, to generate an absolute unique tag
				$strUniqueTag = STATIC_STRING::generate_unique_tag($strText, $arrData);
				
				// Save the data outside the tags
				$strStrippedText .= substr($strText, $iPos, $stringPos[0] - $iPos);
				
				// Add the unique tag, this is at the location of the match
				$strStrippedText .= $strUniqueTag;
				// Save the match into the array
				$arrData[$strUniqueTag] = substr($strText, $stringPos[0], $stringPos[2]);
				
				// Set the position at the end of the match
				$iPos = $stringPos[1];
			}
			// After all, match the text after the last tag
			$strStrippedText .= substr($strText, $iPos);
			
			$strText = $strStrippedText;
		}
		
		return $strText;
	}
	
	/**
	 * Replace matched tags by their values. Undo's the strip_out_and_save_by_tag function
	 *
	 * @param string $strText
	 * @param array $arrMatchedTags
	 * @return strText
	 */
	function insert_saved_by_tag($strText, $arrMatchedTags)
	{
		foreach($arrMatchedTags as $key=>$value)
		{
			$strText = str_replace($key, $value, $strText);
		}
		
		return $strText;
	}
	
	/**
	 * Get the first position of a set of strings.
	 *
	 * @param string $strText
	 * @param mixeld $arrSearch
	 * @param int $iOffset
	 * @return array($iPosition, $strNeedle)
	 */
	function first_position($strText, $arrSearch, $iOffset = null)
	{
		$iPosition 	= false;
		$strNeedle	= '';
		
		// Convert a single node into the array.
		if(!is_array($arrSearch)) $arrSearch = array($arrSearch);
		
		foreach($arrSearch as $Needle)
		{
			$iTMP = strpos($strText, $Needle, $iOffset);
			if($iTMP !== false && ( $iTMP < $iPosition || $iPosition === false))
			{
				$iPosition 	= $iTMP;
				$strNeedle	= $Needle;
			}
		}

		return array($iPosition, $strNeedle);
	}
	
	/**
	 * Get the last position of a set of strings.
	 *
	 * @param string $strText
	 * @param mixeld $arrSearch
	 * @return array($iPosition, $strNeedle)
	 */
	function last_position($strText, $arrSearch)
	{
		$iPosition 	= false;
		$strNeedle	= '';
		
		// Convert a single node into the array.
		if(!is_array($arrSearch)) $arrSearch = array($arrSearch);
		
		foreach($arrSearch as $Needle)
		{
			$iTMP = strpos($strText, $Needle);
			if($iTMP !== false && ( $iTMP > $iPosition || $iPosition == false))
			{
				$iPosition 	= $iTMP;
				$strNeedle 	= $Needle;
			}
		}

		return array($iPosition, $strNeedle);
	}
	
	/**
	 * This function strips php code, it removes comments, tabs and newlines. It leaves string intact, so newlines in your strings won't be replaced.
	 *
	 * @param string $strText
	 * @return string stripped from comments
	 */
	function compact_php($strText)
	{
		// Don't do anything when a file already contains some of those tags. It would messup the whole thing
		/// Do that by finding the first postion of one of the tags. If it returns false, it doesn't contain any of them
		$strCompressString = '<? /** Compressed with PHPCodeCompacter **/ ?>';
		$iPrefPos = strpos($strText, $strCompressString);
		if($strText != '' &&  ($iPrefPos > 0 || $iPrefPos === false))
		{
			$arr = array();
			$arr['ESCESC'] 	= STATIC_STRING::generate_unique_tag($strText, $arr);
			$arr['ESCSNG'] 	= STATIC_STRING::generate_unique_tag($strText, $arr);
			$arr['ESCDBL'] 	= STATIC_STRING::generate_unique_tag($strText, $arr);
			$arr['SNG'] 	= STATIC_STRING::generate_unique_tag($strText, $arr);
			$arr['DBL'] 	= STATIC_STRING::generate_unique_tag($strText, $arr);
			
			
			// Replace escaped escapes
			$strText = str_replace('\\\\', $arr['ESCESC'], $strText);
			// Replace escaped quotes
			$strText = str_replace(array('\\\'', '\\"'), array($arr['ESCSNG'], $arr['ESCDBL']), $strText);
			
			$arrQuoted = array();
			
			// It is difficult to strip all out in the right way
			//  the most precise manner is by walking through the text and see what comes first
			//  there is comment, what has to be stripped and strings which have to be remove and store
			do 
			{
				$arrFirstCharData = STATIC_STRING::first_position($strText, array('//', '/*', '#', "'", '"'));
				$iStrPos 	= $arrFirstCharData[0];
				$strNeedle 	= $arrFirstCharData[1]; 
				
				if($iStrPos !== false && $strNeedle == '//')
				{
					// It is comment, so strip out comment first
					$strText = STATIC_STRING::convert_by_tag($strText, '//', "\n", 'strip', true, 0, 1);
				}elseif($iStrPos !== false && $strNeedle == '/*')
				{
					// It is comment, so strip out comment first
					$strText = STATIC_STRING::convert_by_tag($strText, '/*', "*/", 'strip', true, 0, 1 );
				}
				elseif($iStrPos !== false && $strNeedle == '"')
				{
					// It isn't comment, so it should be a tag for a single or double quote
					//  Replace the damn quotes!
					$strText = substr_replace($strText, $arr['DBL'], $iStrPos, 1);
					
					// Determine the position of the closing quote after the replace
					$iNextQuote = strpos($strText, '"');
					$strText = substr_replace($strText, $arr['DBL'], $iNextQuote, 1);
					$strText = STATIC_STRING::strip_out_and_save_by_tag($strText, $arrQuoted, $arr['DBL'], $arr['DBL'], 0, 1);
				}elseif($iStrPos !== false && $strNeedle == "'")
				{
					$strText = substr_replace($strText, $arr['SNG'], $iStrPos, 1);
					
					// Determine the position of the closing quote after the replace
					$iNextQuote = strpos($strText, "'");
					$strText = substr_replace($strText, $arr['SNG'], $iNextQuote, 1);
					$strText = STATIC_STRING::strip_out_and_save_by_tag($strText, $arrQuoted, $arr['SNG'], $arr['SNG'], 0, 1);
					echo '';
				}elseif($iStrPos !== false && $strNeedle == '#')
				{
					// It is comment, so strip out comment first
					$strText = STATIC_STRING::convert_by_tag($strText, '#', "\n", 'strip', true, 0, 1);
				}
				
			}while($iStrPos);
			
			// The core removal
			
			// remove whitespace
			$strText = preg_replace('/\s\s+/', ' ', $strText);
			
			$strText = str_replace(" class ", "\r\nclass ", $strText);
			$strText = STATIC_STRING::insert_saved_by_tag($strText, $arrQuoted);
			
			// Undo the escaping in shifted order
			$strText = str_replace(array($arr['SNG'], $arr['DBL']), array('\'', '"'), $strText);
			$strText = str_replace(array($arr['ESCSNG'], $arr['ESCDBL']), array('\\\'', '\\"'), $strText);
			$strText = str_replace($arr['ESCESC'], '\\\\', $strText);
			
			
			$strText = str_replace('?><?', '', $strCompressString.$strText);
			
			return $strText;
		}
		
		return trim($strText);
	}
	
	/**
	 * This function strips php code, it removes comments, tabs and newlines. It leaves strings intact, so newlines in your strings won't be replaced.
	 *
	 * @param string $strText
	 * @return string stripped from comments
	 */
	function compact_xml($strText)
	{
		// Don't do anything when a file already contains some of those tags. It would messup the whole thing
		/// Do that by finding the first postion of one of the tags. If it returns false, it doesn't contain any of them
		$strCompressString = '<!-- /** Compressed with PHPCodeCompacter **/ -->';
		$iPrefPos = strpos($strText, $strCompressString);
		if($strText != '' &&  ($iPrefPos > 0 || $iPrefPos === false))
		{
			$arr = array();
			$arr['SAFEDAT_OPEN'] = STATIC_STRING::generate_unique_tag($strText, $arr);
			$arr['SAFEDAT_CLOSE'] = STATIC_STRING::generate_unique_tag($strText, $arr);
			$arrSafe = array();
			
			// It is difficult to strip all out in the right way
			//  the most precise manner is by walking through the text and see what comes first
			//  there is comment, what has to be stripped and strings which have to be remove and store
			do 
			{
				$arrFirstPosData = STATIC_STRING::first_position($strText, array('<![CDATA[', '<!--'));
				$iStrPos 	= $arrFirstPosData[0];
				$strNeedle 	= $arrFirstPosData[1];
				
				if($iStrPos && $strNeedle == '<![CDATA[')
				{
					// It is cdata, save the data in the save array
					$strText = substr_replace($strText, $arr['SAFEDAT_OPEN'], $iStrPos, 9);
					
					// Determine the position of the closing quote after the replace
					$iSafedatClose = strpos($strText, ']]>');
					$strText = substr_replace($strText, $arr['SAFEDAT_CLOSE'], $iSafedatClose, 3);
					$strText = STATIC_STRING::strip_out_and_save_by_tag($strText, $arrSafe, $arr['SAFEDAT_OPEN'], $arr['SAFEDAT_CLOSE'], 0, 1);
				}elseif($iStrPos && $strNeedle == '<!--')
				{
					// It is comment, so strip out comment first
					$strText = STATIC_STRING::convert_by_tag($strText, '<!--', "-->", 'strip', true, 0, 1 );
				}
				
			}while($iStrPos);
			
			// The core removal
			$strText = str_replace(array("\r\n", "\n", "\t", ' ', '   ', '    ', '     '), ' ', $strText);
			
			$strText = STATIC_STRING::insert_saved_by_tag($strText, $arrSafe);
			
			// Undo the escaping in shifted order
			$strText = str_replace(array($arr['SAFEDAT_OPEN'], $arr['SAFEDAT_CLOSE']), array('<![CDATA[', ']]>'), $strText);
			
			$strText = $strText.$strCompressString;
		}
		
		return trim($strText);
	}
	
	/**
	 * When you want to generate an unique tag that isn't in a string or in a array
	 *
	 * @param string $TextUnique
	 * @param array $ArrayUnique
	 * @return Unique Tag
	 */
	function generate_unique_tag($TextUnique = null, $ArrayUnique = null)
	{
		$strTag = "";
		$iTagLength = 5;
		do{
			$strTag = '['.substr(md5(rand(0,10000).date("I-Y-sM:y:m")), 0, $iTagLength).']';
			$iTagLength++;
		}while( (isset($TextUnique) && strstr($TextUnique, $strTag))
					|| (isset($ArrayUnique) && (array_search($strTag, $ArrayUnique) || isset($ArrayUnique[$strTag]))));
		
		return $strTag;
	}
}

?>[/code]

Reacties

0
Nog geen reacties.