Ver Fonte

fixed bug in ParseOgcFilter

Piotr Labudda há 9 anos atrás
pai
commit
785b48f025
1 ficheiros alterados com 114 adições e 37 exclusões
  1. 114 37
      SE/se-lib/ParseOgcFilter.php

+ 114 - 37
SE/se-lib/ParseOgcFilter.php

@@ -122,43 +122,7 @@ OGC_FILTER_XML_FILE;
 						$wildCard = V::get('wildCard', '', $tag['attributes']);
 						$wildCard = V::get('wildCard', '', $tag['attributes']);
 						$singleChar = V::get('singleChar', '', $tag['attributes']);
 						$singleChar = V::get('singleChar', '', $tag['attributes']);
 						$escapeChar = V::get('escapeChar', '', $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;
-							}
-						}
+						$value = $this->_convertIsLikeToSql($value, $wildCard, $singleChar, $escapeChar);
 					}
 					}
 					DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue value({$value})", null, __CLASS__, __FUNCTION__, __LINE__);
 					DBG::_('DBG_DS_OGC', '>3', "sql_filter_comparisonFieldToValue value({$value})", null, __CLASS__, __FUNCTION__, __LINE__);
 					if ($fieldFunction) {
 					if ($fieldFunction) {
@@ -202,6 +166,119 @@ OGC_FILTER_XML_FILE;
 		return $queryWhereBuilder;
 		return $queryWhereBuilder;
 	}
 	}
 
 
+	public function _convertIsLikeToSql($value, $wildCard, $singleChar, $escapeChar) {
+		if (0 === strlen($wildCard)) throw new Exception("Missing wildCard in PropertyIsLike");
+		if (0 === strlen($singleChar)) throw new Exception("Missing singleChar in PropertyIsLike");
+		if (0 === strlen($escapeChar)) throw new Exception("Missing escapeChar in PropertyIsLike");
+		// The <PropertyIsLike> element is intended to encode a character string comparison operator with pattern matching.
+		// The pattern is defined by a combination of regular characters, the wildCard character, the singleChar character,
+		// and the escapeChar character.
+		// - wildCard   (sql: '%') - matches zero or more characters
+		// - singleChar (sql: '_') - matches exactly one character
+		// - escapeChar (sql: '\') - is used to escape the meaning of the wildCard, singleChar and escapeChar itself
+
+		// wildCard="*" singleChar="#" escapeChar="!" => sql: % _ \
+		// '*ORMA!*' => '%ORMA\*'
+		// TODO: BUG: singleChar="%23"
+
+		// TODO: first replace every escapeChar
+		$valLength = strlen($value);
+
+		$parts = [ $value ];
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - init");
+		$parts = array_reduce($parts, function ($ret, $cur) use ($escapeChar, $wildCard) {
+			if (is_array($cur)) { $ret[] = $cur; return $ret; }// SKIP SQL_...
+			foreach (explode("{$escapeChar}{$wildCard}", $cur) as $idx => $p) {
+				if ($idx > 0) $ret[] = [ $wildCard ];
+				$ret[] = $p;
+			}
+			return $ret;
+		}, []);
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass split escape \$wildCard");
+		$parts = array_reduce($parts, function ($ret, $cur) use ($escapeChar, $singleChar) {
+			if (is_array($cur)) { $ret[] = $cur; return $ret; }// SKIP SQL_...
+			foreach (explode("{$escapeChar}{$singleChar}", $cur) as $idx => $p) {
+				if ($idx > 0) $ret[] = [ $singleChar ];
+				$ret[] = $p;
+			}
+			return $ret;
+		}, []);
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass split escape \$singleChar");
+		$parts = array_reduce($parts, function ($ret, $cur) use ($wildCard) {
+			if (is_array($cur)) { $ret[] = $cur; return $ret; }// SKIP SQL_...
+			foreach (explode("{$wildCard}", $cur) as $idx => $p) {
+				if ($idx > 0) $ret[] = [ '%' ];
+				$ret[] = $p;
+			}
+			return $ret;
+		}, []);
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass split escape \$wildCard");
+		$parts = array_reduce($parts, function ($ret, $cur) use ($singleChar) {
+			if (is_array($cur)) { $ret[] = $cur; return $ret; }// SKIP SQL_...
+			foreach (explode("{$singleChar}", $cur) as $idx => $p) {
+				if ($idx > 0) $ret[] = [ '_' ];
+				$ret[] = $p;
+			}
+			return $ret;
+		}, []);
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass split escape \$singleChar");
+		foreach ($parts as $idx => $cur) {
+			if (is_array($cur)) continue;
+			$parts[$idx] = str_replace('\\', '\\\\', $cur);
+		}
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass escape sql escape");
+		foreach ($parts as $idx => $cur) {
+			if (is_array($cur)) continue;
+			$parts[$idx] = str_replace('%', '\\%', $cur);
+		}
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass escape sql wildCard");
+		foreach ($parts as $idx => $cur) {
+			if (is_array($cur)) continue;
+			$parts[$idx] = str_replace('_', '\\_', $cur);
+		}
+		DBG::log($parts, 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - pass escape sql singleChar");
+		foreach ($parts as $idx => $cur) {
+			if (is_array($cur)) $parts[$idx] = $cur[0];
+		}
+		DBG::log(implode('', $parts), 'array', "_convertIsLikeToSql('{$value}', '{$wildCard}', '{$singleChar}', '{$escapeChar}') - END");
+		return implode('', $parts);
+
+		$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;
+			}
+		}
+		return $value;
+	}
+
 	public function _convertOgcFilterToCmdList($ogcFilterXmlString) {
 	public function _convertOgcFilterToCmdList($ogcFilterXmlString) {
 		$convertOgcFilterXslString = @file_get_contents(APP_PATH_SCHEMA . DS . 'wfs' . DS . 'convertOgcFilterToXmlTaskList.xsl');
 		$convertOgcFilterXslString = @file_get_contents(APP_PATH_SCHEMA . DS . 'wfs' . DS . 'convertOgcFilterToXmlTaskList.xsl');
 		if (false === $convertOgcFilterXslString) throw new HttpException("Cannot find file 'convertOgcFilter...'", 404);
 		if (false === $convertOgcFilterXslString) throw new HttpException("Cannot find file 'convertOgcFilter...'", 404);