<?php
/**
 * parseAttributes is a function for parsing attribute and attribute-like strings
 * @package   domit-xmlparser
 * @copyright (C) 2004 John Heinstein. All rights reserved
 * @license   http://www.gnu.org/copyleft/lesser.html LGPL License
 * @author    John Heinstein <johnkarl@nbnet.nb.ca>
 * @link      http://www.engageinteractive.com/domit/ DOMIT! Home Page
 *            DOMIT! is Free Software
 **/

/** attribute parse state, just before parsing an attribute */
define('DOMIT_ATTRIBUTEPARSER_STATE_ATTR_NONE', 0);
/** attribute parse state, parsing an attribute key */
define('DOMIT_ATTRIBUTEPARSER_STATE_ATTR_KEY', 1);
/** attribute parse state, parsing an attribute value */
define('DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE', 2);

/**
 * @global Array Translation table for predefined XML entities
 */
$GLOBALS['DOMIT_PREDEFINED_ENTITIES'] = array('&' => '&amp;', '<' => '&lt;', '>' => '&gt;',
	'"' => '&quot;', "'" => '&apos;');

/**
 * Parses the attributes string into an array of key / value pairs
 *
 * @param string The attribute text
 *
 * @return Array An array of key / value pairs
 */
function parseAttributes($attrText, $convertEntities = true, $definedEntities = null)
{
	$attrText = trim($attrText);
	$attrArray = array();
	$maybeEntity = false;

	$total = strlen($attrText);
	$keyDump = '';
	$valueDump = '';
	$currentState = DOMIT_ATTRIBUTEPARSER_STATE_ATTR_NONE;
	$quoteType = '';

	if ($definedEntities == null) $defineEntities = array();

	for ($i = 0; $i < $total; $i++)
	{
		$currentChar = $attrText{$i};

		if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_NONE)
		{
			if (trim($currentChar != ''))
			{
				$currentState = DOMIT_ATTRIBUTEPARSER_STATE_ATTR_KEY;
			}
		}

		switch ($currentChar)
		{
			case "\t":
				if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE)
				{
					$valueDump .= $currentChar;
				}
				else
				{
					$currentChar = '';
				}
				break;

			case "\x0B": //vertical tab
			case "\n":
			case "\r":
				$currentChar = '';
				break;

			case '=':
				if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE)
				{
					$valueDump .= $currentChar;
				}
				else
				{
					$currentState = DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE;
					$quoteType = '';
					$maybeEntity = false;
				}
				break;

			case '"':
				if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE)
				{
					if ($quoteType == '')
					{
						$quoteType = '"';
					}
					else
					{
						if ($quoteType == $currentChar)
						{
							if ($convertEntities && $maybeEntity)
							{
								$valueDump = strtr($valueDump, DOMIT_PREDEFINED_ENTITIES);
								$valueDump = strtr($valueDump, $definedEntities);
							}

							$attrArray[trim($keyDump)] = $valueDump;
							$keyDump = $valueDump = $quoteType = '';
							$currentState = DOMIT_ATTRIBUTEPARSER_STATE_ATTR_NONE;
						}
						else
						{
							$valueDump .= $currentChar;
						}
					}
				}
				break;

			case "'":
				if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_VALUE)
				{
					if ($quoteType == '')
					{
						$quoteType = "'";
					}
					else
					{
						if ($quoteType == $currentChar)
						{
							if ($convertEntities && $maybeEntity)
							{
								$valueDump = strtr($valueDump, $predefinedEntities);
								$valueDump = strtr($valueDump, $definedEntities);
							}

							$attrArray[trim($keyDump)] = $valueDump;
							$keyDump = $valueDump = $quoteType = '';
							$currentState = DOMIT_ATTRIBUTEPARSER_STATE_ATTR_NONE;
						}
						else
						{
							$valueDump .= $currentChar;
						}
					}
				}
				break;

			case '&':
				//might be an entity
				$maybeEntity = true;
				$valueDump .= $currentChar;
				break;

			default:
				if ($currentState == DOMIT_ATTRIBUTEPARSER_STATE_ATTR_KEY)
				{
					$keyDump .= $currentChar;
				}
				else
				{
					$valueDump .= $currentChar;
				}
		}
	}

	return $attrArray;
} //parseAttributes
