isAllowedBlockType($blockType)) throw new Exception("unsupported block type"); $this->_log[] = "open_block_{$blockType}"; } public function closeBlock($blockType) { if (!$this->isAllowedBlockType($blockType)) throw new Exception("unsupported block type"); $this->_log[] = "close_block_{$blockType}"; } public function addComparisonFieldToValue($fieldName, $comparisonSign, $value) { $sqlCompSign = ""; switch ($comparisonSign) { case '=': $sqlCompSign = '='; break; default: throw new Exception("Unsupported comparison sign"); } $this->_log[] = array('comparisonFieldToValue', $fieldName, $sqlCompSign, $value); } public function getQueryWhere($tablePrefix = '') { $sqlWhereRaw = $this->parseQueryWhere(); $sqlTablePrefix = ($tablePrefix)? "`{$tablePrefix}`." : ''; return str_replace('{tablePrefix}', $sqlTablePrefix, $sqlWhereRaw); } public function parseQueryWhere() { $this->_raw = ""; $this->_usedFields = array(); $sqlBlocksStack = array(); $sqlValuesStack = array(); $arr = array(); array_push($sqlValuesStack, $arr);// empty array to start foreach ($this->_log as $log) { switch ($log) { case 'open_block_and': case 'open_block_or': { $blockType = substr($log, 11); array_push($sqlBlocksStack, $blockType); $arr = array(); array_push($sqlValuesStack, $arr); //echo "L.".__LINE__.":sqlBlocksStack:" . json_encode($sqlBlocksStack) . "\n"; //echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n\n"; } break; case 'close_block_and': case 'close_block_or': { $blockType = substr($log, 12); if (empty($sqlBlocksStack)) throw new Exception("parse sql query failed - blocks stack is empty"); $stackBlockType = array_pop($sqlBlocksStack); if ($blockType != $stackBlockType) throw new Exception("parse sql query failed - expected stop '{$blockType}', given '{$stackBlockType}'"); // parse to string and add to parent value stack $stackValue = array_pop($sqlValuesStack); if (!is_array($stackValue)) throw new Exception("parse sql query failed - stack value is not array"); if (empty($stackValue)) throw new Exception("parse sql query failed - stack value is empty"); $sqlFromStack = " ( " . implode(" {$blockType} ", $stackValue) . " ) "; $parentStackValue = array_pop($sqlValuesStack); if (!is_array($parentStackValue)) throw new Exception("parse sql query failed - parent stack value is not array"); array_push($parentStackValue, $sqlFromStack); array_push($sqlValuesStack, $parentStackValue); } break; default: { if (is_array($log) && 4 == count($log) && 'comparisonFieldToValue' == $log[0]) { $sqlFieldName = $log[1]; $this->_usedFields[$sqlFieldName] = true; $sqlFromStack = "{tablePrefix}`{$sqlFieldName}` {$log[2]} '{$log[3]}'"; $stackValue = array_pop($sqlValuesStack); if (!is_array($stackValue)) throw new Exception("parse sql query failed - stack value is not array"); array_push($stackValue, $sqlFromStack); array_push($sqlValuesStack, $stackValue); //echo "L.".__LINE__.":sqlBlocksStack:" . json_encode($sqlBlocksStack) . "\n"; //echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n\n"; } else { throw new Exception("parse sql query failed - unknown '" . json_encode($log) . "'"); } } } } // TODO: parse log //echo "L.".__LINE__.":sqlBlocksStack:" . json_encode($sqlBlocksStack) . "\n"; //echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n--------\n"; if (!empty($sqlBlocksStack)) throw new Exception("parse sql query failed - blocks stack is not empty"); if (1 !== count($sqlValuesStack)) throw new Exception("parse sql query failed - values stack is empty"); $this->_raw = implode("\n", $sqlValuesStack[0]); return $this->_raw; } public function getUsedFields() { return array_keys($this->_usedFields); } public function isAllowedBlockType($blockType) { if ('and' == $blockType || 'or' == $blockType) { return true; } else if ('not' == $blockType) { return false;// TODO: allow not operator: expect only one children, if more -> use only last } return false; } public function splitQueryToWords($q) { $searchWords = explode(' ', $q); $sqlSearchWords = array(); if (!empty($searchWords)) { foreach ($searchWords as $word) { if (!empty($word)) { $sqlSearchWords[] = $word; } } } return $sqlSearchWords; } }