public function formatCurrency($amount)
    {
        $money = $this->getMoney((string) $amount);
        $formatter = new DecimalMoneyFormatter($this->getCurrencies());

        return $formatter->format($money);
    }

public function formatCurrency ( $ amount ) { $ money = $ this -> getMoney ( ( string ) $ amount ) ; $ formatter = new DecimalMoneyFormatter ( $ this -> getCurrencies ( ) ) ; return $ formatter -> format ( $ money ) ; }

Format an amount for the payment currency.

@param string $amount
@return string

Format an amount for the payment currency .


public function replace(array $items = array())
    {
        $this->items = array();

        foreach ($items as $item) {
            $this->add($item);
        }
    }

public function replace ( array $ items = array ( ) ) { $ this -> items = array ( ) ; foreach ( $ items as $ item ) { $ this -> add ( $ item ) ; } }

Replace the contents of this bag with the specified items

@param array $items An array of items


protected function validateRedirect()
    {
        if (!$this instanceof RedirectResponseInterface || !$this->isRedirect()) {
            throw new RuntimeException('This response does not support redirection.');
        }

        if (empty($this->getRedirectUrl())) {
            throw new RuntimeException('The given redirectUrl cannot be empty.');
        }

        if (!in_array($this->getRedirectMethod(), ['GET', 'POST'])) {
            throw new RuntimeException('Invalid redirect method "'.$this->getRedirectMethod().'".');
        }
    }

Validate that the current Response is a valid redirect.

@return void

Validate that the current Response is a valid redirect .


public static function camelCase($str)
    {
        $str = self::convertToLowercase($str);
        return preg_replace_callback(
            '/_([a-z])/',
            function ($match) {
                return strtoupper($match[1]);
            },
            $str
        );
    }

public static function camelCase ( $ str ) { $ str = self :: convertToLowercase ( $ str ) ; return preg_replace_callback ( '/_([a-z])/' , function ( $ match ) { return strtoupper ( $ match [ 1 ] ) ; } , $ str ) ; }

Convert a string to camelCase. Strings already in camelCase will not be harmed.

@param  string  $str The input string
@return string camelCased output string

Convert a string to camelCase . Strings already in camelCase will not be harmed .


public static function validateLuhn($number)
    {
        $str = '';
        foreach (array_reverse(str_split($number)) as $i => $c) {
            $str .= $i % 2 ? $c * 2 : $c;
        }

        return array_sum(str_split($str)) % 10 === 0;
    }

public static function validateLuhn ( $ number ) { $ str = '' ; foreach ( array_reverse ( str_split ( $ number ) ) as $ i => $ c ) { $ str .= $ i % 2 ? $ c * 2 : $ c ; } return array_sum ( str_split ( $ str ) ) % 10 === 0 ; }

Validate a card number according to the Luhn algorithm.

@param  string  $number The card number to validate
@return boolean True if the supplied card number is valid

Validate a card number according to the Luhn algorithm .


public static function getGatewayShortName($className)
    {
        if (0 === strpos($className, '\\')) {
            $className = substr($className, 1);
        }

        if (0 === strpos($className, 'Omnipay\\')) {
            return trim(str_replace('\\', '_', substr($className, 8, -7)), '_');
        }

        return '\\'.$className;
    }

public static function getGatewayShortName ( $ className ) { if ( 0 === strpos ( $ className , '\\' ) ) { $ className = substr ( $ className , 1 ) ; } if ( 0 === strpos ( $ className , 'Omnipay\\' ) ) { return trim ( str_replace ( '\\' , '_' , substr ( $ className , 8 , - 7 ) ) , '_' ) ; } return '\\' . $ className ; }

Resolve a gateway class to a short name.

The short name can be used with GatewayFactory as an alias of the gateway class,
to create new instances of a gateway.

Resolve a gateway class to a short name .


public static function getGatewayClassName($shortName)
    {
        if (0 === strpos($shortName, '\\')) {
            return $shortName;
        }

        // replace underscores with namespace marker, PSR-0 style
        $shortName = str_replace('_', '\\', $shortName);
        if (false === strpos($shortName, '\\')) {
            $shortName .= '\\';
        }

        return '\\Omnipay\\'.$shortName.'Gateway';
    }

Resolve a short gateway name to a full namespaced gateway class.

Class names beginning with a namespace marker (\) are left intact.
Non-namespaced classes are expected to be in the \Omnipay namespace, e.g.:

\Custom\Gateway     => \Custom\Gateway
\Custom_Gateway     => \Custom_Gateway
Stripe              => \Omnipay\Stripe\Gateway
PayPal\Express      => \Omnipay\PayPal\ExpressGateway
PayPal_Express      => \Omnipay\PayPal\ExpressGateway

@param  string  $shortName The short gateway name
@return string  The fully namespaced gateway class name

Resolve a short gateway name to a full namespaced gateway class .


protected function getFixedQueryBuilder(QueryBuilder $queryBuilder)
    {
        $queryBuilderId = clone $queryBuilder;
        $rootAlias = current($queryBuilderId->getRootAliases());

        // step 1 : retrieve the targeted class
        $from = $queryBuilderId->getDQLPart('from');
        $class = $from[0]->getFrom();
        $metadata = $queryBuilderId->getEntityManager()->getMetadataFactory()->getMetadataFor($class);

        // step 2 : retrieve identifier columns
        $idNames = $metadata->getIdentifierFieldNames();

        // step 3 : retrieve the different subjects ids
        $selects = [];
        $idxSelect = '';
        foreach ($idNames as $idName) {
            $select = sprintf('%s.%s', $rootAlias, $idName);
            // Put the ID select on this array to use it on results QB
            $selects[$idName] = $select;
            // Use IDENTITY if id is a relation too.
            // See: http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
            // Should work only with doctrine/orm: ~2.2
            $idSelect = $select;
            if ($metadata->hasAssociation($idName)) {
                $idSelect = sprintf('IDENTITY(%s) as %s', $idSelect, $idName);
            }
            $idxSelect .= ('' !== $idxSelect ? ', ' : '').$idSelect;
        }
        $queryBuilderId->select($idxSelect);
        $queryBuilderId->distinct($this->isDistinct());

        // for SELECT DISTINCT, ORDER BY expressions must appear in idxSelect list
        /* Consider
            SELECT DISTINCT x FROM tab ORDER BY y;
        For any particular x-value in the table there might be many different y
        values.  Which one will you use to sort that x-value in the output?
        */
        $queryId = $queryBuilderId->getQuery();
        $queryId->setHint(Query::HINT_CUSTOM_TREE_WALKERS, [OrderByToSelectWalker::class]);
        $results = $queryId->execute([], Query::HYDRATE_ARRAY);
        $platform = $queryBuilderId->getEntityManager()->getConnection()->getDatabasePlatform();
        $idxMatrix = [];
        foreach ($results as $id) {
            foreach ($idNames as $idName) {
                // Convert ids to database value in case of custom type, if provided.
                $fieldType = $metadata->getTypeOfField($idName);
                $idxMatrix[$idName][] = $fieldType && Type::hasType($fieldType)
                    ? Type::getType($fieldType)->convertToDatabaseValue($id[$idName], $platform)
                    : $id[$idName];
            }
        }

        // step 4 : alter the query to match the targeted ids
        foreach ($idxMatrix as $idName => $idx) {
            if (\count($idx) > 0) {
                $idxParamName = sprintf('%s_idx', $idName);
                $idxParamName = preg_replace('/[^\w]+/', '_', $idxParamName);
                $queryBuilder->andWhere(sprintf('%s IN (:%s)', $selects[$idName], $idxParamName));
                $queryBuilder->setParameter($idxParamName, $idx);
                $queryBuilder->setMaxResults(null);
                $queryBuilder->setFirstResult(null);
            }
        }

        return $queryBuilder;
    }

This method alters the query to return a clean set of object with a working
set of Object.

@return QueryBuilder

This method alters the query to return a clean set of object with a working set of Object .


public function getParentMetadataForProperty($baseClass, $propertyFullName)
    {
        $nameElements = explode('.', $propertyFullName);
        $lastPropertyName = array_pop($nameElements);
        $class = $baseClass;
        $parentAssociationMappings = [];

        foreach ($nameElements as $nameElement) {
            $metadata = $this->getMetadata($class);

            if (isset($metadata->associationMappings[$nameElement])) {
                $parentAssociationMappings[] = $metadata->associationMappings[$nameElement];
                $class = $metadata->getAssociationTargetClass($nameElement);

                continue;
            }

            break;
        }

        $properties = \array_slice($nameElements, \count($parentAssociationMappings));
        $properties[] = $lastPropertyName;

        return [$this->getMetadata($class), implode('.', $properties), $parentAssociationMappings];
    }

public function getParentMetadataForProperty ( $ baseClass , $ propertyFullName ) { $ nameElements = explode ( '.' , $ propertyFullName ) ; $ lastPropertyName = array_pop ( $ nameElements ) ; $ class = $ baseClass ; $ parentAssociationMappings = [ ] ; foreach ( $ nameElements as $ nameElement ) { $ metadata = $ this -> getMetadata ( $ class ) ; if ( isset ( $ metadata -> associationMappings [ $ nameElement ] ) ) { $ parentAssociationMappings [ ] = $ metadata -> associationMappings [ $ nameElement ] ; $ class = $ metadata -> getAssociationTargetClass ( $ nameElement ) ; continue ; } break ; } $ properties = \ array_slice ( $ nameElements , \ count ( $ parentAssociationMappings ) ) ; $ properties [ ] = $ lastPropertyName ; return [ $ this -> getMetadata ( $ class ) , implode ( '.' , $ properties ) , $ parentAssociationMappings ] ; }

Returns the model's metadata holding the fully qualified property, and the last
property name.

@param string $baseClass        The base class of the model holding the fully qualified property
@param string $propertyFullName The name of the fully qualified property (dot ('.') separated
property string)

@return array(
\Doctrine\ORM\Mapping\ClassMetadata $parentMetadata,
string $lastPropertyName,
array $parentAssociationMappings
)

Returns the model s metadata holding the fully qualified property and the last property name .


protected function getPager($pagerType)
    {
        switch ($pagerType) {
            case Pager::TYPE_DEFAULT:
                return new Pager();

            case Pager::TYPE_SIMPLE:
                return new SimplePager();

            default:
                throw new \RuntimeException(sprintf('Unknown pager type "%s".', $pagerType));
        }
    }

protected
function
getPager
(
$
pagerType
)
{
switch
(
$
pagerType
)
{
case
Pager
::
TYPE_DEFAULT
:
return
new
Pager
(
)
;
case
Pager
::
TYPE_SIMPLE
:
return
new
SimplePager
(
)
;
default
:
throw
new
\
RuntimeException
(
sprintf
(
'Unknown pager type "%s".'
,
$
pagerType
)
)
;
}
}

Get pager by pagerType.

@param string $pagerType

@throws \RuntimeException If invalid pager type is set

@return PagerInterface


private function getParentAlias(ProxyQueryInterface $queryBuilder, $alias)
    {
        $parentAlias = $rootAlias = current($queryBuilder->getRootAliases());
        $joins = $queryBuilder->getDQLPart('join');
        if (isset($joins[$rootAlias])) {
            foreach ($joins[$rootAlias] as $join) {
                if ($join->getAlias() === $alias) {
                    $parts = explode('.', $join->getJoin());
                    $parentAlias = $parts[0];

                    break;
                }
            }
        }

        return $parentAlias;
    }

private function getParentAlias ( ProxyQueryInterface $ queryBuilder , $ alias ) { $ parentAlias = $ rootAlias = current ( $ queryBuilder -> getRootAliases ( ) ) ; $ joins = $ queryBuilder -> getDQLPart ( 'join' ) ; if ( isset ( $ joins [ $ rootAlias ] ) ) { foreach ( $ joins [ $ rootAlias ] as $ join ) { if ( $ join -> getAlias ( ) === $ alias ) { $ parts = explode ( '.' , $ join -> getJoin ( ) ) ; $ parentAlias = $ parts [ 0 ] ; break ; } } } return $ parentAlias ; }

Retrieve the parent alias for given alias.
Root alias for direct association or entity joined alias for association depth >= 2.

@param string $alias

@return string

Retrieve the parent alias for given alias . Root alias for direct association or entity joined alias for association depth > = 2 .


protected function _add($Context, $realmID, $resource, $Object)
	{
		$IPP = $Context->IPP();

		switch ($IPP->version())
		{
			case QuickBooks_IPP_IDS::VERSION_2:
				return $this->_add_v2($Context, $realmID, $resource, $Object);
			case QuickBooks_IPP_IDS::VERSION_3:
				return $this->_add_v3($Context, $realmID, $resource, $Object);
		}
	}

protected function _add ( $ Context , $ realmID , $ resource , $ Object ) { $ IPP = $ Context -> IPP ( ) ; switch ( $ IPP -> version ( ) ) { case QuickBooks_IPP_IDS :: VERSION_2 : return $ this -> _add_v2 ( $ Context , $ realmID , $ resource , $ Object ) ; case QuickBooks_IPP_IDS :: VERSION_3 : return $ this -> _add_v3 ( $ Context , $ realmID , $ resource , $ Object ) ; } }

Add an IDS object via IPP

@param QuickBooks_IPP_Context $Context
@param integer $realmID
@param string $resource
@param object $Object
@return integer


