13 require_once dirname(__FILE__).
'/DAL.inc';
18 require_once dirname(__FILE__).
'/Exceptions/DALParserException.inc';
19 require_once dirname(__FILE__).
'/Exceptions/DALBakerException.inc';
20 require_once dirname(__FILE__).
'/Query.inc';
40 private static $_whereConditions = array(
43 'equal-or-greater' =>
'>=',
44 'equal-or-less' =>
'<=',
48 'not-like' =>
'NOT LIKE',
51 'is-null' =>
'IS NULL',
52 'not-null' =>
'NOT NULL',
61 private static $_assertionTypes = array(
67 'assert-greater-than',
79 private static $_forbiddenVariablecharacters = array(
103 private function __construct()
128 $systemPath = Channels::getSystemsPath($systemName);
129 $schemaXML = $systemPath.
'/DB/schema.xml';
130 if (file_exists($schemaXML) === FALSE) {
134 $doc =
new DomDocument();
135 $doc->load($schemaXML);
156 if (ChannelsBaker::systemExists($systemName) === FALSE) {
160 $schemaDoc = self::getSystemSchemaDocument($systemName);
161 if ($schemaDoc === NULL) {
165 $schemaNode = $schemaDoc->getElementsByTagName(
'schema');
166 if ($schemaNode->length === 0) {
170 $schemaNode = $schemaNode->item(0);
171 $schemaArray = self::parseSchema($schemaNode);
172 $converter = self::getConverter();
173 if (array_key_exists(
'CREATE', $schemaArray) === TRUE) {
174 foreach ($schemaArray[
'CREATE'] as $table) {
175 $tableName = $table[
'table'];
177 $exists = self::_dbTableExists($tableName, $converter);
178 if ($exists === FALSE) {
179 $sql = $converter->convertCreateTable($table);
186 if (file_exists($schemaOvenPath) === FALSE) {
187 mkdir($schemaOvenPath);
190 $fileName = $schemaOvenPath.
'/'.$systemName.
'.schema';
191 file_put_contents($fileName, $schemaDoc->saveXML());
211 if ($converter === NULL) {
212 $converter = self::getConverter();
215 if (self::_dbTableExists($tableName, $converter) === TRUE) {
216 $sql = $converter->convertDropTable($tableName);
237 if ($converter === NULL) {
238 $converter = self::getConverter();
241 $schema =
'\''.DAL::getDbName().
'\'';
242 $name =
'\''.$tableName.
'\'';
243 $sql = $converter->handleFunctionTableExists($name, $schema);
245 $row = $result->fetchAll();
246 $count = (int)current(current($row));
267 if (ChannelsBaker::systemExists($systemName) === FALSE) {
271 $systemPath = Channels::getSystemsPath($systemName);
272 $queryXML = $systemPath.
'/DB/queries.xml';
273 if (file_exists($queryXML) === FALSE) {
277 $success = self::processQueriesFile($systemName, $queryXML);
295 if (file_exists($fileName) === FALSE) {
299 $doc =
new DomDocument();
300 $doc->load($fileName);
301 $queryNode = $doc->getElementsByTagName(
'queries')->item(0);
305 foreach ($queryNode->childNodes as $child) {
306 if ($child->nodeType !== 1) {
312 if ($child->tagName ===
'query') {
313 if ($child->hasAttribute(
'id') === FALSE) {
314 $error =
'ID not specified for query in '.$systemName;
318 if ($child->hasAttribute(
'databases') === TRUE) {
319 $dbString = $child->getAttribute(
'databases');
320 $dbString = str_replace(
' ',
'', $dbString);
321 $dbs = explode(
',', $dbString);
322 if (in_array($currentDbType, $dbs) === FALSE) {
323 $id = $child->getAttribute(
'id');
324 echo
'Skipped Query: '.$id.
" (not for this DB type)\n";
329 if ($child->hasAttribute(
'hookid') === TRUE) {
330 $hookId = $child->getAttribute(
'hookid');
331 if (substr_count($hookId,
'.') === 1) {
333 self::addQueryFragment($systemName, $child);
336 self::addSubQuery($systemName, $child);
340 self::addQuery($systemName, $child);
368 $doc = self::getQueryXML($systemName, $queryName);
381 $baseQuery = $doc->getElementsByTagname(
'basequery')->item(0);
382 $primaryNode = $baseQuery->getElementsByTagName(
'primary');
383 if ($primaryNode->length === 0) {
384 $msg =
'No primary query found for query.';
386 }
else if ($primaryNode->length > 1) {
387 $msg =
'Multiple primary queries found in query';
393 $primaryNode = $primaryNode->item(0);
394 $alternateNodes = $baseQuery->getElementsByTagName(
'alternate');
396 $alternatives[] = $primaryNode;
397 $conditions = array();
399 foreach ($alternatives as $basePath) {
402 $queryParent = $basePath;
403 $previousNode = $queryParent;
405 if (in_array($queryParent->tagName, self::$_assertionTypes) === FALSE) {
406 $queryParent = $previousNode;
410 $previousNode = $queryParent;
414 $assertions = array();
416 $fragmentsNode = $doc->getElementsByTagName(
'fragments')->item(0);
417 foreach ($fragmentsNode->childNodes as $fragment) {
419 $types = self::$_assertionTypes;
421 if (count($assertionList) === 0) {
424 $select = $fragment->getElementsByTagName(
'select')->item(0);
425 $basePath = self::_combineFragment($basePath, $select);
426 $basePath = $doc->importNode($basePath, TRUE);
429 $assertions[] = $fragment;
435 $assertTree = self::_recurseAddAssertion($assertions);
439 $queryParent = $doc->importNode($queryParent, TRUE);
441 $queryBaseId = $systemName.
'_'.$queryName;
442 if ($queryParent->tagName !==
'primary') {
443 $queryBaseId .=
'Alternate'.$alternateCount;
447 if (count($assertions) !== 0) {
448 $phpCode = self::_recursePrintAssertions($assertTree, $queryParent, $queryBaseId);
451 $phpCode = self::_printNodeSql($queryParent, $queryBaseId);
459 if ($basePath->tagName ===
'primary') {
460 if (count($alternatives) > 1) {
461 $phpCode =
"{\n$phpCode\n}\n";
466 $phpCode = self::_printAlternateAssertions($basePath, $phpCode);
469 $conditions[] = $phpCode;
472 $completeCode = implode(
' else ', $conditions);
473 return $completeCode;
497 $assertVars = array();
498 foreach ($asserts as $assertion) {
499 $varName = self::_getAssertionVariableName($assertion);
500 $assertVars[] =
"($varName === TRUE)";
503 $condition =
'if ('.implode(
' && ', $assertVars).
") {\n";
504 return $condition.$contents.
"\n}";
538 if (empty($assertions) === TRUE) {
542 $currentAssertion = array_shift($assertions);
545 $elseChildren = self::_recurseAddAssertion($assertions, $currentStack);
546 $elseCondition = array(
547 'assertions' => $currentStack,
548 'children' => $elseChildren,
552 $currentStack[] = $currentAssertion;
554 $ifChildren = self::_recurseAddAssertion($assertions, $currentStack);
556 $ifCondition = array(
557 'current_assertion' => $currentAssertion,
558 'assertions' => $currentStack,
559 'children' => $ifChildren,
562 $retval[
'if_condition'] = $ifCondition;
563 $retval[
'else_condition'] = $elseCondition;
592 if (empty($tree) === TRUE) {
596 $ifCondition = $tree[
'if_condition'];
597 $elseCondition = $tree[
'else_condition'];
598 $currentAssert = $ifCondition[
'current_assertion'];
602 $types = self::$_assertionTypes;
604 $assertionNode = array_shift($assertionList);
605 $assertionChannel = $assertionNode->getAttribute(
'channel');
606 $assertVariable = self::_getAssertionVariableName($assertionNode);
609 $contents .=
"\nif ($assertVariable === TRUE) {\n";
610 if (empty($ifCondition[
'children']) === TRUE) {
612 $fragments = $ifCondition[
'assertions'];
613 $ifQuery = self::_mergeAllAssertions($baseQuery, $fragments);
615 foreach ($fragments as $queryPart) {
616 $idParts[] = $queryPart->getAttribute(
'id');
619 $contents .= self::_printNodeSql($ifQuery, $baseQueryId, $idParts);
622 $contents .= self::_recursePrintAssertions($ifCondition[
'children'], $baseQuery, $baseQueryId, ($level + 1));
625 $contents .=
"\n} else {\n";
626 if (empty($ifCondition[
'children']) === TRUE) {
628 $fragments = $elseCondition[
'assertions'];
629 $elseQuery = self::_mergeAllAssertions($baseQuery, $fragments);
631 foreach ($fragments as $queryPart) {
632 $idParts[] = $queryPart->getAttribute(
'id');
635 $contents .= self::_printNodeSql($elseQuery, $baseQueryId, $idParts);
638 $contents .= self::_recursePrintAssertions($elseCondition[
'children'], $baseQuery, $baseQueryId, ($level + 1));
642 $contents = str_replace(
"\n",
"\n$indentSpace", $contents);
665 $doc =
new DomDocument();
668 $returnQuery = $doc->importNode($baseQuery, TRUE);
669 foreach ($assertions as $fragment) {
672 $select = $fragment->getElementsByTagName(
'select')->item(0);
673 $returnQuery = self::_combineFragment($returnQuery, $select);
692 $doc = self::getQueryXML($systemName, $queryName);
695 $types = self::$_assertionTypes;
725 if ($assertion->hasAttribute(
'channel') === TRUE) {
726 $channelName = $assertion->getAttribute(
'channel');
727 if (trim($channelName) ===
'') {
731 list($system, $event) = explode(
'::', $channelName);
732 $variableName =
'$'.strtolower($system).ucfirst($event);
733 }
else if ($assertion->hasAttribute(
'data') === TRUE) {
734 $variableName =
'$'.$assertion->getAttribute(
'data').
'ChannelData';
735 $variableName .= str_replace(
'assert-',
'', $assertion->tagName);
737 $value = strval($assertion->getAttribute(
'value'));
738 if (strlen($value) > 5) {
739 $value = substr($value, 0, 5);
742 $variableName .= $value;
744 $functionCall = $assertion->getElementsByTagName(
'function-call');
745 if ($functionCall->length === 0) {
746 $error =
'No function call specified for assertion.';
750 $functionCall = $functionCall->item(0);
751 $argList = $functionCall->getElementsByTagName(
'arg');
752 $variableName = $functionCall->getAttribute(
'function');
753 foreach ($argList as $argNode) {
755 $argText = $argNode->nodeValue;
756 $replace = self::$_forbiddenVariablecharacters;
757 $argText = str_replace($replace,
' ', $argText);
758 $argText = str_replace(
' ',
'', ucwords($argText));
760 $variableName .= ucfirst($argText);
763 $variableName =
'$'.$variableName;
766 return $variableName;
788 $systemPath = dirname(__FILE__).
'/Oven/'.$systemName;
789 $fileName = $systemPath.
'/'.$queryName.
'.xml';
791 if (file_exists($systemPath) === FALSE) {
795 $contents =
'<querychannel system="'.$systemName.
'" query="';
796 $contents .= $queryName.
'">';
797 $contents .=
'<basequery />';
798 $contents .=
'<fragments />';
799 $contents .=
'<sub-queries />';
800 $contents .=
'</querychannel>';
802 return file_put_contents($fileName, $contents);
819 $systemPath = dirname(__FILE__).
'/Oven/'.$systemName;
820 $fileName = $systemPath.
'/'.$queryName.
'.xml';
822 return file_exists($fileName);
839 $systemPath = dirname(__FILE__).
'/Oven/'.$systemName;
840 $fileName = $systemPath.
'/'.$queryName.
'.xml';
842 if (self::queryXMLExists($systemName, $queryName) === FALSE) {
843 self::generateQueryXML($systemName, $queryName);
846 $doc =
new DomDocument();
847 $doc->load($fileName);
864 public static function saveQueryXML($system, $queryName, DomDocument $doc)
866 $systemPath = dirname(__FILE__).
'/Oven/'.$system;
867 $fileName = $systemPath.
'/'.$queryName.
'.xml';
869 if (file_exists($fileName)) {
873 $doc->save($fileName);
895 public static function addQuery($systemName, DomElement $query)
897 $queryId = $query->getAttribute(
'id');
900 self::generateQueryXML($systemName, $queryId);
903 $doc = self::getQueryXML($systemName, $queryId);
904 $queryNode = $doc->getElementsByTagName(
'basequery')->item(0);
906 if ($queryNode !== NULL) {
907 if ($queryNode->getElementsByTagName(
'query')->length !== 0) {
915 $query->setAttribute(
'system', $systemName);
916 $importedNode = self::_prepareFragment($query);
918 $importedNode = $doc->importNode($importedNode, TRUE);
920 $queryNode->appendChild($importedNode);
921 self::saveQueryXML($systemName, $queryId, $doc);
944 $fragment->setAttribute(
'system', $systemName);
948 $fragment = self::_prepareFragment($fragment);
950 $hookId = $fragment->getAttribute(
'hookid');
951 list($targetSystem, $targetQuery) = explode(
'.', $hookId);
954 self::generateQueryXML($targetSystem, $targetQuery);
957 $doc = self::getQueryXML($targetSystem, $targetQuery);
958 $fragmentsNode = $doc->getElementsByTagName(
'fragments')->item(0);
965 $importedNode = $doc->importNode($fragment, TRUE);
966 $fragmentsNode->appendChild($importedNode);
967 self::saveQueryXML($targetSystem, $targetQuery, $doc);
984 public static function addSubQuery($systemName, DomElement $subQuery)
988 $subQuery->setAttribute(
'system', $systemName);
992 $subQuery = self::_prepareFragment($subQuery);
994 $hookId = $subQuery->getAttribute(
'hookid');
995 list($targetSystem, $targetQuery) = explode(
'.', $hookId);
998 self::generateQueryXML($targetSystem, $targetQuery);
1001 $doc = self::getQueryXML($targetSystem, $targetQuery);
1002 $subQueriesNode = $doc->getElementsByTagName(
'sub-queries')->item(0);
1009 $importedNode = $doc->importNode($subQuery, TRUE);
1010 $subQueriesNode->appendChild($importedNode);
1011 self::saveQueryXML($targetSystem, $targetQuery, $doc);
1040 $doc =
new DomDocument();
1042 $query = $doc->importNode($query, TRUE);
1043 $fragment = $doc->importNode($fragment, TRUE);
1045 foreach ($fragment->childNodes as $section) {
1046 if ($section->nodeType !== 1) {
1053 $currentNode = $query->getElementsByTagName($section->tagName);
1054 if ($currentNode->length === 0) {
1057 $select = $query->getElementsByTagName(
'select')->item(0);
1058 $clone = $section->cloneNode(TRUE);
1059 $select->appendChild($clone);
1061 $currentNode = $currentNode->item(0);
1064 foreach ($section->childNodes as $condition) {
1065 if ($condition->nodeType !== 1) {
1072 $copy = $condition->cloneNode(TRUE);
1073 $currentNode->appendChild($copy);
1100 $doc =
new DomDocument();
1103 $returnQuery = $doc->importNode($query, TRUE);
1105 $returnQuery = self::_extractPlaceHolders($returnQuery);
1106 $returnQuery = self::_extractKeywords($returnQuery);
1108 $returnQuery = self::_extractBindings($returnQuery);
1109 $returnQuery = $doc->importNode($returnQuery, TRUE);
1111 return $returnQuery;
1136 if (trim($systemName) ===
'') {
1141 $ovenDir = dirname(__FILE__).
'/Oven/'.$systemName;
1143 if (file_exists($ovenDir) === FALSE) {
1147 $fileName = $ovenDir.
'/'.$systemName.
'Queries.inc';
1149 $contents =
'<?'.
"php\n\n";
1150 $contents .=
"require_once dirname(dirname(dirname(__FILE__))).'/DAL.inc';\n";
1151 $contents .=
"class $systemName".
"Queries\n{\n\n";
1154 $types = array(
'.xml');
1156 foreach ($xmlFiles as $queryName) {
1157 $queryName = basename($queryName,
'.xml');
1158 $contents .= self::bakeQueryMethod($systemName, $queryName);
1161 $contents .=
"\n\n}\n?>";
1163 file_put_contents($fileName, $contents);
1186 $methodName =
'prepare'.ucwords($queryName).
'Query';
1187 $contents =
"public static function $methodName(array \$data, \$bind)\n{\n";
1189 $contents .= self::_printPlaceHolderVariables($systemName, $queryName);
1191 $contents .=
"try {\n";
1194 $assertions = self::_getQueryAssertions($systemName, $queryName);
1197 $contents .= self::_printAssertionCalls($assertions);
1198 $contents .=
"} catch (ChannelException \$e) {\n";
1199 $contents .=
" // Exception thrown in the called channel.\n";
1204 $queryBody = self::mergeQuery($systemName, $queryName);
1205 $contents .= $queryBody;
1206 $subQueries = self::printSubQueries($systemName, $queryName);
1207 $contents .= $subQueries;
1208 $contents .= self::_printKeywords($systemName, $queryName);
1209 $contents .= self::_printBindings($systemName, $queryName);
1210 $contents .=
"\n}//end $methodName()\n";
1252 $assignments =
"\n// Initialise values for use in the conditions\n";
1258 $includedFiles = array();
1260 foreach ($assertions as $assertion) {
1261 $assignments .= self::_printAssertionInitialisation($assertion).
"\n";
1262 if ($assertion->hasAttribute(
'channel') === TRUE) {
1265 $channel = $assertion->getAttribute(
'channel');
1266 list($system, $methodName) = explode(
'::', $channel);
1269 if (in_array($system, $includedFiles) === FALSE) {
1271 $includes .=
"Channels::includeSystem('$system');\n";
1273 Channels::requireSystemActions($system);
1274 $includedFiles[] = $system;
1279 $comment =
"\n// Include required files for the assertion values.\n";
1280 if ($includes !==
'') {
1281 $includes = $comment.$includes;
1284 $contents = $includes.$assignments;
1307 if ($assertion->hasAttribute(
'channel') === TRUE) {
1309 $channel = $assertion->getAttribute(
'channel');
1310 list($system, $methodName) = explode(
'::', $channel);
1313 $actionsPath = Channels::getSystemsPath($system);
1314 $actionsPath .=
'/actions.xml';
1316 $eventDoc =
new DomDocument();
1317 $eventDoc->load($actionsPath);
1321 $actionNodes = $eventDoc->getElementsByTagName(
'action');
1322 foreach ($actionNodes as $node) {
1324 if ($node->getAttribute(
'name') === $methodName) {
1325 $parentNode = $node;
1330 $query = $parentNode->getElementsByTagName(
'query');
1331 $params = $parentNode->getElementsByTagName(
'param');
1334 $paramIndexes = array();
1335 foreach ($params as $param) {
1336 $paramIndexes[] =
'$data[\''.$param->getAttribute(
'name').
'\']
';
1339 // Construct the method call for the channel.
1340 $paramString = '(
'.implode(',
', $paramIndexes).')
';
1341 $methodCall = $channel.$paramString;
1343 // Maybe query channel :-) Query object itself isn't very useful..
1344 if ($query->length > 0) {
1345 $methodCall =
'DAL::executeDALQuery('.$methodCall.
')';
1347 }
else if ($assertion->hasAttribute(
'data') === TRUE) {
1349 $methodCall =
'$data[\''.$assertion->getAttribute(
'data').
'\']
';
1351 // This is probably a function call (no channel specified) so the
1352 // method call has to be extracted.
1353 $functionCall = $assertion->getElementsByTagName('function-call
');
1354 if ($functionCall->length === 0) {
1355 // No channel, and no function call. Nothing to assert.
1356 $error = 'No
function call specified
for assertion
';
1357 throw new DALBakerException($error);
1360 $functionCall = $functionCall->item(0);
1362 if ($functionCall->hasAttribute('function') === FALSE) {
1363 // No function specified for the function-call, which makes it
1364 // pretty tough to do anything.
1365 $error = 'No
function call specified
for assertion
';
1366 throw new DALBakerException($error);
1369 $functionName = $functionCall->getAttribute('function');
1370 $argList = $functionCall->getElementsByTagName('arg
');
1372 foreach ($argList as $argNode) {
1373 $args[] = self::_printAssertionArgument($argNode);
1376 $argString = implode(',
', $args);
1377 $methodCall = "$functionName($argString)";
1382 // Add the assignment call to the contents.
1383 switch ($assertion->tagName) {
1385 $methodCall = "($methodCall === TRUE)";
1387 case 'assert-
false':
1388 $methodCall = "($methodCall === FALSE)";
1391 $methodCall = "($methodCall === NULL)";
1393 case 'assert-empty
':
1394 // Can't call empty on
function return value,
do extra stuffs.
1395 $initCode =
'$empty = '.$methodCall.
';'.
"\n";
1396 $methodCall =
'(empty($empty) === TRUE)';
1398 case 'assert-equal':
1399 case 'assert-greater-than':
1400 case 'assert-less-than':
1401 if ($assertion->hasAttribute(
'value') === FALSE) {
1402 $msg =
'No value specified for comparison assertion.';
1406 $assertValue = $assertion->getAttribute(
'value');
1407 if ($assertion->tagName ===
'assert-equal') {
1409 }
else if ($assertion->tagName ===
'assert-greater-than') {
1415 $methodCall =
"($methodCall $operator $assertValue)";
1418 $error =
'Unknown Assertion Type: '.$assertion->tagName;
1422 $variableName = self::_getAssertionVariableName($assertion);
1424 return $initCode.$variableName.
' = '.$methodCall.
';';
1442 $type = $argNode->getAttribute(
'type');
1443 $data = $argNode->nodeValue;
1448 $argText =
"'$data'";
1474 protected static function _printNodeSql(DomElement $query, $baseId=
'', array $idParts=array())
1478 $sqlArray = self::constructSql($query);
1479 $sql = self::convertToSql($query, $sqlArray);
1480 $id = $baseId.md5(implode(
'_', $idParts));
1481 self::_writeQueryObject($id, $sqlArray, $sql);
1482 $returnQuery =
"\$query = DAL::getQueryObject('$id');\n";
1483 return $returnQuery;
1501 $queryObj =
new Query($id, $sqlArray, $sql);
1502 $objData = serialize($queryObj);
1503 $fileName = $id.
'.qob';
1505 if (file_exists($path) === TRUE) {
1506 if (unlink($path) === FALSE) {
1507 throw new DALException(
'Query object already exists, and was unable to be removed');
1511 file_put_contents($path, $objData);
1531 $doc = self::getQueryXML($systemName, $queryName);
1533 $contents =
"\n// Values that were hard-coded in query definitions.\n";
1535 $placeHolders = $doc->getElementsByTagName(
'placeholder');
1536 foreach ($placeHolders as $element) {
1537 $varName = substr($element->getAttribute(
'var_name'), 1);
1538 $varValue = $element->getAttribute(
'value');
1539 $contents .=
"\$$varName = '$varValue';\n";
1559 $hookIds = self::_generateHookArray($systemName, $queryName);
1560 return self::_printHookCode($hookIds);
1577 $doc = self::getQueryXML($systemName, $queryName);
1580 $hooks = $doc->getElementsByTagName(
'hook');
1581 foreach ($hooks as $hook) {
1582 $id = $hook->getAttribute(
'id');
1583 $hooksIds[$id] = array();
1584 $parent = $hook->parentNode;
1585 $hookIds[$id][
'parent-type'] = $parent->tagName;
1586 $hookIds[$id][
'sub-queries'] = array();
1589 $subNode = $doc->getElementsByTagName(
'sub-queries')->item(0);
1590 $queries = $subNode->getElementsByTagName(
'query');
1591 foreach ($queries as $subQuery) {
1592 $origHookId = $subQuery->getAttribute(
'hookid');
1593 $hookSys = $subQuery->getAttribute(
'system');
1594 $hookId = substr($origHookId, (strrpos($origHookId,
'.') + 1));
1596 if (array_key_exists($hookId, $hookIds) === FALSE) {
1602 'assertion_var' =>
'',
1603 'sub-query' => NULL,
1608 $select = $subQuery->getElementsByTagName(
'select')->item(0);
1610 if ($select === NULL) {
1611 $select = $subQuery->getElementsByTagName(
'hookQuery')->item(0);
1615 if (count($assertions) !== 0) {
1619 $assertionVar = self::_getAssertionVariableName($assertions[0]);
1621 $subData[
'assertion_var'] = $assertionVar;
1626 $tempDoc =
new DomDocument();
1627 $newSub =
"<query hookid=\"$origHookId\" system=\"$hookSys\">";
1628 $newSub .= $doc->saveXML($select).
'</query>';
1629 $tempDoc->loadXML($newSub);
1630 $queryNode = $tempDoc->getElementsByTagName(
'query')->item(0);
1633 $subData[
'sub-query'] = $queryNode;
1636 $hookIds[$hookId][
'sub-queries'][] = $subData;
1677 foreach ($hookIds as $id => $hookData) {
1678 $codeId = self::getHookCodeId($id);
1679 $arrayId = self::getHookArrayId($id);
1680 $contents .=
"\n// Setting up hook data for $id.\n\n";
1681 $contents .=
"$arrayId = array();\n";
1682 foreach ($hookData[
'sub-queries'] as $subQuery) {
1684 $subQueryNode = $subQuery[
'sub-query'];
1685 $subQueryId = $subQueryNode->getAttribute(
'id');
1686 $subQuerySys = $subQueryNode->getAttribute(
'system');
1687 $subQueryHook = $subQueryNode->getAttribute(
'hookid');
1688 $subObjectId =
'subquery_'.$id.
'_';
1689 $subObjectId .= md5($subQuerySys.$subQueryId.$subQueryHook);
1690 if ($subQuery[
'assertion_var'] !==
'') {
1691 $assertionVar = $subQuery[
'assertion_var'];
1692 $contents .=
"if ($assertionVar === TRUE) {\n ";
1695 $sqlArray = self::constructSql($subQuery[
'sub-query']);
1696 $sql = self::convertToSql($subQuery[
'sub-query'], $sqlArray);
1697 self::_writeQueryObject($subObjectId, $sqlArray, $sql);
1698 $contents .= $arrayId.
"[] = DAL::getQueryObject('$subObjectId');\n";
1700 if ($subQuery[
'assertion_var'] !==
'') {
1706 $contents .=
"\$query->subQueries('$id', $arrayId);\n";
1727 return 'HOOKID:'.$hookId;
1745 $str = ucwords(str_replace(
'_',
' ', $hookId));
1746 return '$'.str_replace(
' ',
'', $str).
'Array';
1764 switch (strtolower($tagName)) {
1766 $seperator =
'\nUNION-ALL\n';
1769 $seperator =
'\nAND\n';
1772 $seperator =
'\nOR\n';
1797 $doc = self::getQueryXML($systemName, $queryName);
1798 $keywords = $doc->getElementsByTagName(
'keyword');
1799 $processed = array();
1803 foreach ($keywords as $keyword) {
1804 if (in_array($keyword->nodeValue, $processed) === FALSE) {
1805 if ($arrayInit === FALSE) {
1807 $contents =
"\$queryKeywordsArray = array();\n";
1808 $suffix =
"\$query->keywords(\$queryKeywordArray);\n";
1812 $processed[] = $keyword->nodeValue;
1813 $contents .=
'$queryKeywordArray[\''.$keyword->nodeValue.
'\'] = $data[\
''.$keyword->nodeValue.
"'];\n";
1818 $contents .= $suffix;
1844 protected static function _printBindings($systemName, $queryName, $printBindings=TRUE)
1846 $doc = self::getQueryXML($systemName, $queryName);
1849 $bindingList = $doc->getElementsByTagName(
'binding');
1852 $placeHolders = array();
1853 $placeHoldersList = $doc->getElementsByTagName(
'placeholder');
1854 foreach ($placeHoldersList as $element) {
1855 $varName = $element->getAttribute(
'var_name');
1856 $varValue = $element->getAttribute(
'value');
1857 $placeHolders[$varName] = $varValue;
1860 $usedNames = array();
1861 foreach ($bindingList as $binding) {
1862 $bindName = $binding->getAttribute(
'name');
1865 $columnType = $binding->getAttribute(
'column_type');
1866 if ($columnType !==
'') {
1867 $dataType = self::_getPdoDataType($system, $table, $column, $columnType);
1869 $column = $binding->getAttribute(
'column');
1870 $table = $binding->getAttribute(
'table');
1871 $system = $binding->getAttribute(
'system');
1872 $dataType = self::_getPdoDataType($system, $table, $column);
1876 $index = substr($bindName, 1);
1880 if (isset($placeHolders[$bindName]) === TRUE) {
1882 $varName =
'$'.substr($bindName, 1);
1886 $varName =
"\$data['$index']";
1889 if ($printBindings === TRUE) {
1892 if (isset($placeHolders[$bindName]) === FALSE) {
1893 $bindCall =
"\nif (array_key_exists('$index',\$data) === TRUE) {\n";
1896 $bindCall .=
"\$query->bind('$bindName', $varName, $dataType);\n";
1898 if (isset($placeHolders[$bindName]) === FALSE) {
1899 $bindCall .=
"}\n\n";
1903 $contents .= $bindCall;
1908 $contents .=
"return \$query;\n";
1940 $doc =
new DomDocument();
1941 $query = $doc->importNode($fragment, TRUE);
1943 $bindingsParent = $doc->createElement(
'bindings');
1944 $query->appendChild($bindingsParent);
1945 $systemName = $fragment->getAttribute(
'system');
1947 $xmlString = $doc->saveXML($query);
1949 preg_match_all(
'/:[a-zA-Z\d_]+/i', $xmlString, $matches);
1950 $bindings = $matches[0];
1951 $bindingsCount = count($bindings);
1952 if ($bindingsCount === 0) {
1959 $allElements = $query->getElementsByTagName(
'*');
1960 foreach ($allElements as $element) {
1961 if ($element->childNodes->length === 1) {
1963 $nodeValue = trim($element->nodeValue);
1964 $bindMatches = array();
1965 preg_match(
'/:[a-zA-Z\d_]+/i', $nodeValue, $bindMatches);
1966 if (empty($bindMatches) === FALSE) {
1972 $fullTagValue = $doc->saveXML($element->firstChild);
1973 if (substr(trim($fullTagValue), 0, 1) !==
':') {
1980 $bindColumnType =
'';
1982 $bindSystem = $systemName;
1983 $bindName = $bindMatches[0];
1989 if ($element->hasAttribute(
'table') === FALSE) {
1990 if ($element->parentNode->hasAttribute(
'table') === TRUE) {
1991 $targetNode = $element->parentNode;
1992 }
else if ($element->tagName ===
'value') {
1995 $parent = $element->parentNode->parentNode;
1996 $fieldNode = $parent->getElementsByTagName(
'fields');
1997 if ($fieldNode->length !== 0) {
1998 $targetNode = $fieldNode->item(0);
2003 $targetNode = $element;
2006 $bindColumnType = $element->getAttribute(
'column_type');
2008 if ($targetNode !== NULL) {
2009 $bindColumn = $targetNode->getAttribute(
'column');
2010 if ($bindColumn ===
'') {
2011 $bindColumn = $element->getAttribute(
'column');
2014 $bindTable = $targetNode->getAttribute(
'table');
2019 $newBinding = $doc->createElement(
'binding');
2020 $newBinding->setAttribute(
'table', $bindTable);
2021 $newBinding->setAttribute(
'column', $bindColumn);
2022 $newBinding->setAttribute(
'column_type', $bindColumnType);
2024 $newBinding->setAttribute(
'system', $bindSystem);
2025 $newBinding->setAttribute(
'name', $bindName);
2026 $bindingsParent->appendChild($newBinding);
2051 $doc =
new DomDocument();
2052 $query = $doc->importNode($fragment, TRUE);
2055 $keywordParent = $doc->createElement(
'keywords');
2056 $query->appendChild($keywordParent);
2057 $xmlString = $doc->saveXML($query);
2060 preg_match_all(
'/\[([a-zA-Z0-9]+)\]/m', $xmlString, $matches);
2062 if (isset($matches[1]) === TRUE && empty($matches[1]) === FALSE) {
2063 foreach ($matches[1] as $keyword) {
2064 $newKeyword = $doc->createElement(
'keyword');
2065 $newKeyword->nodeValue = $keyword;
2066 $keywordParent->appendChild($newKeyword);
2094 $doc =
new DomDocument();
2095 $query = $doc->importNode($fragment, TRUE);
2097 $placeParent = $doc->createElement(
'placeholders');
2098 $query->appendChild($placeParent);
2099 $systemName = $fragment->getAttribute(
'system');
2100 $queryId = $fragment->getAttribute(
'id');
2102 $allElements = $query->getElementsByTagName(
'value');
2103 foreach ($allElements as $element) {
2104 if ($element->childNodes->length === 1) {
2106 $nodeValue = trim($element->nodeValue);
2107 if ($nodeValue ===
'') {
2111 if ($element->tagName ===
'table') {
2115 if (substr($nodeValue, 0, 1) ===
':') {
2120 if (substr($nodeValue, 0, 1) ===
'[') {
2133 if ($element->hasAttribute(
'table') === FALSE) {
2134 if ($element->parentNode->hasAttribute(
'table') === TRUE) {
2135 $targetNode = $element->parentNode;
2136 }
else if ($element->tagName ===
'value') {
2139 $parent = $element->parentNode->parentNode;
2140 $fieldNode = $parent->getElementsByTagName(
'fields');
2141 if ($fieldNode->length !== 0) {
2142 $targetNode = $fieldNode->item(0);
2144 }
else if ($element->tagName ===
'table') {
2145 $placeTable = $nodeValue;
2146 $targetNode = $element;
2150 $targetNode = $element;
2153 if ($targetNode === NULL) {
2157 if ($placeColumn ===
'') {
2158 if ($targetNode->hasAttribute(
'column') === TRUE) {
2159 $placeColumn = $targetNode->getAttribute(
'column');
2162 $placeColumn = $queryId;
2166 if ($placeTable ===
'') {
2167 if ($targetNode->hasAttribute(
'table') === TRUE) {
2168 $placeTable = $targetNode->getAttribute(
'table');
2171 $placeTable = $systemName;
2177 $newPlaceHolder = $doc->createElement(
'placeholder');
2178 $varName = $placeTable.
' '.$placeColumn;
2179 $varName = ucwords(str_replace(
'_',
' ', $varName));
2180 $varName =
':'.str_replace(
' ',
'', $varName);
2181 $newPlaceHolder->setAttribute(
'value', $element->nodeValue);
2182 $newPlaceHolder->setAttribute(
'var_name', $varName);
2183 $placeParent->appendChild($newPlaceHolder);
2185 $element->nodeValue = $varName;
2210 if ($dataType === NULL) {
2211 $dataType = self::getTableColumnTypes($systemId, $table, $column);
2214 switch (strtoupper($dataType)) {
2220 case 'DOUBLE PRECISION':
2222 $pdoType =
'PDO::PARAM_INT';
2225 $pdoType =
'PDO::PARAM_BOOL';
2228 $pdoType =
'PDO::PARAM_STR';
2246 require_once
'DAL/Parsers/DALSchemaParser.inc';
2273 if ($queries->getAttribute(
'system') ===
'') {
2279 $qs = $queries->getElementsByTagName(
'query');
2280 foreach ($qs as $query) {
2281 $id = $query->getAttribute(
'id');
2282 if (in_array($id, $ids) === TRUE) {
2303 $xp =
new DOMXPath($doc);
2304 $qry =
'//query[@id = "'.$query->getAttribute(
'id').
'"]';
2305 $nodes = $xp->query($qry);
2307 foreach ($nodes as $node) {
2308 if ($node !== $query) {
2333 $doc = $query->ownerDocument;
2334 $queryId = $query->getAttribute(
'id');
2336 if ($queryId ===
'') {
2338 }
else if (self::queryIdIsUnique($doc, $query) === FALSE) {
2339 $msg =
'Query must have a unique id. Id "'.$queryId;
2340 $msg .=
'" already used by another query.';
2344 $type = self::getQueryType($query);
2345 $fn =
'validate'.ucwords($type).
'Query';
2346 if (method_exists(
'DALBaker', $fn) === FALSE) {
2365 foreach ($query->childNodes as $child) {
2366 if ($child->nodeType !== XML_ELEMENT_NODE) {
2370 return $child->tagName;
2389 list($hsysid, $hqid) = explode(
'.', $hookid);
2391 $doc = self::loadBakedQuery($hsysid, $hqid);
2392 if ($doc === NULL) {
2396 $queries = $doc->getElementsByTagName(
'query');
2398 foreach ($queries as $query) {
2399 if ($query->getAttribute(
'id') === $queryid) {
2400 if ($query->getAttribute(
'system') === $system) {
2421 public static function convertToSql(DomElement $xmlQuery, array $sqlArray=array())
2423 if (empty($sqlArray) === TRUE) {
2424 $sqlArray = self::constructSql($xmlQuery);
2427 $converter = self::getConverter();
2428 return $converter->convertToSql($sqlArray[
'query']);
2445 if ($dbType === NULL) {
2446 $dbType = ucfirst(self::getDatabaseType());
2451 $converterClass =
'DAL'.$dbType.
'Converter';
2452 require_once
'Converters/'.$converterClass.
'.inc';
2454 $converter = eval(
"return new DAL$dbType".
'Converter();');
2476 if ($column === NULL) {
2479 $column = strtolower($column);
2483 $doc = self::loadSystemSchemaXML($systemid);
2484 if ($doc === NULL) {
2489 $tables = $doc->getElementsByTagName(
'table');
2490 foreach ($tables as $currTable) {
2491 if ($currTable->getAttribute(
'name') === $table) {
2493 $colsTag = $currTable->getElementsByTagName(
'columns')->item(0);
2494 $cols = $colsTag->getElementsByTagName(
'column');
2495 foreach ($cols as $col) {
2496 if ($column === strtolower($col->nodeValue)) {
2497 return $col->getAttribute(
'type');
2498 }
else if ($column === NULL) {
2499 $types[strtolower($col->nodeValue)] = $col->getAttribute(
'type');
2526 $queriesXML = self::loadQueriesXML($systemid);
2528 if ($queriesXML !== NULL) {
2530 $queries = $queriesXML->getElementsByTagName(
'query');
2531 foreach ($queries as $query) {
2532 if ($query->getAttribute(
'id') === $queryid) {
2558 if (file_exists($ovenPath) === TRUE) {
2561 if (mkdir($ovenPath, 0775, TRUE) === FALSE) {
2562 $msg =
'Could not create directory: '.$ovenPath;
2563 throw new ChannelException($msg);
2584 $fileName = Channels::getSystemsPath($systemid).
'/DB/queries.xml';
2585 if (file_exists($fileName) === FALSE) {
2589 $doc =
new DOMDocument();
2590 $doc->load($fileName);
2625 $fileName = self::getBakedQueryFileName($systemid, $queryid);
2626 if (file_exists($fileName) === FALSE) {
2630 $doc =
new DOMDocument();
2631 $doc->load($fileName);
2650 $fileName = Channels::getSystemsPath($systemid).
'/DB/schema.xml';
2651 if (file_exists($fileName) === FALSE) {
2655 $doc =
new DOMDocument();
2656 $doc->load($fileName);
2684 require_once dirname(__FILE__).
'/Parsers/DALQueryParser.inc';
2705 $prefix =
'HOOKID:';
2721 if ($type !== NULL) {
2722 if (isset(self::$_whereConditions[$type]) === TRUE) {
2723 return self::$_whereConditions[$type];
2729 return self::$_whereConditions;
2745 if ($dsn === NULL) {
2748 $dbType = $dsn[
'type'];
2753 $fullType =
'postgres';
2756 $fullType =
'oracle';
2762 $fullType =
'mssql';
2765 $fullType = $dbType;