/** * @param string $type * @param mixed $value * @return string */ public function processModifier($type, $value) { switch (gettype($value)) { case 'string': switch ($type) { case 'any': case 's': case '?s': return $this->driver->convertStringToSql($value); case 'i': case '?i': if (!preg_match('#^-?[1-9][0-9]*+\\z#', $value)) { break; } return (string) $value; case '_like': return $this->driver->convertLikeToSql($value, -1); case 'like_': return $this->driver->convertLikeToSql($value, 1); case '_like_': return $this->driver->convertLikeToSql($value, 0); case 'column': if ($value === '*') { return '*'; } // intential pass-through // intential pass-through case 'table': return $this->identifiers->{$value}; case 'blob': return $this->driver->convertBlobToSql($value); case 'raw': return $value; } break; case 'integer': switch ($type) { case 'any': case 'i': case '?i': return (string) $value; } break; case 'double': if (is_finite($value)) { // database can not handle INF and NAN switch ($type) { case 'any': case 'f': case '?f': return ($tmp = json_encode($value)) . (strpos($tmp, '.') === FALSE ? '.0' : ''); } } break; case 'boolean': switch ($type) { case 'any': case 'b': case '?b': return $this->driver->convertBoolToSql($value); } break; case 'NULL': switch ($type) { case 'any': case '?s': case '?i': case '?f': case '?b': case '?dt': case '?dts': case '?di': case '?blob': return 'NULL'; } break; case 'object': if ($value instanceof \DateTimeImmutable || $value instanceof \DateTime) { switch ($type) { case 'any': case 'dt': case '?dt': return $this->driver->convertDateTimeToSql($value); case 'dts': case '?dts': return $this->driver->convertDateTimeSimpleToSql($value); } } elseif ($value instanceof \DateInterval) { switch ($type) { case 'any': case 'di': case '?di': return $this->driver->convertDateIntervalToSql($value); } } elseif (method_exists($value, '__toString')) { switch ($type) { case 'any': case 's': case '?s': return $this->driver->convertStringToSql((string) $value); case '_like': return $this->driver->convertLikeToSql($value, -1); case 'like_': return $this->driver->convertLikeToSql($value, 1); case '_like_': return $this->driver->convertLikeToSql($value, 0); } } break; case 'array': switch ($type) { // micro-optimizations case 'any': return $this->processArray("any[]", $value); case 'i[]': foreach ($value as $v) { if (!is_int($v)) { break 2; } // fallback to processArray } return '(' . implode(', ', $value) . ')'; case 's[]': foreach ($value as &$subValue) { if (!is_string($subValue)) { break 2; } // fallback to processArray $subValue = $this->driver->convertStringToSql($subValue); } return '(' . implode(', ', $value) . ')'; // normal // normal case 'column[]': case 'table[]': $subType = substr($type, 0, -2); foreach ($value as &$subValue) { $subValue = $this->processModifier($subType, $subValue); } return implode(', ', $value); case 'and': case 'or': return $this->processWhere($type, $value); case 'values': return $this->processValues($type, $value); case 'values[]': return $this->processMultiValues($type, $value); case 'set': return $this->processSet($type, $value); case 'ex': return $this->process($value); } if (substr($type, -1) === ']') { $baseType = trim($type, '[]?'); if (isset($this->modifiers[$baseType]) && $this->modifiers[$baseType][1]) { return $this->processArray($type, $value); } } } $baseType = trim($type, '[]?'); $typeNullable = $type[0] === '?'; $typeArray = substr($type, -2) === '[]'; if (!isset($this->modifiers[$baseType])) { throw new InvalidArgumentException("Unknown modifier %{$type}."); } elseif ($typeNullable && !$this->modifiers[$baseType][0] || $typeArray && !$this->modifiers[$baseType][1]) { throw new InvalidArgumentException("Modifier %{$baseType} does not have %{$type} variant."); } elseif ($typeArray) { $this->throwInvalidValueTypeException($type, $value, 'array'); } elseif ($value === NULL && !$typeNullable && $this->modifiers[$baseType][0]) { $this->throwWrongModifierException($type, $value, "?{$type}"); } elseif (is_array($value) && !$typeArray && $this->modifiers[$baseType][1]) { $this->throwWrongModifierException($type, $value, "{$type}[]"); } else { $this->throwInvalidValueTypeException($type, $value, $this->modifiers[$baseType][2]); } }