protected function _findById($Context, $realmID, $resource, $IDType, $xml_or_IDType = '', $query = null)
	{
		$IPP = $Context->IPP();

		$flavor = $IPP->flavor();

		if (!$xml_or_IDType)
		{
			if ($flavor == QuickBooks_IPP_IDS::FLAVOR_DESKTOP)
			{
				$parse = QuickBooks_IPP_IDS::parseIDType($IDType);

				$xml_or_IDType = '';
				$xml_or_IDType .= '<?xml version="1.0" encoding="UTF-8"?>' . QUICKBOOKS_CRLF;
				$xml_or_IDType .= '<' . $resource . 'Query xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.intuit.com/sb/cdm/' . $IPP->version() . '">' . QUICKBOOKS_CRLF;

				if ($resource == QuickBooks_IPP_IDS::RESOURCE_CUSTOMER)
				{
					$xml_or_IDType .= '<CustomFieldEnable>true</CustomFieldEnable>';
				}

				if ($query)
				{
					$xml_or_IDType .= $query;
				}

				$xml_or_IDType .= '	<' . QuickBooks_IPP_IDS::resourceToKeyType($resource) . 'Set>' . QUICKBOOKS_CRLF;
				$xml_or_IDType .= '		<Id idDomain="' . $parse['domain'] . '">' . $parse['ID'] . '</Id>' . QUICKBOOKS_CRLF;
				$xml_or_IDType .= '	</' . QuickBooks_IPP_IDS::resourceToKeyType($resource) . 'Set>' . QUICKBOOKS_CRLF;
				$xml_or_IDType .= '</' . $resource . 'Query>';
			}
			else if ($flavor == QuickBooks_IPP_IDS::FLAVOR_ONLINE)
			{
				$xml_or_IDType = $IDType;
			}
		}

		$return = $IPP->IDS($Context, $realmID, $resource, QuickBooks_IPP_IDS::OPTYPE_FINDBYID, $xml_or_IDType);
		$this->_setLastRequestResponse($Context->lastRequest(), $Context->lastResponse());
		$this->_setLastDebug($Context->lastDebug());

		if (count($return))
		{
			return $return[0];
		}

		return null;
	}


public function authenticate($user, $pass)
	{
		$req = new QuickBooks_Request_Authenticate($user, $pass);

		$resp = parent::__soapCall('authenticate', array( $req ));
		$tmp = current($resp);

		return current($tmp);
	}

public function authenticate ( $ user , $ pass ) { $ req = new QuickBooks_Request_Authenticate ( $ user , $ pass ) ; $ resp = parent :: __soapCall ( 'authenticate' , array ( $ req ) ) ; $ tmp = current ( $ resp ) ; return current ( $ tmp ) ; }

Authenticate against a QuickBooks SOAP server

@param string $user
@param string $pass
@return array


public function setParentApplicationID($id)
	{
		return $this->set('ParentRef ' . QUICKBOOKS_API_APPLICATIONID, $this->encodeApplicationID(QUICKBOOKS_OBJECT_CUSTOMER, QUICKBOOKS_LISTID, $id));
	}

public
function
setParentApplicationID
(
$
id
)
{
return
$
this
->
set
(
'ParentRef '
.
QUICKBOOKS_API_APPLICATIONID
,
$
this
->
encodeApplicationID
(
QUICKBOOKS_OBJECT_CUSTOMER
,
QUICKBOOKS_LISTID
,
$
id
)
)
;
}

Set the application id of the parent client

@param string $id
@return boolean


public function setCreditCardInfo($cardno, $expmonth, $expyear, $name, $address, $postalcode)
	{
		// should probably do better checking here for failed sets.
		$b = FALSE;
		$b = $this->set('CreditCardInfo CreditCardNumber', $cardno);
		$b = $this->set('CreditCardInfo ExpirationMonth', $expmonth);
		$b = $this->set('CreditCardInfo ExpirationYear', $expyear);
		$b = $this->set('CreditCardInfo NameOnCard', $name);
		$b = $this->set('CreditCardInfo CreditCardAddress', $address);
		$b = $this->set('CreditCardInfo CreditCardPostalCode', $postalcode);

		return $b;
	}

Set the credit card information for this customer

@param string $cardno		The credit card number
@param integer $expmonth		The expiration month (1 is January, 2 is February, etc.)
@param integer $expyear		The expiration year
@param string $name			The name on the credit card
@param string $address		The billing address for the credit card
@param string $postalcode	The postal code for the credit card
@return boolean


public function getCreditCardInfo($part = null, $defaults = array())
	{
		if (!is_null($part))
		{
			return $this->get('CreditCardInfo ' . $part);
		}

		return $this->getArray('CreditCardInfo *', $defaults);
	}

public
function
getCreditCardInfo
(
$
part
=
,
$
defaults
=
array
(
)
)
{
if
(
!
is_null
(
$
part
)
)
{
return
$
this
->
get
(
'CreditCardInfo '
.
$
part
)
;
}
return
$
this
->
getArray
(
'CreditCardInfo *'
,
$
defaults
)
;
}

Get credit card information for this customer

@param string $part		If you just want a specific part of the card info, specify it here
@param array $defaults	Defaults for the card data if you want the entire array
@return mixed			If you specify a part, a string part is returned, otherwise an array of card data


public function add($Context, $realmID, $Object)
	{
		return parent::_add($Context, $realmID, QuickBooks_IPP_IDS::RESOURCE_CLASS, $Object);
	}

public function add ( $ Context , $ realmID , $ Object ) { return parent :: _add ( $ Context , $ realmID , QuickBooks_IPP_IDS :: RESOURCE_CLASS , $ Object ) ; }

Add a new class to QuickBooks

@param QuickBooks_IPP_Context $Context
@param string $realmID
@param QuickBooks_IPP_Object_Class
@return string								The new ID of the created class


public function findById($Context, $realmID, $ID)
	{
		$xml = null;
		return parent::_findById($Context, $realmID, QuickBooks_IPP_IDS::RESOURCE_EMPLOYEE, $ID, null, $xml);
	}

public function findById ( $ Context , $ realmID , $ ID ) { $ xml = null ; return parent :: _findById ( $ Context , $ realmID , QuickBooks_IPP_IDS :: RESOURCE_EMPLOYEE , $ ID , null , $ xml ) ; }

Get an employee by ID

@param QuickBooks_IPP_Context $Context
@param string $realmID
@param string $ID						The ID of the customer (this expects an IdType, which includes the domain)
@return QuickBooks_IPP_Object_Employee	The employee object


public function signature($method, $keyfile = null)
	{
		$this->_signature = $method;
		$this->_keyfile = $keyfile;
	}

public function signature ( $ method , $ keyfile = null ) { $ this -> _signature = $ method ; $ this -> _keyfile = $ keyfile ; }


public function handleError500($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
	{
		mail('your-email@your-domain.com',
			'QuickBooks error occured!',
			'The following error occured: ' . $errnum . ': ' . $errmsg);

		// return true;			// If you return TRUE, it will continue to process requests
		return false;			// If you return FALSE, it will stop processing requests
	}

Catch and handle a 500 error from QuickBooks

@param string $requestID
@param string $action
@param mixed $ID
@param mixed $extra
@param string $err
@param string $xml
@param mixed $errnum
@param string $errmsg
@return void


public function hookLoginSuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config)
	{
		if ($this->_dsn)
		{
			QuickBooks_Utilities::log($this->_dsn, 'This user logged in and the user login hook was called: ' . $user . ', params: ' . print_r($hook_data, true));
			return true;
		}

		return false;
	}

Example of a login success hook implemented as an object method

@param string $requestID
@param string $user
@param string $hook
@param string $err
@param array $hook_data
@param array $callback_config
@return boolean


public function isRepeatable($path)
	{
		/*
		static $paths = array(
			'FirstName' => false,
			'LastName' => false,
			);
		*/

		$paths = $this->_isRepeatablePaths();

		if (isset($paths[$path]))
		{
			return $paths[$path];
		}

		return false;
	}

Tell whether or not a specific element is repeatable

@param string $path
@return boolean


public function exists($path, $case_doesnt_matter = true, $is_end_element = false)
	{
		$ordered_paths = $this->_reorderPathsPaths();

		if (in_array($path, $ordered_paths))
		{
			return true;
		}
		else if ($case_doesnt_matter)
		{
			foreach ($ordered_paths as $ordered_path)
			{
				if (strtolower($path) == strtolower($ordered_path))
				{
					return true;
				}
			}
		}

		return false;
	}

public function exists ( $ path , $ case_doesnt_matter = true , $ is_end_element = false ) { $ ordered_paths = $ this -> _reorderPathsPaths ( ) ; if ( in_array ( $ path , $ ordered_paths ) ) { return true ; } else if ( $ case_doesnt_matter ) { foreach ( $ ordered_paths as $ ordered_path ) { if ( strtolower ( $ path ) == strtolower ( $ ordered_path ) ) { return true ; } } } return false ; }

Tell whether or not an element exists

@param string $path
@return boolean


public function reorderPaths($unordered_paths, $allow_application_id = true, $allow_application_editsequence = true)
	{
		/*
		static $ordered_paths = array(
			0 => 'Name',
			1 => 'FirstName',
			2 => 'LastName',
			);
		*/

		$ordered_paths = $this->_reorderPathsPaths();

		$tmp = array();

		foreach ($ordered_paths as $key => $path)
		{
			if (in_array($path, $unordered_paths))
			{
				$tmp[$key] = $path;
			}
			/*else if (substr($path, -6) == 'ListID' and $allow_application_id)
			{
				// Modify and add:  (so that application IDs are supported and in the correct place)
				//	CustomerRef ListID tags
				// modified to:
				//	CustomerRef APIApplicationID tags

				$parent = trim(substr($path, 0, -7));

				$apppath = trim($parent . ' ' . QUICKBOOKS_API_APPLICATIONID);

				if (in_array($apppath, $unordered_paths))
				{
					$tmp[$key] = $apppath;
				}
			}
			else if (substr($path, -5) == 'TxnID' and $allow_application_id)
			{
				$parent = trim(substr($path, 0, -6));

				$apppath = $parent . ' ' . QUICKBOOKS_API_APPLICATIONID;

				if (in_array($apppath, $unordered_paths))
				{
					$tmp[$key] = $apppath;
				}
			}
			else if ($path == 'EditSequence' and $allow_application_editsequence)
			{
				$apppath = QUICKBOOKS_API_APPLICATIONEDITSEQUENCE;

				if (in_array($apppath, $unordered_paths))
				{
					$tmp[$key] = $apppath;
				}
			}*/

			/*else if ($path == QUICKBOOKS_API_APPLICATIONID)
			{
				print('HERE!');
			}*/
		}

		return array_merge($tmp);
	}

Re-order an array to match the schema order

@param array $unordered_paths
@param boolean $allow_application_id
@return array

Re - order an array to match the schema order


static protected function _callFunction($function, &$vars, &$err, $which = null)
	{
		if (!function_exists($function))
		{
			$err = 'Callback does not exist: [function] ' . $function . '(...)';
			return false;
		}

		$ret = call_user_func_array($function, $vars);

		if (!is_null($which))
		{
			$err = $vars[$which];
		}

		return $ret;
	}

static
protected
function
_callFunction
(
$
function
,
&
$
vars
,
&
$
err
,
$
which
=
)
{
if
(
!
function_exists
(
$
function
)
)
{
$
err
=
'Callback does not exist: [function] '
.
$
function
.
'(...)'
;
return
false
;
}
$
ret
=
call_user_func_array
(
$
function
,
$
vars
)
;
if
(
!
is_null
(
$
which
)
)
{
$
err
=
$
vars
[
$
which
]
;
}
return
$
ret
;
}

Call a callback function

@param string $function		A valid function name
@param array $vars			An array of arguments to the function
@param string $err			An error message will be passed back to this if an error occurs
@param integer $which		If you want a particular $var to be passed the error message, specify which $var as an integer here (i.e. 0 to fill $var[0], 1 to fill $var[1], etc.)
@return mixed


static protected function _callStaticMethod($class_and_method, &$vars, &$err, $which = null)
	{
		$tmp = explode('::', $class_and_method);
		$class = current($tmp);
		$method = next($tmp);

		if (is_callable(array( $class, $method)))
		{
			$ret = call_user_func_array(array( $class, $method ), $vars);

			if (!is_null($which))
			{
				// *** WARNING *** This is a hack for just this _callStaticMethod routine, because the offset doesn't seem to be working correctly for static methods...
				//$which = $which - 1;

				$err = $vars[$which];
			}

			return $ret;
		}

		$err = 'Static method does not exist: ' . $class . '::' . $method . '(...)';
		return false;
	}

Call a static method of a class and return the result

@param string $class_and_method
@param array $vars
@param string $err
@param integer $which
@return mixed


public function findByName($Context, $realm, $name)
	{
		$xml = null;
		return parent::_findByName($Context, $realm, QuickBooks_IPP_IDS::RESOURCE_CUSTOMER, $name, $xml);
	}

public function findByName ( $ Context , $ realm , $ name ) { $ xml = null ; return parent :: _findByName ( $ Context , $ realm , QuickBooks_IPP_IDS :: RESOURCE_CUSTOMER , $ name , $ xml ) ; }

Get a customer by name

