File/@xlink:href
https://biuro.biall-net.pl/wfs/objects#File.45
* TODO: in SqlQueryWhereBuilder split query for main database and join-ed db (right join in ref's)
*
* @usage:
$parser = new ParseOgcFilter();
$parser->loadOgcFilter($ogcFilter);
$queryWhereBuilder = $parser->convertToSqlQueryWhereBuilder();
$query = $queryWhereBuilder->getQueryWhere('t');
*
*/
class ParseOgcFilter {
public $_ogcFilter = '';
public function __construct() {
}
public function loadOgcFilter($ogcFilter) {
// validate?
$this->_ogcFilter = $ogcFilter;
}
public function convertToSqlQueryWhereBuilder() {
$ogcFilterXmlString = '' . "\n";
$ogcFilterXmlString .= <<
{$this->_ogcFilter}
OGC_FILTER_XML_FILE;
$convertedGuiXml = $this->_convertOgcFilterToCmdList($ogcFilterXmlString);
DBG::_('DBG_DS_OGC', '>1', "convertedGuiXml(".strlen($convertedGuiXml).")", $convertedGuiXml, __CLASS__, __FUNCTION__, __LINE__);
$tags = array();
$parserXml = xml_parser_create();
xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
if (0 == xml_parse_into_struct($parserXml, $convertedGuiXml, $tags)) {
throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction failed");
}
xml_parser_free($parserXml);
if (empty($tags)) {
throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction returns empty structure");
}
$queryWhereBuilder = new SqlQueryWhereBuilder();
foreach ($tags as $tag) {
switch ($tag['tag']) {
case 'filter': {// root tag
}
break;
case 'sql_filter_comparisonFieldToValue': {
$fieldName = V::get('fieldName', '', $tag['attributes']);
$fieldFunction = V::get('fieldFunction', null, $tag['attributes']);
$comparisonSign = V::get('comparisonSign', '', $tag['attributes']);
$value = V::get('value', '', $tag['attributes']);
DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue comparisonSign", $comparisonSign, __CLASS__, __FUNCTION__, __LINE__);
if ('like' == $comparisonSign) {
$wildCard = V::get('wildCard', '', $tag['attributes']);
$singleChar = V::get('singleChar', '', $tag['attributes']);
$escapeChar = V::get('escapeChar', '', $tag['attributes']);
// wildCard="*" singleChar="#" escapeChar="!" => sql: % _ \
// '*ORMA!*' => '%ORMA\*'
// TODO: first replace every escapeChar
$valLength = strlen($value);
$valCharsAllowReplace = array(); for ($i = 0; $i < $valLength; $i++) $valCharsAllowReplace[] = true;
{// escapeChar
$lastOffset = 0;
while (false !== ($pos = strpos($value, $escapeChar, $lastOffset))) {
DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue like value({$value}) escapeChar({$escapeChar}) pos({$pos}) lastOffset({$lastOffset})", null, __CLASS__, __FUNCTION__, __LINE__);
$value[$pos] = '\\';
$valCharsAllowReplace[$pos] = false;
if ($pos + 1 < $valLength) $valCharsAllowReplace[$pos + 1] = false;
$lastOffset = $pos + 1;
}
}
{// singleChar
$lastOffset = 0;
while (false !== ($pos = strpos($value, $singleChar, $lastOffset))) {
DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue like value({$value}) singleChar({$singleChar}) pos({$pos}) lastOffset({$lastOffset})", null, __CLASS__, __FUNCTION__, __LINE__);
if ($valCharsAllowReplace[$pos]) {
$value[$pos] = '_';
$valCharsAllowReplace[$pos] = false;
}
$lastOffset = $pos + 1;
}
}
{// wildCard
$lastOffset = 0;
while (false !== ($pos = strpos($value, $wildCard, $lastOffset))) {
DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue like value({$value}) wildCard({$wildCard}) pos({$pos}) lastOffset({$lastOffset})", null, __CLASS__, __FUNCTION__, __LINE__);
if ($valCharsAllowReplace[$pos]) {
$value[$pos] = '%';
$valCharsAllowReplace[$pos] = false;
}
$lastOffset = $pos + 1;
}
}
}
DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue value({$value})", null, __CLASS__, __FUNCTION__, __LINE__);
if ($fieldFunction) {
$queryWhereBuilder->addComparisonFieldFunToValue($fieldFunction, $fieldName, $comparisonSign, $value);
} else {
$queryWhereBuilder->addComparisonFieldToValue($fieldName, $comparisonSign, $value);
}
}
break;
case 'sql_filter_comparisonFieldIsNull': {
$fieldName = V::get('fieldName', '', $tag['attributes']);
$queryWhereBuilder->sql_filter_comparisonFieldIsNull($fieldName);
}
break;
case 'sql_filter_openBlock': {
$blockType = V::get('type', '', $tag['attributes']);
DBG::_('DBG_DS_OGC', '>2', "sql_filter_openBlock block Type {$blockType} attrs", json_encode($tag), __CLASS__, __FUNCTION__, __LINE__);
$queryWhereBuilder->openBlock($blockType);
}
break;
case 'sql_filter_closeBlock': {
$blockType = V::get('type', '', $tag['attributes']);
$queryWhereBuilder->closeBlock($blockType);
}
break;
case 'not_implemented_tag': {
$tagName = V::get('name', '', $tag['attributes']);
DBG::_('DBG_DS_OGC', '>1', "Not Implemented tag '{$tagName}'", $queryWhereBuilder, __CLASS__, __FUNCTION__, __LINE__);
throw new Api_WfsException("Not Implemented tag '{$tagName}'", 501, null, 'NotImplementedOgcTag', 'request');
}
break;
default: {
DBG::_('DBG_DS_OGC', '>1', "TODO: tag {$tag['tag']}", $queryWhereBuilder, __CLASS__, __FUNCTION__, __LINE__);
throw new HttpException("TODO: tag {$tag['tag']}", 501);
}
}
}
$queryWhereBuilder->parseQueryWhere();
DBG::_('DBG_DS_OGC', '>1', "queryWhereBuilder", $queryWhereBuilder, __CLASS__, __FUNCTION__, __LINE__);
return $queryWhereBuilder;
}
public function _convertOgcFilterToCmdList($ogcFilterXmlString) {
$convertOgcFilterXslString = @file_get_contents(APP_PATH_SCHEMA . DS . 'wfs' . DS . 'convertOgcFilterToXmlTaskList.xsl');
if (false === $convertOgcFilterXslString) throw new HttpException("Cannot find file 'convertOgcFilter...'", 404);
if (empty($convertOgcFilterXslString)) throw new HttpException("Empty file 'convertOgcFilter...'", 404);
$requestXml = new DOMDocument();
$isFileCorrect = @$requestXml->loadXml($ogcFilterXmlString);
if (false === $isFileCorrect) throw new HttpException("Parse error for ogc filter", 400);
$convertOgcFilterXsl = new DOMDocument();
$isFileCorrect = @$convertOgcFilterXsl->loadXml($convertOgcFilterXslString);
if (false === $isFileCorrect) throw new HttpException("Parse error for file 'convertOgcFilter...'", 500);
$proc = new XSLTProcessor();
$isImported = $proc->importStylesheet($convertOgcFilterXsl);
if (false === $isImported) throw new HttpException("XSLT Parse error for import 'convertOgcFilter...'", 500);
return $proc->transformToXML($requestXml);
}
}