@param QuickBooks_IPP_Context $Context
@param string $realm
@param string $name						The name of the customer
@return QuickBooks_IPP_Object_Customer	The customer object


public function setClassApplicationID($value)
	{
		return $this->set('ClassRef ' . QUICKBOOKS_API_APPLICATIONID, $this->encodeApplicationID(QUICKBOOKS_OBJECT_CLASS, QUICKBOOKS_LISTID, $value));
	}

public
function
setClassApplicationID
(
$
value
)
{
return
$
this
->
set
(
'ClassRef '
.
QUICKBOOKS_API_APPLICATIONID
,
$
this
->
encodeApplicationID
(
QUICKBOOKS_OBJECT_CLASS
,
QUICKBOOKS_LISTID
,
$
value
)
)
;
}

Set the class application ID

@param mixed $value
@return boolean


public function getBillAddress($part = null, $defaults = array())
	{
		if (!is_null($part))
		{
			return $this->get('BillAddress ' . $part);
		}

		return $this->getArray('BillAddress *', $defaults);
	}

public
function
getBillAddress
(
$
part
=
,
$
defaults
=
array
(
)
)
{
if
(
!
is_null
(
$
part
)
)
{
return
$
this
->
get
(
'BillAddress '
.
$
part
)
;
}
return
$
this
->
getArray
(
'BillAddress *'
,
$
defaults
)
;
}

Get the billing address

@param string $part			A specific portion of the address to get (i.e. "Addr1" or "State")
@param array $defaults		Default values if a value isn't filled in
@return array				The address


public function setShipMethodApplicationID($value)
	{
		return $this->set('ShipMethodRef ' . QUICKBOOKS_API_APPLICATIONID, $this->encodeApplicationID(QUICKBOOKS_OBJECT_SHIPMETHOD, QUICKBOOKS_LISTID, $value));
	}

public
function
setShipMethodApplicationID
(
$
value
)
{
return
$
this
->
set
(
'ShipMethodRef '
.
QUICKBOOKS_API_APPLICATIONID
,
$
this
->
encodeApplicationID
(
QUICKBOOKS_OBJECT_SHIPMETHOD
,
QUICKBOOKS_LISTID
,
$
value
)
)
;
}

Set the application ID for the shipping method

@param mixed $value		The shipping method primary key from your application
@return 					boolean


public function setPaymentMethodApplicationID($value)
	{
		return $this->set('PaymentMethodRef ' . QUICKBOOKS_API_APPLICATIONID, $this->encodeApplicationID(QUICKBOOKS_OBJECT_PAYMENTMETHOD, QUICKBOOKS_LISTID, $value));
	}

public
function
setPaymentMethodApplicationID
(
$
value
)
{
return
$
this
->
set
(
'PaymentMethodRef '
.
QUICKBOOKS_API_APPLICATIONID
,
$
this
->
encodeApplicationID
(
QUICKBOOKS_OBJECT_PAYMENTMETHOD
,
QUICKBOOKS_LISTID
,
$
value
)
)
;
}

Set the application ID for the payment method

@param mixed $value		The payment method primary key from your application
@return 					boolean


protected function _generateFieldSchema($name, $def)
    {
        switch ($def[0])
        {
            case QUICKBOOKS_DRIVER_SQL_SERIAL:

                $sql = $name . ' INTEGER PRIMARY KEY  '; // AUTO_INCREMENT
                return $sql;
            case QUICKBOOKS_DRIVER_SQL_TIMESTAMP:
            case QUICKBOOKS_DRIVER_SQL_TIMESTAMP_ON_INSERT_OR_UPDATE:

                $sql = $name . ' TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ';
                return $sql;
            case QUICKBOOKS_DRIVER_SQL_TIMESTAMP_ON_UPDATE:

                $sql = $name . ' TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP ';
                return $sql;
            case QUICKBOOKS_DRIVER_SQL_TIMESTAMP_ON_INSERT:

                $sql = $name . ' TIMESTAMP DEFAULT CURRENT_TIMESTAMP ';
                return $sql;
            case QUICKBOOKS_DRIVER_SQL_BOOLEAN:
                $sql = $name . ' tinyint(1) ';

                if (isset($def[2]))
                {
                    if (strtolower($def[2]) == 'null')
                    {
                        $sql .= ' DEFAULT NULL ';
                    }
                    else if ($def[2])
                    {
                        $sql .= ' DEFAULT 1 ';
                    }
                    else
                    {
                        $sql .= ' DEFAULT 0 ';
                    }
                }

                return $sql;
            case QUICKBOOKS_DRIVER_SQL_INTEGER:
                $sql = $name . ' int(10) ';

                if (isset($def[2]))
                {
                    if (strtolower($def[2]) == 'null')
                    {
                        $sql .= ' DEFAULT NULL ';
                    }
                    else
                    {
                        $sql .= ' DEFAULT ' . (int) $def[2];
                    }
                }
                else
                {
                    $sql .= ' NOT NULL ';
                }

                return $sql;
            default:

                return parent::_generateFieldSchema($name, $def);
        }
    }

Override for the default SQL generation functions, MySQL-specific field generation function

@param string $name
@param array $def
@return string

Override for the default SQL generation functions MySQL - specific field generation function


protected function _getChildAtHelper($root, $path)
	{
		if (false !== strpos($path, ' ') and false === strpos($path, '/'))
		{
			$path = str_replace(' ', '/', $path);
		}

		$explode = explode('/', $path);
		//$explode = explode(' ', $path);
		$current = array_shift($explode);
		$next = current($explode);

		if ($path == $root->name())
		{
			return $root;
		}
		else if ($current == $root->name())
		{
			$path = implode('/', $explode);

			foreach ($root->children() as $child)
			{
				if ($child->name() == $next)
				{
					return $this->_getChildAtHelper($child, $path);
				}
			}
		}

		return false;
	}

protected
function
_getChildAtHelper
(
$
root
,
$
path
)
{
if
(
false
!==
strpos
(
$
path
,
' '
)
and
false
===
strpos
(
$
path
,
'/'
)
)
{
$
path
=
str_replace
(
' '
,
'/'
,
$
path
)
;
}
$
explode
=
explode
(
'/'
,
$
path
)
;
//$explode = explode(' ', $path);
$
current
=
array_shift
(
$
explode
)
;
$
next
=
current
(
$
explode
)
;
if
(
$
path
==
$
root
->
name
(
)
)
{
return
$
root
;
}
else
if
(
$
current
==
$
root
->
name
(
)
)
{
$
path
=
implode
(
'/'
,
$
explode
)
;
foreach
(
$
root
->
children
(
)
as
$
child
)
{
if
(
$
child
->
name
(
)
==
$
next
)
{
return
$
this
->
_getChildAtHelper
(
$
child
,
$
path
)
;
}
}
}
return
false
;
}

Recursive helper function - get child at location

@param QuickBooks_XML_Node $root
@param string $path
@return QuickBooks_XML_Node


public function addChildAt($path, $node, $create = false)
	{
		return $this->_addChildAtHelper($this, $path, $node, $create);
	}

public function addChildAt ( $ path , $ node , $ create = false ) { return $ this -> _addChildAtHelper ( $ this , $ path , $ node , $ create ) ; }

Add a child XML node at a particular path

@param string $path
@param QuickBooks_XML_Node $child
@param boolean $create
@return boolean


public function children($pattern = null)
	{
		if (!is_null($pattern))
		{
			$list = array();

			foreach ($this->_children as $Child)
			{
				if ($this->_fnmatch($pattern, $Child->name()))
				{
					$list[] = $Child;
				}
			}

			return $list;
		}

		return $this->_children;
	}

public function children ( $ pattern = null ) { if ( ! is_null ( $ pattern ) ) { $ list = array ( ) ; foreach ( $ this -> _children as $ Child ) { if ( $ this -> _fnmatch ( $ pattern , $ Child -> name ( ) ) ) { $ list [ ] = $ Child ; } } return $ list ; } return $ this -> _children ; }

Get an array of child nodes for this XML node

@param string $pattern
@return QuickBooks_XML_Node[]


public function removeAttribute($attr)
	{
		if ($this->attributeExists($attr))
		{
			unset($this->_attributes[$attr]);
			return true;
		}

		return false;
	}

public function removeAttribute ( $ attr ) { if ( $ this -> attributeExists ( $ attr ) ) { unset ( $ this -> _attributes [ $ attr ] ) ; return true ; } return false ; }

Remove an attribute from the XML node

@param string $attr
@return boolean


public function _asXMLHelper($node, $tabs, $empty, $indent)
	{
		$xml = '';

		if ($node->childCount())
		{
			$xml .= str_repeat($indent, $tabs) . '<' . $node->name();

			foreach ($node->attributes() as $key => $value)
			{
				// Make sure double-encode is *off*
				//$xml .= ' ' . $key . '="' . QuickBooks_XML::encode($value, true, false) . '"';
				$xml .= ' ' . $key . '="' . QuickBooks_XML::encode($value) . '"';
			}

			$xml .= '>' . "\n";
			foreach ($node->children() as $child)
			{
				$xml .= $this->_asXMLHelper($child, $tabs + 1, $empty, $indent);
			}
			$xml .= str_repeat($indent, $tabs) . '</' . $node->name() . '>' . "\n";
		}
		else
		{
			if ($node->hasAttributes())		// if the node has attributes, we'll build the whole thing no matter what
			{
				$xml .= str_repeat($indent, $tabs) . '<' . $node->name();

				foreach ($node->attributes() as $key => $value)
				{
					// Double-encode is *off*
					//$xml .= ' ' . $key . '="' . QuickBooks_XML::encode($value, true, false) . '"';
					$xml .= ' ' . $key . '="' . QuickBooks_XML::encode($value) . '"';
				}

				// Double-encode is *off*
				//$xml .= '>' . QuickBooks_XML::encode($node->data(), true, false) . '</' . $node->name() . '>' . "\n";
				$xml .= '>' . QuickBooks_XML::encode($node->data()) . '</' . $node->name() . '>' . "\n";
			}
			else
			{
				if ($node->data() == '__EMPTY__')		// ick, bad hack
				{
					$xml .= str_repeat($indent, $tabs) . '<' . $node->name() . '></' . $node->name() . '>' . "\n";
				}
				else if ($node->hasData() or $empty == QuickBooks_XML::XML_PRESERVE)
				{
					// Double-encode is *off*
					//$xml .= str_repeat($indent, $tabs) . '<' . $node->name() . '>' . QuickBooks_XML::encode($node->data(), true, false) . '</' . $node->name() . '>' . "\n";
					$xml .= str_repeat($indent, $tabs) . '<' . $node->name() . '>' . QuickBooks_XML::encode($node->data()) . '</' . $node->name() . '>' . "\n";
				}
				else if ($empty == QuickBooks_XML::XML_COMPRESS)
				{
					$xml .= str_repeat($indent, $tabs) . '<' . $node->name() . ' />' . "\n";
				}
				else if ($empty == QuickBooks_XML::XML_DROP)
				{
					; // do nothing, drop the empty element
				}
			}

		}

		return $xml;
	}

Resursive helper function for converting to XML

@param QuickBooks_XML_Node $node
@param integer $tabs
@param boolean $empty				A constant, one of: QUICKBOOKS_XML_XML_PRESERVE, QUICKBOOKS_XML_XML_DROP, QUICKBOOKS_XML_XML_COMPRESS
@param string $indent
@return string


public function asArray($mode = QuickBooks_XML::ARRAY_NOATTRIBUTES)
	{
		switch ($mode)
		{
			case QuickBooks_XML::ARRAY_EXPANDATTRIBUTES:
				return $this->_asArrayExpandAttributesHelper($this);
			case QuickBooks_XML::ARRAY_BRANCHED:
				return $this->_asArrayBranchedHelper($this);
			case QuickBooks_XML::ARRAY_PATHS:

				$current = '';
				$paths = array();
				$this->_asArrayPathsHelper($this, $current, $paths);

				return $paths;
			case QuickBooks_XML::ARRAY_NOATTRIBUTES:
			default:
				return $this->_asArrayNoAttributesHelper($this);
		}
	}

public function asArray ( $ mode = QuickBooks_XML :: ARRAY_NOATTRIBUTES ) { switch ( $ mode ) { case QuickBooks_XML :: ARRAY_EXPANDATTRIBUTES : return $ this -> _asArrayExpandAttributesHelper ( $ this ) ; case QuickBooks_XML :: ARRAY_BRANCHED : return $ this -> _asArrayBranchedHelper ( $ this ) ; case QuickBooks_XML :: ARRAY_PATHS : $ current = '' ; $ paths = array ( ) ; $ this -> _asArrayPathsHelper ( $ this , $ current , $ paths ) ; return $ paths ; case QuickBooks_XML :: ARRAY_NOATTRIBUTES : default : return $ this -> _asArrayNoAttributesHelper ( $ this ) ; } }

Get an array represtation of this XML node

@param string $mode
@return array


protected function _asArrayPathsHelper($node, $current, &$paths)
	{
		if ($node->hasChildNodes())
		{
			foreach ($node->children() as $child)
			{
				$this->_asArrayPathsHelper($child, $current . ' ' . $node->name(), $paths);
			}
		}
		else if ($node->hasData())
		{
			$paths[trim($current . ' ' . $node->name())] = $node->data();
		}
	}

protected
function
_asArrayPathsHelper
(
$
node
,
$
current
,
&
$
paths
)
{
if
(
$
node
->
hasChildNodes
(
)
)
{
foreach
(
$
node
->
children
(
)
as
$
child
)
{
$
this
->
_asArrayPathsHelper
(
$
child
,
$
current
.
' '
.
$
node
->
name
(
)
,
$
paths
)
;
}
}
else
if
(
$
node
->
hasData
(
)
)
{
$
paths
[
trim
(
$
current
.
' '
.
$
node
->
name
(
)
)
]
=
$
node
->
data
(
)
;
}
}

Helper function for converting to an array mapping paths to tag values

@param QuickBooks_XML_Node $node
@param string $current
@param array $paths
@return void


public function saveXML($path_or_resource, $mode = 'wb', $todo_for_empty_elements = QuickBooks_XML::XML_COMPRESS)
	{
		$xml = $this->asXML($todo_for_empty_elements);

		if (is_resource($path_or_resource))
		{
			return fwrite($path_or_resource, $xml);
		}

		$fp = fopen($path_or_resource, $mode);
		$bytes = fwrite($fp, $xml);
		fclose($fp);

		return $bytes;
	}

public function saveXML ( $ path_or_resource , $ mode = 'wb' , $ todo_for_empty_elements = QuickBooks_XML :: XML_COMPRESS ) { $ xml = $ this -> asXML ( $ todo_for_empty_elements ) ; if ( is_resource ( $ path_or_resource ) ) { return fwrite ( $ path_or_resource , $ xml ) ; } $ fp = fopen ( $ path_or_resource , $ mode ) ; $ bytes = fwrite ( $ fp , $ xml ) ; fclose ( $ fp ) ; return $ bytes ; }

Save this XML node structure as an XML file

@param mixed $path_or_resource			The filepath of the file you want write to *or* an opened file resource
@param string $mode						The mode to open the file in
@param boolean $todo_for_empty_elements	A constant, one of: QUICKBOOKS_XML_XML_COMPRESS, QUICKBOOKS_XML_XML_DROP, QUICKBOOKS_XML_XML_PRESERVE
@return integer							The number of bytes written to the file


public function saveJSON($path_or_resource, $mode = 'wb')
	{
		$json = $this->_root->asJSON();

		if (is_resource($path_or_resource))
		{
			return fwrite($path_or_resource, $json);
		}

		$fp = fopen($path_or_resource, $mode);
		$bytes = fwrite($fp, $json);
		fclose($fp);

		return $bytes;
	}

public function saveJSON ( $ path_or_resource , $ mode = 'wb' ) { $ json = $ this -> _root -> asJSON ( ) ; if ( is_resource ( $ path_or_resource ) ) { return fwrite ( $ path_or_resource , $ json ) ; } $ fp = fopen ( $ path_or_resource , $ mode ) ; $ bytes = fwrite ( $ fp , $ json ) ; fclose ( $ fp ) ; return $ bytes ; }

Save the XML node structure as a JSON document

@param mixed $path_or_resource
@param string $mode
@return integer


static protected function _castTruncate($value, $length, $with_abbrevs = true)
	{
		//$value = QuickBooks_Cast::_castCharset($value);

		if (strlen($value) > $length)
		{
			if ($with_abbrevs)
			{
				$value = QuickBooks_Cast::_castAbbreviations($value);
			}

			if (strlen($value) > $length)
			{
				$value = substr($value, 0, $length);
			}
		}

		// This breaks the UTF8 encoding
		//return utf8_encode($value);

		// Just return the data
		return $value;
	}

Shorten a string to a specific length by truncating or abbreviating the string

QuickBooks often uses unusually short field lengths. This function can
be used to try to make long strings fit cleanly into the QuickBooks
fields. It tries to do a few things:
- Convert long words to shorter abbreviations
- Remove non-ASCII characters
- Truncate the string if it's still too long

@param string $value				The string to shorten
@param integer $length			The max. length the string should be
@param boolean $with_abbrevs		Whether or not to abbreviate some long words to shorten the string
@return string					The shortened string


static protected function _decodeUTF8($string)
	{
		// don't do decoding when there are no 8bit symbols
		if (!QuickBooks_Cast::_is8Bit($string, 'utf-8'))
		{
			return $string;
		}

		// decode four byte unicode characters
		$string = preg_replace_callback("/([\360-\367])([\200-\277])([\200-\277])([\200-\277])/",
		function($arr)
		{
		    $val = ((ord($arr[1])-240)*262144+(ord($arr[2])-128)*4096+(ord($arr[3])-128)*64+(ord($arr[4])-128));
		    return "&#" . $val . ";";
		}, $string);

		// decode three byte unicode characters
		$string = preg_replace_callback("/([\340-\357])([\200-\277])([\200-\277])/",
		function($arr)
		{
		    $val = ((ord($arr[1])-224)*4096+(ord($arr[2])-128)*64+(ord($arr[3])-128));
		    return "&#" . $val . ";";
		}, $string);

		// decode two byte unicode characters
		$string = preg_replace_callback("/([\300-\337])([\200-\277])/",
		function($arr)
		{
		    $val = ((ord($arr[1])-192)*64+(ord($arr[2])-128));
		    return "&#" . $val . ";";
		}, $string);

		// remove broken unicode
		$string = preg_replace("/[\200-\237]|\240|[\241-\377]/", '?', $string);

		return $string;
	}

Decode a UTF-8 string to an entity encoded string

@param string $string 	Encoded string
@return string 			Decoded string

Decode a UTF - 8 string to an entity encoded string


static public function parseDSN($dsn, $defaults = array(), $part = null)
	{
		// Some DSN strings look like this:		filesystem:///path/to/file
		//	parse_url() will not parse this *unless* we provide some sort of hostname (in this case, null)
		$dsn = str_replace(':///', '://null/', $dsn);

		$defaults = array_merge(array(
			'scheme' => '',
			'host' => '',
			'port' => 0,
			'user' => '',
			'pass' => '',
			'path' => '',
			'query' => '',
			'fragment' => '',
			), $defaults);

		$parse = array_merge($defaults, parse_url($dsn));

		$parse['user'] = urldecode($parse['user']);
		$parse['pass'] = urldecode($parse['pass']);

		if (is_null($part))
		{
			return $parse;
		}
		else if (isset($parse[$part]))
		{
			return $parse[$part];
		}

		return null;
	}

Parse a DSN style connection string

@param string $dsn		The DSN connection string
@param string $part		If you want just a specific part of the string, choose which part here: scheme, host, port, user, pass, query, fragment
@return mixed 			An array or a string, depending on if you wanted the whole thing parsed or just a piece of it


static public function extractRequestID($xml)
	{
		$look = array(

			);

		if (false !== ($start = strpos($xml, ' requestID="')) and
			false !== ($end = strpos($xml, '"', $start + 12)))
		{
			return substr($xml, $start + 12, $end - $start - 12);
		}

		return false;
	}

static
public
function
extractRequestID
(
$
xml
)
{
$
look
=
array
(
)
;
if
(
false
!==
(
$
start
=
strpos
(
$
xml
,
' requestID="'
)
)
and
false
!==
(
$
end
=
strpos
(
$
xml
,
'"'
,
$
start
+
12
)
)
)
{
return
substr
(
$
xml
,
$
start
+
12
,
$
end
$
start
12
)
;
}
return
false
;
}

Extract the requestID attribute from an XML stream

@param string $xml	The XML stream to look for a requestID attribute in
@return mixed		The request ID


static public function parseRequestID($requestID, &$action, &$ident)
	{
		$tmp = explode('|', base64_decode($requestID));

		if (count($tmp) == 2)
		{
			$action = $tmp[0];
			$ident = $tmp[1];

			return true;
		}

		$action = null;
		$ident = null;

		return false;
	}

static public function parseRequestID ( $ requestID , & $ action , & $ ident ) { $ tmp = explode ( '|' , base64_decode ( $ requestID ) ) ; if ( count ( $ tmp ) == 2 ) { $ action = $ tmp [ 0 ] ; $ ident = $ tmp [ 1 ] ; return true ; } $ action = null ; $ ident = null ; return false ; }

Parse a requestID string into it's action and ident parts

@param string $requestID
@param string $action
@param mixed $ident
@return boolean

Parse a requestID string into it s action and ident parts


static protected function _checkCIDR($remoteaddr, $CIDR)
	{
		$remoteaddr_long = ip2long($remoteaddr);

		list ($net, $mask) = split('/', $CIDR);
		$ip_net = ip2long($net);
		$ip_mask = ~((1 << (32 - $mask)) - 1);

		$remoteaddr_net = $remoteaddr_long & $ip_mask;

		return $remoteaddr_net == $ip_net;
	}

static protected function _checkCIDR ( $ remoteaddr , $ CIDR ) { $ remoteaddr_long = ip2long ( $ remoteaddr ) ; list ( $ net , $ mask ) = split ( '/' , $ CIDR ) ; $ ip_net = ip2long ( $ net ) ; $ ip_mask = ~ ( ( 1 << ( 32 - $ mask ) ) - 1 ) ; $ remoteaddr_net = $ remoteaddr_long & $ ip_mask ; return $ remoteaddr_net == $ ip_net ; }

Check if a given IP address lies within a CIDR range

@param string $remoteaddr		The remote machine's IP address (example: 192.168.1.4)
@param string $CIDR				A CIDR network address (example: 192.168.0.0/24)
@return boolean


static public function createUser($dsn, $username, $password, $company_file = null, $wait_before_next_update = null, $min_run_every_n_seconds = null)
	{
		$driver = QuickBooks_Utilities::driverFactory($dsn);

		return $driver->authCreate($username, $password, $company_file, $wait_before_next_update, $min_run_every_n_seconds);
	}

static public function createUser ( $ dsn , $ username , $ password , $ company_file = null , $ wait_before_next_update = null , $ min_run_every_n_seconds = null ) { $ driver = QuickBooks_Utilities :: driverFactory ( $ dsn ) ; return $ driver -> authCreate ( $ username , $ password , $ company_file , $ wait_before_next_update , $ min_run_every_n_seconds ) ; }

Create a user for the QuickBooks Web Connector SOAP server

@param string $dsn		A DSN-style connection string for the back-end driver
@param string $username	The username for the new user
@param string $password	The password for the new user
@param string $company_file
@param string $wait_before_next_update
@param string $min_run_every_n_seconds
@return boolean


static public function disableUser($dsn, $username)
	{
		$driver = QuickBooks_Utilities::driverFactory($dsn);

		return $driver->authDisable($username);
	}

static public function disableUser ( $ dsn , $ username ) { $ driver = QuickBooks_Utilities :: driverFactory ( $ dsn ) ; return $ driver -> authDisable ( $ username ) ; }

Disable a user for the QuickBooks Web Connector SOAP server

@param string $dsn		A DSN-style connection string
@param string $username	The username for the user to disable
@return boolean


static public function generateUniqueHash($mixed1, $mixed2 = null, $mixed3 = null, $mixed4 = null, $mixed5 = null)
	{
		return md5(serialize($mixed1) . serialize($mixed2) . serialize($mixed3) . serialize($mixed4) . serialize($mixed5));
	}

static public function generateUniqueHash ( $ mixed1 , $ mixed2 = null , $ mixed3 = null , $ mixed4 = null , $ mixed5 = null ) { return md5 ( serialize ( $ mixed1 ) . serialize ( $ mixed2 ) . serialize ( $ mixed3 ) . serialize ( $ mixed4 ) . serialize ( $ mixed5 ) ) ; }

Generate a unique hash from a bunch of variables

@param mixed $mixed1
@param mixed $mixed2
@param mixed $mixed3
@param mixed $mixed4
@param mixed $mixed5
@return string


public static function hasQuickBooksID($dsn, $user, $object_type, $app_ID)
	{
		if (QuickBooks_Utilities::fetchQuickBooksID($dsn, $user, $object_type, $app_ID))
		{
			return true;
		}

		return false;
	}

public static function hasQuickBooksID ( $ dsn , $ user , $ object_type , $ app_ID ) { if ( QuickBooks_Utilities :: fetchQuickBooksID ( $ dsn , $ user , $ object_type , $ app_ID ) ) { return true ; } return false ; }

Tell whether or not a given object has a ListID or TxnID associated with it

* Note *
This function *does not* query QuickBooks, it only queries the internal
mapping of QuickBooks IDs to PRIMARY KEYS. The mappings can be created
with the {@link QuickBooks_Utilities::createMapping()} method and the API
tries to automatically create the mapping when you add or update an
object and provide a PRIMARY KEY when calling the ->add* or ->update*
method.

@param string $object_type
@param mixed $app_ID
@return boolean


static public function initialize($dsn, $driver_options = array(), $init_options = array())
	{
		$Driver = QuickBooks_Utilities::driverFactory($dsn, $driver_options);

		return $Driver->initialize($init_options);
	}

static public function initialize ( $ dsn , $ driver_options = array ( ) , $ init_options = array ( ) ) { $ Driver = QuickBooks_Utilities :: driverFactory ( $ dsn , $ driver_options ) ; return $ Driver -> initialize ( $ init_options ) ; }

Initialize the backend driver

Initialization should only be done once, and is used to take care of
things like creating the database schema, etc.

@param string $dsn				A DSN-style connection string
@param array $driver_options
@return boolean


static public function initialized($dsn, $driver_options = array())
	{
		$Driver = QuickBooks_Utilities::driverFactory($dsn, $driver_options);

		return $Driver->initialized();
	}

static public function initialized ( $ dsn , $ driver_options = array ( ) ) { $ Driver = QuickBooks_Utilities :: driverFactory ( $ dsn , $ driver_options ) ; return $ Driver -> initialized ( ) ; }

Tell whether or not a driver has been initialized

@param string $dsn
@param array $driver_options
@return boolean


static public function listObjects($filter = null, $return_keys = false, $order_for_mapping = false)
	{
		static $cache = array();

		$crunch = $filter . '[' . $return_keys . '[' . $order_for_mapping;

		if (isset($cache[$crunch]))
		{
			return $cache[$crunch];
		}

		$constants = array();

		foreach (get_defined_constants() as $constant => $value)
		{
			if (substr($constant, 0, strlen('QUICKBOOKS_OBJECT_')) == 'QUICKBOOKS_OBJECT_' and
				substr_count($constant, '_') == 2)
			{
				if (!$return_keys)
				{
					$constant = $value;
				}

				if ($filter)
				{
					if (QuickBooks_Utilities::fnmatch($filter, $constant))
					{
						$constants[] = $constant;
					}
				}
				else
				{
					$constants[] = $constant;
				}
			}
		}

		if ($order_for_mapping)
		{
			// Sort with the very longest values first, to the shortest values last
			usort($constants, function($a, $b){ return strlen($a) > strlen($b) ? -1 : 1; });
		}
		else
		{
			sort($constants);
		}

		$cache[$crunch] = $constants;

		return $constants;
	}

List all of the QuickBooks object types supported by the framework

@param string $filter
@param boolean $return_keys
@param boolean $order_for_mapping
@return array


static public function listActions($filter = null, $return_keys = false)
	{
		$startswith = array(
			'QUICKBOOKS_IMPORT_',
			'QUICKBOOKS_QUERY_',
			'QUICKBOOKS_ADD_',
			'QUICKBOOKS_MOD_',
			'QUICKBOOKS_DEL_',
			'QUICKBOOKS_VOID_',
			);

		$constants = array();

		//$inter_key = 'QUICKBOOKS_INTERACTIVE_MODE';
		//$inter_val = QUICKBOOKS_INTERACTIVE_MODE;
		/*
		if (is_null($filter))
		{
			if ($return_keys)
			{
				$constants[] = $inter_key;
			}
			else
			{
				$constants[] = $inter_val;
			}
		}
		*/
		/*
		else if ($return_keys and QuickBooks_Utilities::fnmatch($filter, $inter_key))
		{
			$constants[] = $inter_key;
		}
		else if (!$return_keys and QuickBooks_Utilities::fnmatch($filter, $inter_val))
		{
			$constants[] = $inter_val;
		}
		*/

		foreach (get_defined_constants() as $constant => $value)
		{
			foreach ($startswith as $start)
			{
				if (substr($constant, 0, strlen($start)) == $start)
				{
					if (!$return_keys)
					{
						$constant = $value;
					}

					if (!is_null($filter))
					{
						if (QuickBooks_Utilities::fnmatch($filter, $constant))
						{
							$constants[] = $constant;
						}
					}
					else
					{
						$constants[] = $constant;
					}
				}
			}
		}

		sort($constants);

		return $constants;
	}

List all of the QuickBooks actions the framework supports

@param string $filter
@param boolean $return_keys
@return array


protected function _escape($str)
	{
		if (is_array($str))
		{
			error_log('Param passed to _escape($str) was an array: ' . print_r($str, true));
			$str = '';
		}

		return $this->_conn->real_escape_string($str);
	}

Escape a string for the database

@param string $str
@return string


public function config()
	{
		$name = 'CodeIgniter QuickBooks Demo';			// A name for your server (make it whatever you want)
		$descrip = 'CodeIgniter QuickBooks Demo';		// A description of your server

		$appurl = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/qbwc';		// This *must* be httpS:// (path to your QuickBooks SOAP server)
		$appsupport = $appurl; 		// This *must* be httpS:// and the domain name must match the domain name above

		$username = $this->config->item('quickbooks_user');		// This is the username you stored in the 'quickbooks_user' table by using QuickBooks_Utilities::createUser()

		$fileid = QuickBooks_WebConnector_QWC::fileID();		// Just make this up, but make sure it keeps that format
		$ownerid = QuickBooks_WebConnector_QWC::ownerID();		// Just make this up, but make sure it keeps that format

		$qbtype = QUICKBOOKS_TYPE_QBFS;	// You can leave this as-is unless you're using QuickBooks POS

		$readonly = false; // No, we want to write data to QuickBooks

		$run_every_n_seconds = 600; // Run every 600 seconds (10 minutes)

		// Generate the XML file
		$QWC = new QuickBooks_WebConnector_QWC($name, $descrip, $appurl, $appsupport, $username, $fileid, $ownerid, $qbtype, $readonly, $run_every_n_seconds);
		$xml = $QWC->generate();

		// Send as a file download
		header('Content-type: text/xml');
		//header('Content-Disposition: attachment; filename="my-quickbooks-wc-file.qwc"');
		print($xml);
		exit;

	}

Generate and return a .QWC Web Connector configuration file

Generate and return a . QWC Web Connector configuration file


public function qbwc()
	{
		$user = $this->config->item('quickbooks_user');
		$pass = $this->config->item('quickbooks_pass');

		// Memory limit
		ini_set('memory_limit', $this->config->item('quickbooks_memorylimit'));

		// We need to make sure the correct timezone is set, or some PHP installations will complain
		if (function_exists('date_default_timezone_set'))
		{
			// * MAKE SURE YOU SET THIS TO THE CORRECT TIMEZONE! *
			// List of valid timezones is here: http://us3.php.net/manual/en/timezones.php
			date_default_timezone_set($this->config->item('quickbooks_tz'));
		}

		// Map QuickBooks actions to handler functions
		$map = array(
			QUICKBOOKS_ADD_CUSTOMER => array( array( $this, '_addCustomerRequest' ), array( $this, '_addCustomerResponse' ) ),
			);

		// Catch all errors that QuickBooks throws with this function
		$errmap = array(
			'*' => array( $this, '_catchallErrors' ),
			);

		// Call this method whenever the Web Connector connects
		$hooks = array(
			//QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => array( array( $this, '_loginSuccess' ) ), 	// Run this function whenever a successful login occurs
			);

		// An array of callback options
		$callback_options = array();

		// Logging level
		$log_level = $this->config->item('quickbooks_loglevel');

		// What SOAP server you're using
		//$soapserver = QUICKBOOKS_SOAPSERVER_PHP;			// The PHP SOAP extension, see: www.php.net/soap
		$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;		// A pure-PHP SOAP server (no PHP ext/soap extension required, also makes debugging easier)

		$soap_options = array(		// See http://www.php.net/soap
			);

		$handler_options = array(
			'deny_concurrent_logins' => false,
			'deny_reallyfast_logins' => false,
			);		// See the comments in the QuickBooks/Server/Handlers.php file

		$driver_options = array(		// See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
			'max_log_history' => 32000,	// Limit the number of quickbooks_log entries to 1024
			'max_queue_history' => 1024, 	// Limit the number of *successfully processed* quickbooks_queue entries to 64
			);

		// Build the database connection string
		$dsn = 'mysql://' . $this->db->username . ':' . $this->db->password . '@' . $this->db->hostname . '/' . $this->db->database;

		// Check to make sure our database is set up
		if (!QuickBooks_Utilities::initialized($dsn))
		{
			// Initialize creates the neccessary database schema for queueing up requests and logging
			QuickBooks_Utilities::initialize($dsn);

			// This creates a username and password which is used by the Web Connector to authenticate
			QuickBooks_Utilities::createUser($dsn, $user, $pass);
		}

		// Set up our queue singleton
		QuickBooks_WebConnector_Queue_Singleton::initialize($dsn);

		// Create a new server and tell it to handle the requests
		// __construct($dsn_or_conn, $map, $errmap = array(), $hooks = array(), $log_level = QUICKBOOKS_LOG_NORMAL, $soap = QUICKBOOKS_SOAPSERVER_PHP, $wsdl = QUICKBOOKS_WSDL, $soap_options = array(), $handler_options = array(), $driver_options = array(), $callback_options = array()
		$Server = new QuickBooks_WebConnector_Server($dsn, $map, $errmap, $hooks, $log_level, $soapserver, QUICKBOOKS_WSDL, $soap_options, $handler_options, $driver_options, $callback_options);
		$response = $Server->handle(true, true);
	}

SOAP endpoint for the Web Connector to connect to


public function _addCustomerRequest($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
	{
		// Do something here to load data using your model
		//$data = $this->yourmodel->getCustomerData($ID);

		// Build the qbXML request from $data
		$xml = '<?xml version="1.0" encoding="utf-8"?>
		<?qbxml version="2.0"?>
		<QBXML>
			<QBXMLMsgsRq onError="stopOnError">
				<CustomerAddRq requestID="' . $requestID . '">
					<CustomerAdd>
						<Name>ConsoliBYTE, LLC (' . mt_rand() . ')</Name>
						<CompanyName>ConsoliBYTE, LLC</CompanyName>
						<FirstName>Keith</FirstName>
						<LastName>Palmer</LastName>
						<BillAddress>
							<Addr1>ConsoliBYTE, LLC</Addr1>
							<Addr2>134 Stonemill Road</Addr2>
							<City>Mansfield</City>
							<State>CT</State>
							<PostalCode>06268</PostalCode>
							<Country>United States</Country>
						</BillAddress>
						<Phone>860-634-1602</Phone>
						<AltPhone>860-429-0021</AltPhone>
						<Fax>860-429-5183</Fax>
						<Email>Keith@ConsoliBYTE.com</Email>
						<Contact>Keith Palmer</Contact>
					</CustomerAdd>
				</CustomerAddRq>
			</QBXMLMsgsRq>
		</QBXML>';

		return $xml;
	}

Issue a request to QuickBooks to add a customer


public function _addCustomerResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
	{
		// Do something here to record that the data was added to QuickBooks successfully

		return true;
	}

Handle a response from QuickBooks indicating a new customer has been added


public function _catchallErrors($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
	{
		return false;
	}

public function _catchallErrors ( $ requestID , $ user , $ action , $ ID , $ extra , & $ err , $ xml , $ errnum , $ errmsg ) { return false ; }


final public function queueProcessing($user)
	{
		$hookdata = array(
			'username' => $user,
			);
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_QUEUEPROCESSING, null, $hookerr, $hookdata);

		return $this->_queueProcessing($user);
	}

final public function queueProcessing ( $ user ) { $ hookdata = array ( 'username' => $ user , ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_QUEUEPROCESSING , null , $ hookerr , $ hookdata ) ; return $ this -> _queueProcessing ( $ user ) ; }

Fetch the item currently being processed by QuickBooks

@param string $user
@return array


final public function recurEnqueue($user, $run_every, $action, $ident, $replace = true, $priority = 0, $extra = null, $qbxml = null)
	{
		$hookdata = array(
			'username' => $user,
			'interval' => $run_every,
			'action' => $action,
			'ident' => $ident,
			'replace' => $replace,
			'priority' => $priority,
			'extra' => $extra,
			'qbxml' => $qbxml,
			);
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE, null, $hookerr, $hookdata);

		return $this->_recurEnqueue($user, $run_every, $action, $ident, $replace, $priority, $extra, $qbxml);
	}

final public function recurEnqueue ( $ user , $ run_every , $ action , $ ident , $ replace = true , $ priority = 0 , $ extra = null , $ qbxml = null ) { $ hookdata = array ( 'username' => $ user , 'interval' => $ run_every , 'action' => $ action , 'ident' => $ ident , 'replace' => $ replace , 'priority' => $ priority , 'extra' => $ extra , 'qbxml' => $ qbxml , ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE , null , $ hookerr , $ hookdata ) ; return $ this -> _recurEnqueue ( $ user , $ run_every , $ action , $ ident , $ replace , $ priority , $ extra , $ qbxml ) ; }

Create a recurring event which will be queued up every so often...

@param integer $run_every
@param string $action
@param mixed $ident
@param boolean $replace
@param integer $priority
@param mixed $extra
@return boolean

Create a recurring event which will be queued up every so often ...


final public function recurDequeue($user, $by_priority = false)
	{
		$hookdata = array(
			'username' => $user,
			);
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE, null, $hookerr, $hookdata);

		return $this->_recurDequeue($user, $by_priority);
	}

final public function recurDequeue ( $ user , $ by_priority = false ) { $ hookdata = array ( 'username' => $ user , ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE , null , $ hookerr , $ hookdata ) ; return $ this -> _recurDequeue ( $ user , $ by_priority ) ; }

Fetch the next recurring event from the recurring event queue

@param boolean $by_priority
@return boolean


final public function queueLeft($user, $queued = true)
	{
		$hookdata = array(
			'username' => $user,
			'queued' => $queued,
			);
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_QUEUELEFT, null, $hookerr, $hookdata);

		return $this->_queueLeft($user, $queued);
	}

final public function queueLeft ( $ user , $ queued = true ) { $ hookdata = array ( 'username' => $ user , 'queued' => $ queued , ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_QUEUELEFT , null , $ hookerr , $ hookdata ) ; return $ this -> _queueLeft ( $ user , $ queued ) ; }

Tell the number of queued items left in the queue for a given user

@param string $user
@param boolean $queued
@return integer


final public function queueReport($user, $date_from, $date_to, $offset = 0, $limit = null)
	{
		$offset = max(0, (int) $offset);
		$limit = min(999999999, (int) $limit);

		$hookdata = array(
			'offset' => $offset,
			'limit' => $limit,
			'from' => $date_from,
			'to' => $date_to,
			);
		$hookerr = '';
		$this->_callHook(QuickBooks_Driver::HOOK_QUEUEREPORT, null, $hookerr, $hookdata);

		return $this->_queueReport($user, $date_from, $date_to, $offset, $limit);
	}

final public function queueReport ( $ user , $ date_from , $ date_to , $ offset = 0 , $ limit = null ) { $ offset = max ( 0 , ( int ) $ offset ) ; $ limit = min ( 999999999 , ( int ) $ limit ) ; $ hookdata = array ( 'offset' => $ offset , 'limit' => $ limit , 'from' => $ date_from , 'to' => $ date_to , ) ; $ hookerr = '' ; $ this -> _callHook ( QuickBooks_Driver :: HOOK_QUEUEREPORT , null , $ hookerr , $ hookdata ) ; return $ this -> _queueReport ( $ user , $ date_from , $ date_to , $ offset , $ limit ) ; }

Get a list of records from the queue for use in a report

@param string $date_from
@param string $date_to
@param integer $offset
@param integer $limit
@return array


final public function queueProcessed($ticket)
	{
		$hookdata = array();
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_QUEUEPROCESSED, $ticket, $hookerr, $hookdata);

		return $this->_queueProcessed($ticket);
	}

final public function queueProcessed ( $ ticket ) { $ hookdata = array ( ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_QUEUEPROCESSED , $ ticket , $ hookerr , $ hookdata ) ; return $ this -> _queueProcessed ( $ ticket ) ; }

Tell how many commands have been processed during this login session

@param string $ticket		The ticket for the login session
@return integer				The number of commands processed so far


final public function errorLog($ticket, $errno, $errstr)
	{
		$hookdata = array(
			'errno' => $errno,
			'errstr' => $errstr,
			);
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE, $ticket, $hookerr, array());

		return $this->_errorLog($ticket, $errno, $errstr);
	}

final public function errorLog ( $ ticket , $ errno , $ errstr ) { $ hookdata = array ( 'errno' => $ errno , 'errstr' => $ errstr , ) ; $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE , $ ticket , $ hookerr , array ( ) ) ; return $ this -> _errorLog ( $ ticket , $ errno , $ errstr ) ; }

Log an error that occured for a specific ticket

@param string $ticket
@param string $errno
@param string $errstr
@return boolean


final public function errorLast($ticket)
	{
		$hookerr = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE, $ticket, $hookerr, array());

		return $this->_errorLast($ticket);
	}

final public function errorLast ( $ ticket ) { $ hookerr = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE , $ ticket , $ hookerr , array ( ) ) ; return $ this -> _errorLast ( $ ticket ) ; }

Get the last error that occured

@param string $ticket
@return string


final public function authResolve($ticket)
	{
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE, $ticket, $err, array());

		return $this->_authResolve($ticket);
	}

final public function authResolve ( $ ticket ) { $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHRESOLVE , $ ticket , $ err , array ( ) ) ; return $ this -> _authResolve ( $ ticket ) ; }

Resolve a ticket string to a QuickBooks username

@param string $ticket
@return string


final public function authCheck($ticket)
	{
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHCHECK, $ticket, $err, array());

		return $this->_authCheck($ticket);
	}

final public function authCheck ( $ ticket ) { $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHCHECK , $ ticket , $ err , array ( ) ) ; return $ this -> _authCheck ( $ ticket ) ; }

Check to see whether or not a ticket is for a valid, unexpired login session

@param string $ticket	The login session ticket to check
@return boolean 			Whether or not the ticket is valid

Check to see whether or not a ticket is for a valid unexpired login session


final public function authLogout($ticket)
	{
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHLOGOUT, $ticket, $err, array());

		return $this->_authLogout($ticket);
	}

final public function authLogout ( $ ticket ) { $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHLOGOUT , $ ticket , $ err , array ( ) ) ; return $ this -> _authLogout ( $ ticket ) ; }

End a log-in session

@param string $ticket	The ticket for the session
@return boolean


final public function authCreate($username, $password, $company_file = null, $wait_before_next_update = null, $min_run_every_n_seconds = null)
	{
		$hookdata = array(
			'username' => $username,
			'password' => $password,
			'qb_company_file' => $company_file,
			'qbwc_wait_before_next_update' => $wait_before_next_update,
			'qbwc_min_run_every_n_seconds' => $min_run_every_n_seconds,
			);
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_AUTHCREATE, null, $err, $hookdata);

		return $this->_authCreate($username, $password, $company_file, $wait_before_next_update, $min_run_every_n_seconds);
	}

final public function authCreate ( $ username , $ password , $ company_file = null , $ wait_before_next_update = null , $ min_run_every_n_seconds = null ) { $ hookdata = array ( 'username' => $ username , 'password' => $ password , 'qb_company_file' => $ company_file , 'qbwc_wait_before_next_update' => $ wait_before_next_update , 'qbwc_min_run_every_n_seconds' => $ min_run_every_n_seconds , ) ; $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_AUTHCREATE , null , $ err , $ hookdata ) ; return $ this -> _authCreate ( $ username , $ password , $ company_file , $ wait_before_next_update , $ min_run_every_n_seconds ) ; }

Create a user account with the given username and password

@param string $username	The desired username
@param string $password	The desired password
@return boolean 			Whether or not the user was created


public function initialize($options)
	{
		$hookdata = array(
			'options' => $options,
			);
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_INITIALIZE, null, $err, $hookdata);

		return $this->_initialize($options);
	}

public function initialize ( $ options ) { $ hookdata = array ( 'options' => $ options , ) ; $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_INITIALIZE , null , $ err , $ hookdata ) ; return $ this -> _initialize ( $ options ) ; }

Initialize the driver class

@param array $options
@return boolean


public function initialized()
	{
		$hookdata = array();
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_INITIALIZED, null, $err, $hookdata);

		return $this->_initialized();
	}

public function initialized ( ) { $ hookdata = array ( ) ; $ err = '' ; $ this -> _callHook ( QUICKBOOKS_DRIVER_HOOK_INITIALIZED , null , $ err , $ hookdata ) ; return $ this -> _initialized ( ) ; }

Tell whether or not the driver class has been initialized

@return boolean


final public function log($msg, $ticket = null, $lvl = QUICKBOOKS_LOG_NORMAL)
	{
		/*
		$hookdata = array(
			'message' => $msg,
			'level' => $lvl,
			);
		$err = '';
		$this->_callHook(QUICKBOOKS_DRIVER_HOOK_LOG, $ticket, $err, $hookdata);
		*/

		if (is_null($lvl) or $this->_loglevel >= $lvl)
		{
			return $this->_log($msg, $ticket, $lvl);
		}

		return true;
	}

Log a message to the QuickBooks log

@param string $msg		The message to place in the log
@param string $ticket	The ticket for the login session
@param integer $lvl
@return boolean 			Whether or not the message was logged successfully


final protected function _callHook($hook, $ticket, &$err, $hook_data)
	{
		$user = '';
		if ($ticket)
		{
			$user = (string) $this->_authResolve($ticket);
		}

		// Call the hook
		QuickBooks_Callbacks::callHook($this, $this->_hooks, $hook, null, $user, $ticket, $err, $hook_data, null, __FILE__, __LINE__);

		if ($err)
		{
			// Log errors reporting by hooks
			$this->errorLog($ticket, QUICKBOOKS_ERROR_HOOK, $err);
		}

		return true;
	}

final
protected
function
_callHook
(
$
hook
,
$
ticket
,
&
$
err
,
$
hook_data
)
{
$
user
=
''
;
if
(
$
ticket
)
{
$
user
=
(
string
)
$
this
->
_authResolve
(
$
ticket
)
;
}
// Call the hook
QuickBooks_Callbacks
::
callHook
(
$
this
,
$
this
->
_hooks
,
$
hook
,
,
$
user
,
$
ticket
,
$
err
,
$
hook_data
,
,
__FILE__
,
__LINE__
)
;
if
(
$
err
)
{
// Log errors reporting by hooks
$
this
->
errorLog
(
$
ticket
,
QUICKBOOKS_ERROR_HOOK
,
$
err
)
;
}
return
true
;
}

Call any user-defined hooks hooked into a particular type of event

Hooks will be executed in the order they were added in. If any hook
returns FALSE, then execution for that type of hook will be stopped and
no other hooks will run. Errors reported via the $err parameter will be
logged using the driver logging mechanism.

@param string $hook			The type of hook we're to execute
@param string $ticket		The Web Connector ticket
@param string $err			Any error messages that should be reported
@param array $hook_data		An array of hook data
@return boolean

Call any user - defined hooks hooked into a particular type of event


public function connectOAuth($provider, $token, $pem_key, $encryption_key, $app_username, $app_tenant, $auth_id_pseudonym, $realm_id_pseudonym, $realm, $flavor)
	{
		if (!$this->_driver)
		{
			$this->_log('Could not connect to OAuth, no DRIVER storage instance.');
			return false;
		}

		$url = QuickBooks_IPP_Federator::URL_OAUTH;

		// First we need to push the request data into the OAuth storage
		$this->_driver->oauthRequestWrite(
			$app_username,
			$app_tenant,
			$auth_id_pseudonym,
			$realm_id_pseudonym);

		$params = array(
			'xoauth_service_provider_id' => $provider,
			'xoauth_auth_id_pseudonym' => $auth_id_pseudonym,
			'xoauth_realm_id_pseudonym' => $realm_id_pseudonym,
			);

		// Create our OAuth instance class
		$OAuth = new QuickBooks_IPP_OAuth(
			$token,		// The "consumer key" in this case is our application token
			'');		// There is no consumer secret

		$OAuth->signature(QuickBooks_IPP_OAuth::SIGNATURE_RSA, $pem_key);

		// Sign the request
		$sign = $OAuth->sign(QuickBooks_IPP_OAuth::METHOD_GET, $url, null, null, $params);

		// Now make our HTTP request to get the OAuth tokens
		$HTTP = new QuickBooks_HTTP($sign[2]);

		$HTTP->useDebugMode($this->_debug);

		$data = $HTTP->GET();

		$this->_log('OAuth HTTP request: [' . $HTTP->lastRequest() . ']');
		$this->_log('OAuth HTTP response: [' . $HTTP->lastResponse() . ']');

		if ($data)
		{
			$tmp = array();
			parse_str($data, $tmp);

			if (!empty($tmp['oauth_token']) and
				!empty($tmp['oauth_token_secret']))
			{
				// Store the OAuth tokens

				$this->_log('Storing OAuth tokens...');

				return $this->_driver->oauthAccessWrite(
					$encryption_key,
					$auth_id_pseudonym,
					$tmp['oauth_token'],
					$tmp['oauth_token_secret'],
					$realm,
					$flavor);
			}
		}

		return false;
	}

Fetch OAuth tokens with the data provided to you in the SAML request

Federated applications can use OAuth for unattended access to IDS data.
(i.e. access data even if the user isn't logged in) Before you start
using this, you have to make sure Intuit onboards you for OAuth access.

@param string $provider					Your federated provider id (Intuit should have given you this)
@param string $token						Your application token
@param string $key						The full path to your .pem file (e.g. /path/to/file.pem)
@param string $user						The username or user ID of the authenticating user
@param string $tenant					The tenant ID of the authenticating user
@param string $auth_id_pseudonym			The Auth ID Pseudonym extracted from the SAML message
@param string $realm_id_pseudonym		The Realm ID Pseudonym extracted from the SAML message
@return boolean


protected function _defaults($config)
	{
		$url = '?';
		if (isset($_SERVER['REQUEST_URI']))
		{
			$url = $_SERVER['REQUEST_URI'];
		}

		$defaults = array(
			'qb_company_file' => null,					// To force a specific company file to be used
			'qbwc_min_version' => null, 				// Minimum version of the QBWC that must be used to connect
			'qbwc_wait_before_next_update' => null, 	// Tell the QBWC to wait this number of seconds before doing another update
			'qbwc_min_run_every_n_seconds' => null,		// Tell the QBWC to run every n seconds (overrides whatever was in the .QWC web connector configuration file)
			'qbwc_version_warning_message' => null,		// Not implemented...
			'qbwc_version_error_message' => null,  		// Not implemented...
			'qbwc_interactive_url' => null, 			// Provide the URL for an interactive session to the QuickBooks Web Connector
			'autoadd_missing_requestid' => true,
			'check_valid_requestid' => true,
			'server_version' => 'PHP QuickBooks SOAP Server v' . QUICKBOOKS_PACKAGE_VERSION . ' at ' . $url,	// Server version string
			'authenticate' => null, 					// If you want to use some custom authentication scheme (and not the quickbooks_user MySQL table) you can specify your own function here
			'authenticate_dsn' => null, 				//		(backward compat. for 'authenticate')
			'map_application_identifiers' => true, 		// Try to map web application IDs to QuickBooks ListIDs/TxnIDs
			'allow_remote_addr' => array(),
			'deny_remote_addr' => array(),
			'convert_unix_newlines' => true,

			'deny_concurrent_logins' => true,
			'deny_concurrent_timeout' => 60,

			'deny_reallyfast_logins' => true,
			'deny_reallyfast_timeout' => 600,

			'masking' => true,
			);

		$config = array_merge($defaults, $config);

		// Make sure this is an *array* of addresses to allow
		if (!is_array($config['allow_remote_addr']))
		{
			$config['allow_remote_addr'] = array( $config['allow_remote_addr'] );
		}

		// Make sure this is an *array* of addresses to deny
		if (!is_array($config['deny_remote_addr']))
		{
			$config['deny_remote_addr'] = array( $config['deny_remote_addr'] );
		}

		$config['autoadd_missing_requestid'] = (boolean) $config['autoadd_missing_requestid'];
		$config['check_valid_requestid'] = (boolean) $config['check_valid_requestid'];
		$config['map_application_identifiers'] = (boolean) $config['map_application_identifiers'];
		$config['convert_unix_newlines'] = (boolean) $config['convert_unix_newlines'];

		$config['deny_concurrent_logins'] = (boolean) $config['deny_concurrent_logins'];
		$config['deny_concurrent_timeout'] = (int) max(1, $config['deny_concurrent_timeout']);

		$config['deny_reallyfast_logins'] = (boolean) $config['deny_reallyfast_logins'];
		$config['deny_reallyfast_timeout'] = (int) max(1, $config['deny_reallyfast_timeout']);

		return $config;
	}

Massage any optional configuration flags

@param array $config
@return array


protected function _handleRecurringEvents($ticket)
	{
		if ($user = $this->_driver->authResolve($ticket))
		{
			while ($next = $this->_driver->recurDequeue($user, true))
			{
				//$this->_driver->log('Dequeued a recurring event, enqueuing!', $ticket, QUICKBOOKS_LOG_VERBOSE);
				$this->_log('Dequeued a recurring event, enqueuing!', $ticket, QUICKBOOKS_LOG_VERBOSE);

				$extra = null;
				if ($next['extra'])
				{
					$extra = unserialize($next['extra']);
				}

				//print_r($next);

				$hookerr = '';
				$this->_callHook($ticket,
					QUICKBOOKS_HANDLERS_HOOK_RECURRING,
					null, 					//$this->_constructRequestID($next['qb_action'], $next['ident']),
					$next['qb_action'],
					$next['ident'],
					$extra,
					$hookerr);
				// $ticket, $hook, $requestID, $action, $ident, $extra, &$err, $xml = '', $qb_identifiers = array()

				//print_r($next);
				//exit;

				// (boolean) $next['replace']
				// 							$user, $action, $ident, $replace = true, $priority = 0, $extra = null, $qbxml = null
				$this->_driver->queueEnqueue($user, $next['qb_action'], $next['ident'], true, (int) $next['priority'], $extra, $next['qbxml']);
			}

			return true;
		}

		return false;
	}

Queue up recurring events that are overdue to be run

@param string $ticket
@return boolean


protected function _extractIdentifiers($xml)
	{
		$fetch_tagdata = array(
			'ListID',
			'TxnID',
			'OwnerID',
			'TxnLineID',
			'EditSequence',
			'FullName',
			'Name',
			'RefNumber',
			);

		$fetch_attributes = array(
			'requestID',
			'iteratorID',
			'iteratorRemainingCount',
			'metaData',
			'retCount',
			'statusCode',
			'statusSeverity',
			'statusMessage',
			'newMessageSetID',
			'messageSetStatusCode',
			);

		$list = array();

		foreach ($fetch_tagdata as $tag)
		{
			if (false !== ($start = strpos($xml, '<' . $tag . '>')) and
				false !== ($end = strpos($xml, '</' . $tag . '>')))
			{
				$list[$tag] = substr($xml, $start + 2 + strlen($tag), $end - $start - 2 - strlen($tag));
			}
		}

		foreach ($fetch_attributes as $attribute)
		{
			if (false !== ($start = strpos($xml, ' ' . $attribute . '="')) and
				false !== ($end = strpos($xml, '"', $start + strlen($attribute) + 3)))
			{
				$list[$attribute] = substr($xml, $start + strlen($attribute) + 3, $end - $start - strlen($attribute) - 3);
			}
		}

		return $list;
	}

protected
function
_extractIdentifiers
(
$
xml
)
{
$
fetch_tagdata
=
array
(
'ListID'
,
'TxnID'
,
'OwnerID'
,
'TxnLineID'
,
'EditSequence'
,
'FullName'
,
'Name'
,
'RefNumber'
,
)
;
$
fetch_attributes
=
array
(
'requestID'
,
'iteratorID'
,
'iteratorRemainingCount'
,
'metaData'
,
'retCount'
,
'statusCode'
,
'statusSeverity'
,
'statusMessage'
,
'newMessageSetID'
,
'messageSetStatusCode'
,
)
;
$
list
=
array
(
)
;
foreach
(
$
fetch_tagdata
as
$
tag
)
{
if
(
false
!==
(
$
start
=
strpos
(
$
xml
,
'<'
.
$
tag
.
'>'
)
)
and
false
!==
(
$
end
=
strpos
(
$
xml
,
'</'
.
$
tag
.
'>'
)
)
)
{
$
list
[
$
tag
]
=
substr
(
$
xml
,
$
start
+
2
+
strlen
(
$
tag
)
,
$
end
$
start
2
strlen
(
$
tag
)
)
;
}
}
foreach
(
$
fetch_attributes
as
$
attribute
)
{
if
(
false
!==
(
$
start
=
strpos
(
$
xml
,
' '
.
$
attribute
.
'="'
)
)
and
false
!==
(
$
end
=
strpos
(
$
xml
,
'"'
,
$
start
+
strlen
(
$
attribute
)
+
3
)
)
)
{
$
list
[
$
attribute
]
=
substr
(
$
xml
,
$
start
+
strlen
(
$
attribute
)
+
3
,
$
end
$
start
strlen
(
$
attribute
)
3
)
;
}
}
return
$
list
;
}

Extract a unique record identifier from an XML response

Some (most?) records within QuickBooks have unique identifiers which are
returned with the qbXML responses. This method will try to extract all
identifiers it can find from a qbXML response and return them in an
associative array.

For example, Customers have unique ListIDs, Invoices have unique TxnIDs,
etc. For an AddCustomer request, you'll get an array that looks like
this:

array(
'ListID' => '2C0000-1039887390'
)

Other transactions might have more than one identifier. For instance, a
call to AddInvoice returns both a ListID and a TxnID:

array(
'ListID' => '200000-1036881887', // This is actually part of the 'CustomerRef' entity in the Invoice XML response
'TxnID' => '11C26-1196256987', // This is the actual transaction ID for the Invoice XML response
)

*** IMPORTANT *** If there are duplicate fields (i.e.: 3 different
ListIDs returned) then only the first value encountered will appear in
the associative array.

The following elements/attributes are supported:
- ListID
- TxnID
- iteratorID
- OwnerID
- TxnLineID

@param string $xml	The XML stream to look for an identifier in
@return array		An associative array mapping identifier fields to identifier values


protected function _extractStatusCode($xml)
	{
		if (false !== ($start = strpos($xml, ' statusCode="')) and
			false !== ($end = strpos($xml, '"', $start + 13)))
		{
			return substr($xml, $start + 13, $end - $start - 13);
		}

		return QUICKBOOKS_ERROR_OK;
	}

protected
function
_extractStatusCode
(
$
xml
)
{
if
(
false
!==
(
$
start
=
strpos
(
$
xml
,
' statusCode="'
)
)
and
false
!==
(
$
end
=
strpos
(
$
xml
,
'"'
,
$
start
+
13
)
)
)
{
return
substr
(
$
xml
,
$
start
+
13
,
$
end
$
start
13
)
;
}
return
QUICKBOOKS_ERROR_OK
;
}

Extract the status code from an XML response

Each qbXML response should return a status code and a status message
indicating whether or not an error occured.

@param string $xml	The XML stream to look for a response status code in
@return integer		The response status code (0 if OK, another positive integer if an error occured)


protected function _extractStatusMessage($xml)
	{
		if (false !== ($start = strpos($xml, ' statusMessage="')) and
			false !== ($end = strpos($xml, '"', $start + 16)))
		{
			return substr($xml, $start + 16, $end - $start - 16);
		}

		return '';
	}

protected
function
_extractStatusMessage
(
$
xml
)
{
if
(
false
!==
(
$
start
=
strpos
(
$
xml
,
' statusMessage="'
)
)
and
false
!==
(
$
end
=
strpos
(
$
xml
,
'"'
,
$
start
+
16
)
)
)
{
return
substr
(
$
xml
,
$
start
+
16
,
$
end
$
start
16
)
;
}
return
''
;
}

Extract the status message from an XML response

Each qbXML response should return a status code and a status message
indicating whether or not an error occured.

@param string $xml	The XML stream to look for a response status message in
@return string		The response status message


protected function _callMappedFunction($which, $user, $requestID, $action, $ident, $extra, &$err, $last_action_time, $last_actionident_time, $xml_or_version = '', $qb_identifier_or_locale = array(), $qbxml = null)
	{
		if ($which == 0)
		{
			return QuickBooks_Callbacks::callRequestHandler($this->_driver, $this->_map, $requestID, $action, $user, $ident, $extra, $err, $last_action_time, $last_actionident_time, $xml_or_version, $qb_identifier_or_locale, $this->_callback_config, $qbxml);
		}
		else if ($which == 1)
		{
			return QuickBooks_Callbacks::callResponseHandler($this->_driver, $this->_map, $requestID, $action, $user, $ident, $extra, $err, $last_action_time, $last_actionident_time, $xml_or_version, $qb_identifier_or_locale, $this->_callback_config, $qbxml);
		}

		$err = 'Request for a mapped function could not be fulfilled, invalid $which parameter.';
		return false;
	}

Call the mapped function for a given action

@param integer $which			Whether or call the request action handler (pass a 0) or the response action handler (pass a 1)
@param string $user				QuickBooks username of the user the request/response is for
@param string $action
@param mixed $ident
@param mixed $extra
@param string $err				If the function returns an error message, the error message will be stored here
@param integer $last_action_time
@param integer $last_actionident_time
@param string $xml				A qbXML response (if you're calling the response handler)
@param array $qb_identifier
@return string


protected function _callHook($ticket, $hook, $requestID, $action, $ident, $extra, &$err, $xml = '', $qb_identifiers = array(), $hook_data = array())
	{
		$user = '';
		if ($ticket)
		{
			$user = $this->_driver->authResolve($ticket);
		}

		// Call the hook
		$ret = QuickBooks_Callbacks::callHook($this->_driver, $this->_hooks, $hook, $requestID, $user, $ticket, $err, $hook_data, $this->_callback_config, __FILE__, __LINE__);

		// If the hook reported an error, log the error
		if ($err)
		{
			$errerr = '';
			$this->_handleError($ticket, QUICKBOOKS_ERROR_HOOK, $err, $requestID, $action, $ident, $extra, $errerr, $xml, $qb_identifiers);
		}

		return true;
	}

Call a user-defined hook

@param string $ticket
@param string $hook
@param string $requestID
@param string $action
@param mixed $ident
@param mixed $extra
@param string $err
@param string $xml
@param array $qb_identifiers
@param array $hook_data
@return boolean


protected function _handleError($ticket, $errnum, $errmsg, $requestID, $action, $ident, $extra, &$err, $xml = '', $qb_identifiers = array())
	{
		// , $requestID, $user, $action, $ident, $extra, &$err, $xml, $qb_identifier
		// Call the error handler (if one is set)

		$errmsg = html_entity_decode($errmsg);

		// First, set the status of the item to error
		/*
		if ($action and $ident)
		{
			$this->_driver->queueStatus($ticket, $action, $ident, QUICKBOOKS_STATUS_ERROR, $errnum . ': ' . $errmsg);
		}
		*/
		if ($requestID)
		{
			$this->_driver->queueStatus($ticket, $requestID, QUICKBOOKS_STATUS_ERROR, $errnum . ': ' . $errmsg);
		}

		// Log the last error (for the ticket)
		$this->_driver->errorLog($ticket, $errnum, $errmsg);
		//$this->_driver->log('Attempting to handle error: ' . $errnum . ', ' . $errmsg);
		$this->_log('Attempting to handle error: ' . $errnum . ', ' . $errmsg, $ticket, QUICKBOOKS_LOG_NORMAL);

		// By default, we don't want to continue if the error is not handled
		$continue = false;

		// Get username of user which experienced the error
		$user = $this->_driver->authResolve($ticket);

		// CALL THE ERROR HANDLER
		$err = '';
		$continue = QuickBooks_Callbacks::callErrorHandler($this->_driver, $this->_onerror, $errnum, $errmsg, $user, $requestID, $action, $ident, $extra, $err, $xml, $this->_callback_config);
		//													$Driver, $errmap, $errnum, $errmsg, $user, $action, $ident, $extra, &$errerr, $xml, $callback_config

		if ($err)
		{
			// Log error messages returned by the error handler
			//$this->_driver->log('An error occured while handling error: ' . $errnum . ': ' . $errmsg . ': ' . $err, $ticket, QUICKBOOKS_LOG_NORMAL);
			$this->_log('An error occured while handling error: ' . $errnum . ': ' . $errmsg . ': ' . $err, $ticket, QUICKBOOKS_LOG_NORMAL);
			$this->_driver->errorLog($ticket, QUICKBOOKS_ERROR_HANDLER, $err);
		}

		// Log the last error (for the log)
		//$this->_driver->log('Handled error: ' . $errnum . ': ' . $errmsg . ' (handler returned: ' . $continue . ')', $ticket, QUICKBOOKS_LOG_NORMAL);
		$this->_log('Handled error: ' . $errnum . ': ' . $errmsg . ' (handler returned: ' . $continue . ')', $ticket, QUICKBOOKS_LOG_NORMAL);

		// Update the queue status
		//if ($action and $ident)
		if ($requestID and
			$continue)
		{
			//$this->_driver->queueStatus($ticket, $action, $ident, QUICKBOOKS_STATUS_HANDLED, $errnum . ': ' . $errmsg);
			$this->_driver->queueStatus($ticket, $requestID, QUICKBOOKS_STATUS_HANDLED, $errnum . ': ' . $errmsg);
		}

		return $continue;
	}

Call an error-handler function and update the status of a request to ERROR

@param string $ticket
@param integer $errnum		The error number from QuickBooks (see the QuickBooks SDK/IDN for a list of error codes)
@param string $errmsg		The error message from QuickBooks
@param string $requestID
@param string $action
@param mixed $ident
@param array $extra
@param string $err
@param string $xml
@param array $qb_identifiers

Call an error - handler function and update the status of a request to ERROR


public function enqueue($action, $ident, $priority = 0, $extra = null, $user = null)
	{
		$Queue = new QuickBooks_WebConnector_Queue($this->_dsn);

		return $Queue->enqueue($action, $ident, $priority, $extra, $user);
	}

public function enqueue ( $ action , $ ident , $ priority = 0 , $ extra = null , $ user = null ) { $ Queue = new QuickBooks_WebConnector_Queue ( $ this -> _dsn ) ; return $ Queue -> enqueue ( $ action , $ ident , $ priority , $ extra , $ user ) ; }

Queue up a request for the Web Connector to process


public function findByName($Context, $realmID, $name)
	{
		$IPP = $Context->IPP();

		if ($IPP->flavor() == QuickBooks_IPP_IDS::FLAVOR_DESKTOP)
		{
			for ($i = 0; $i < 999; $i++)
			{
				$list = $this->findAll($Context, $realmID, $name, $i, 50);

				foreach ($list as $Item)
				{
					if (strtolower($Item->getName()) == strtolower($name))
					{
						return $Item;
					}
				}
			}

			return false;
		}
		else
		{
			$xml = null;
			return parent::_findByName($Context, $realmID, QuickBooks_IPP_IDS::RESOURCE_ITEM, $name, $xml);
		}
	}

public function findByName ( $ Context , $ realmID , $ name ) { $ IPP = $ Context -> IPP ( ) ; if ( $ IPP -> flavor ( ) == QuickBooks_IPP_IDS :: FLAVOR_DESKTOP ) { for ( $ i = 0 ; $ i < 999 ; $ i ++ ) { $ list = $ this -> findAll ( $ Context , $ realmID , $ name , $ i , 50 ) ; foreach ( $ list as $ Item ) { if ( strtolower ( $ Item -> getName ( ) ) == strtolower ( $ name ) ) { return $ Item ; } } } return false ; } else { $ xml = null ; return parent :: _findByName ( $ Context , $ realmID , QuickBooks_IPP_IDS :: RESOURCE_ITEM , $ name , $ xml ) ; } }

Find an item by name

@param unknown_type $Context
@param unknown_type $realmID
@param unknown_type $name


protected function _startsWith($str, $startswith)
	{
		$length = strlen($startswith);

		return (substr($str, 0, $length)) == $startswith;
	}

protected function _startsWith ( $ str , $ startswith ) { $ length = strlen ( $ startswith ) ; return ( substr ( $ str , 0 , $ length ) ) == $ startswith ; }

Tell whether or not a string starts with another string

@param string $str
@param string $startswith
@return boolean


public function query($sql, $look = true)
	{
		if ($this->_driver)
		{
			if ($look)
			{
				$tmp = trim(strtoupper($sql));

				if ($this->_startsWith($sql, 'UPDATE '))
				{

				}
				else if ($this->_startsWith($sql, 'INSERT INTO '))
				{

				}
				else if ($this->_startsWith($sql, 'DELETE FROM '))
				{

				}
			}

			return $this->_driver->query($sql);
		}

		return false;
	}

public
function
query
(
$
sql
,
$
look
=
true
)
{
if
(
$
this
->
_driver
)
{
if
(
$
look
)
{
$
tmp
=
trim
(
strtoupper
(
$
sql
)
)
;
if
(
$
this
->
_startsWith
(
$
sql
,
'UPDATE '
)
)
{
}
else
if
(
$
this
->
_startsWith
(
$
sql
,
'INSERT INTO '
)
)
{
}
else
if
(
$
this
->
_startsWith
(
$
sql
,
'DELETE FROM '
)
)
{
}
}
return
$
this
->
_driver
->
query
(
$
sql
)
;
}
return
false
;
}

Execute an SQL query and return the result resource

@param string $sql		The SQL query to execute
@param boolean $look		Whether or not to examine the query and see if it's an INSERT/UPDATE/DELETE query
@return resource


static public function extractTagContents($tag, $data)
	{
		$tag = trim($tag, '<> ');

		if (false !== strpos($data, '<' . $tag . '>') and
			false !== strpos($data, '</' . $tag . '>'))
		{
			$data = strstr($data, '<' . $tag . '>');
			$end = strpos($data, '</' . $tag . '>');

			return substr($data, strlen($tag) + 2, $end - (strlen($tag) + 2));
		}

		return null;
	}

static
public
function
extractTagContents
(
$
tag
,
$
data
)
{
$
tag
=
trim
(
$
tag
,
'<> '
)
;
if
(
false
!==
strpos
(
$
data
,
'<'
.
$
tag
.
'>'
)
and
false
!==
strpos
(
$
data
,
'</'
.
$
tag
.
'>'
)
)
{
$
data
=
strstr
(
$
data
,
'<'
.
$
tag
.
'>'
)
;
$
end
=
strpos
(
$
data
,
'</'
.
$
tag
.
'>'
)
;
return
substr
(
$
data
,
strlen
(
$
tag
)
+
2
,
$
end
(
strlen
(
$
tag
)
+
2
)
)
;
}
return
;
}

Extract the contents from a particular XML tag in an XML string

<code>
$xml = '<document><stuff>bla bla</stuff><other>ble ble</other></document>';
$contents = QuickBooks_Utilities::_extractTagContents('stuff', $xml);
print($contents); 	// prints "bla bla"
</code>

@param string $tag		The XML tag to extract the contents from
@param string $data		The XML document
@return string			The contents of the tag


static public function extractTagAttributes($tag_w_attrs, $return_tag_first = false)
	{
		$tag = '';
		$attributes = array();

		$tag_w_attrs = trim($tag_w_attrs);

		/*if (substr($tag_w_attrs, -1, 1) == '/')		// condensed empty tag
		{
			$tag = trim($tag_w_attrs, '/ ');
			$attributes = array();
		}
		else*/
		if (false !== strpos($tag_w_attrs, ' '))
		{
			$tmp = explode(' ', $tag_w_attrs);
			//$tag = trim(array_shift($tmp), " \n\r\t<>");
			$tag = trim(array_shift($tmp));

			$attributes = array();

			$attrs = trim(implode(' ', $tmp));
			$length = strlen($attrs);

			$key = '';
			$value = '';
			$in_key = true;
			$in_value = false;
			$expect_key = false;
			$expect_value = false;

			for ($i = 0; $i < $length; $i++)
			{
				if ($attrs{$i} == '=')
				{
					$in_key = false;
					$in_value = false;
					$expect_value = true;
				}
				/*
				else if ($attrs{$i} == '"' and $expect_value)
				{
					$in_value = true;
					$expect_value = false;
				}
				*/
				/*else if ($attrs{$i} == '"' and $in_value)*/
				else if (($attrs{$i} == '"' or $attrs{$i} == '\'') and $expect_value)
				{
					$in_value = true;
					$expect_value = false;
				}
				else if (($attrs{$i} == '"' or $attrs{$i} == '\'') and $in_value)
				{
					$attributes[trim($key)] = $value;

					$key = '';
					$value = '';

					$in_value = false;
					$expect_key = true;
				}
				else if ($attrs{$i} == ' ' and $expect_key)
				{
					$expect_key = false;
					$in_key = true;
				}
				else if ($in_key)
				{
					$key .= $attrs{$i};
				}
				else if ($in_value)
				{
					$value .= $attrs{$i};
				}
			}

			/*
			foreach ($tmp as $attribute)
			{
				if (false !== ($pos = strpos($attribute, '=')))
				{
					$key = trim(substr($attribute, 0, $pos));
					$value = trim(substr($attribute, $pos + 1), '"');

					$attributes[$key] = $value;
				}
			}*/
		}
		else
		{
			$tag = $tag_w_attrs;
			$attributes = array();
		}

		// This returns the actual tag without attributes as the first key of the array
		if ($return_tag_first)
		{
			array_unshift($attributes, $tag);
		}

		return $attributes;
	}

Extract the attributes from a tag container

@todo Holy confusing code Batman!

@param string $tag_w_attributes
@param string $tag
@param array $attributes
@return void


static public function encode($str, $for_qbxml = true, $double_encode = true)
	{
		$transform = array(
			'&' => '&',
			'<' => '<',
			'>' => '>',
			//'\'' => ''',
			'"' => '"',
			);

		$str = str_replace(array_keys($transform), array_values($transform), $str);

		if (!$double_encode)
		{
			$fix = array();
			foreach ($transform as $raw => $encoded)
			{
				$fix[str_replace('&', '&', $encoded)] = $encoded;
			}

			$str = str_replace(array_keys($fix), array_values($fix), $str);
		}

		return $str;
	}

static
public
function
encode
(
$
str
,
$
for_qbxml
=
true
,
$
double_encode
=
true
)
{
$
transform
=
array
(
'&'
=>
'&'
,
'<'
=>
'<'
,
'>'
=>
'>'
,
//'\'' => ''',
'"'
=>
'"'
,
)
;
$
str
=
str_replace
(
array_keys
(
$
transform
)
,
array_values
(
$
transform
)
,
$
str
)
;
if
(
!
$
double_encode
)
{
$
fix
=
array
(
)
;
foreach
(
$
transform
as
$
raw
=>
$
encoded
)
{
$
fix
[
str_replace
(
'&'
,
'&'
,
$
encoded
)
]
=
$
encoded
;
}
$
str
=
str_replace
(
array_keys
(
$
fix
)
,
array_values
(
$
fix
)
,
$
str
)
;
}
return
$
str
;
}

Encode a string for use within an XML document

@todo Investigate QuickBooks qbXML encoding and implement solution

@param string $str				The string to encode
@param boolean $for_qbxml
@return string


static public function decode($str, $for_qbxml = true)
	{
		$transform = array(
			'<' => '<',
			'>' => '>',
			''' => '\'',
			'"' => '"',
			'&' => '&', 		// Make sure that this is *the last* transformation to run, otherwise we end up double-un-encoding things
			);

		return str_replace(array_keys($transform), array_values($transform), $str);
	}

Decode a string for use within an XML document

@todo Investigate QuickBooks qbXML encoding and implement solution

@param string $str				The string to encode
@param boolean $for_qbxml
@return string


public function check($app_username, $app_tenant)
	{
		if ($arr = $this->load($app_username, $app_tenant))
		{
			return true;
		}

		return false;
	}

public function check ( $ app_username , $ app_tenant ) { if ( $ arr = $ this -> load ( $ app_username , $ app_tenant ) ) { return true ; } return false ; }

Returns TRUE if an OAuth token exists for this user, FALSE otherwise

@param string $app_username
@return bool

Returns TRUE if an OAuth token exists for this user FALSE otherwise


public function load($app_username, $app_tenant)
	{
		if ($arr = $this->_driver->oauthLoad($this->_key, $app_username, $app_tenant) and
			strlen($arr['oauth_access_token']) > 0 and
			strlen($arr['oauth_access_token_secret']) > 0)
		{
			$arr['oauth_consumer_key'] = $this->_consumer_key;
			$arr['oauth_consumer_secret'] = $this->_consumer_secret;

			return $arr;
		}

		return false;
	}

public function load ( $ app_username , $ app_tenant ) { if ( $ arr = $ this -> _driver -> oauthLoad ( $ this -> _key , $ app_username , $ app_tenant ) and strlen ( $ arr [ 'oauth_access_token' ] ) > 0 and strlen ( $ arr [ 'oauth_access_token_secret' ] ) > 0 ) { $ arr [ 'oauth_consumer_key' ] = $ this -> _consumer_key ; $ arr [ 'oauth_consumer_secret' ] = $ this -> _consumer_secret ; return $ arr ; } return false ; }

Load OAuth credentials from the database

@param string $app_username
@return array