Example #1
0
 /**
  * 
  * @param string $psMsg
  */
 public static function i18n($psMsg)
 {
     return $psMsg;
     $laTranslator = Config::getAppOptions('translator');
     $loI18n = new self();
     $loI18n->setLocale($laTranslator['locale']);
     $loI18n->addTranslationFilePattern($laTranslator['type'], $laTranslator['base_dir'], $laTranslator['pattern']);
     return $loI18n->translate($psMsg);
 }
Example #2
0
 /**
  * Apply modifier to single value.
  * @param  mixed
  * @param  string
  * @return string
  */
 public function formatValue($value, $modifier)
 {
     // array processing (with or without modifier)
     if ($value instanceof Traversable) {
         $value = iterator_to_array($value);
     }
     if (is_array($value)) {
         $vx = $kx = array();
         switch ($modifier) {
             case 'and':
             case 'or':
                 // key=val AND key IS NULL AND ...
                 if (empty($value)) {
                     return '1=1';
                 }
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $pair = explode('%', $k, 2);
                         // split into identifier & modifier
                         $k = $this->identifiers->{$pair[0]} . ' ';
                         if (!isset($pair[1])) {
                             $v = $this->formatValue($v, FALSE);
                             $vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
                         } elseif ($pair[1] === 'ex') {
                             // TODO: this will be removed
                             $vx[] = $k . $this->formatValue($v, 'ex');
                         } else {
                             $v = $this->formatValue($v, $pair[1]);
                             $vx[] = $k . ($pair[1] === 'l' || $pair[1] === 'in' ? 'IN ' : ($v === 'NULL' ? 'IS ' : '= ')) . $v;
                         }
                     } else {
                         $vx[] = $this->formatValue($v, 'ex');
                     }
                 }
                 return '(' . implode(') ' . strtoupper($modifier) . ' (', $vx) . ')';
             case 'n':
                 // key, key, ... identifier names
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $vx[] = $this->identifiers->{$k} . (empty($v) ? '' : ' AS ' . $v);
                     } else {
                         $pair = explode('%', $v, 2);
                         // split into identifier & modifier
                         $vx[] = $this->identifiers->{$pair[0]};
                     }
                 }
                 return implode(', ', $vx);
             case 'a':
                 // key=val, key=val, ...
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $vx[] = $this->identifiers->{$pair[0]} . '=' . $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return implode(', ', $vx);
             case 'in':
                 // replaces scalar %in modifier!
             // replaces scalar %in modifier!
             case 'l':
                 // (val, val, ...)
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return '(' . ($vx || $modifier === 'l' ? implode(', ', $vx) : 'NULL') . ')';
             case 'v':
                 // (key, key, ...) VALUES (val, val, ...)
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $kx[] = $this->identifiers->{$pair[0]};
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
             case 'm':
                 // (key, key, ...) VALUES (val, val, ...), (val, val, ...), ...
                 foreach ($value as $k => $v) {
                     if (is_array($v)) {
                         if (isset($proto)) {
                             if ($proto !== array_keys($v)) {
                                 $this->hasError = TRUE;
                                 return '**Multi-insert array "' . $k . '" is different.**';
                             }
                         } else {
                             $proto = array_keys($v);
                         }
                     } else {
                         $this->hasError = TRUE;
                         return '**Unexpected type ' . gettype($v) . '**';
                     }
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $kx[] = $this->identifiers->{$pair[0]};
                     foreach ($v as $k2 => $v2) {
                         $vx[$k2][] = $this->formatValue($v2, isset($pair[1]) ? $pair[1] : (is_array($v2) ? 'ex' : FALSE));
                     }
                 }
                 foreach ($vx as $k => $v) {
                     $vx[$k] = '(' . implode(', ', $v) . ')';
                 }
                 return '(' . implode(', ', $kx) . ') VALUES ' . implode(', ', $vx);
             case 'by':
                 // key ASC, key DESC
                 foreach ($value as $k => $v) {
                     if (is_array($v)) {
                         $vx[] = $this->formatValue($v, 'ex');
                     } elseif (is_string($k)) {
                         $v = is_string($v) && strncasecmp($v, 'd', 1) || $v > 0 ? 'ASC' : 'DESC';
                         $vx[] = $this->identifiers->{$k} . ' ' . $v;
                     } else {
                         $vx[] = $this->identifiers->{$v};
                     }
                 }
                 return implode(', ', $vx);
             case 'ex':
             case 'sql':
                 $translator = new self($this->driver);
                 return $translator->translate($value);
             default:
                 // value, value, value - all with the same modifier
                 foreach ($value as $v) {
                     $vx[] = $this->formatValue($v, $modifier);
                 }
                 return implode(', ', $vx);
         }
     }
     // with modifier procession
     if ($modifier) {
         if ($value !== NULL && !is_scalar($value) && !$value instanceof DateTime) {
             // array is already processed
             $this->hasError = TRUE;
             return '**Unexpected type ' . gettype($value) . '**';
         }
         switch ($modifier) {
             case 's':
                 // string
             // string
             case 'bin':
                 // binary
             // binary
             case 'b':
                 // boolean
                 return $value === NULL ? 'NULL' : $this->driver->escape($value, $modifier);
             case 'sN':
                 // string or NULL
             // string or NULL
             case 'sn':
                 return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::TEXT);
                 // notice two equal signs
             // notice two equal signs
             case 'iN':
                 // signed int or NULL
             // signed int or NULL
             case 'in':
                 // deprecated
                 if ($value == '') {
                     $value = NULL;
                 }
                 // intentionally break omitted
             // intentionally break omitted
             case 'i':
                 // signed int
             // signed int
             case 'u':
                 // unsigned int, ignored
                 // support for long numbers - keep them unchanged
                 if (is_string($value) && preg_match('#[+-]?\\d++(e\\d+)?$#A', $value)) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
                 }
             case 'f':
                 // float
                 // support for extreme numbers - keep them unchanged
                 if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
                     return $value;
                     // something like -9E-005 is accepted by SQL, HEX values are not
                 } else {
                     return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value + 0, 5, '.', ''), '0'), '.');
                 }
             case 'd':
                 // date
             // date
             case 't':
                 // datetime
                 if ($value === NULL) {
                     return 'NULL';
                 } else {
                     if (is_numeric($value)) {
                         $value = (int) $value;
                         // timestamp
                     } elseif (is_string($value)) {
                         $value = new DateTime($value);
                     }
                     return $this->driver->escape($value, $modifier);
                 }
             case 'by':
             case 'n':
                 // identifier name
                 return $this->identifiers->{$value};
             case 'ex':
             case 'sql':
                 // preserve as dibi-SQL  (TODO: leave only %ex)
                 $value = (string) $value;
                 // speed-up - is regexp required?
                 $toSkip = strcspn($value, '`[\'":');
                 if (strlen($value) !== $toSkip) {
                     $value = substr($value, 0, $toSkip) . preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\\[(.+?)\\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\\S*?:)([a-zA-Z0-9._]?))/s', array($this, 'cb'), substr($value, $toSkip));
                     if (preg_last_error()) {
                         throw new DibiPcreException();
                     }
                 }
                 return $value;
             case 'SQL':
                 // preserve as real SQL (TODO: rename to %sql)
                 return (string) $value;
             case 'like~':
                 // LIKE string%
                 return $this->driver->escapeLike($value, 1);
             case '~like':
                 // LIKE %string
                 return $this->driver->escapeLike($value, -1);
             case '~like~':
                 // LIKE %string%
                 return $this->driver->escapeLike($value, 0);
             case 'and':
             case 'or':
             case 'a':
             case 'l':
             case 'v':
                 $this->hasError = TRUE;
                 return '**Unexpected type ' . gettype($value) . '**';
             default:
                 $this->hasError = TRUE;
                 return "**Unknown or invalid modifier %{$modifier}**";
         }
     }
     // without modifier procession
     if (is_string($value)) {
         return $this->driver->escape($value, dibi::TEXT);
     } elseif (is_int($value)) {
         return (string) $value;
     } elseif (is_float($value)) {
         return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
     } elseif (is_bool($value)) {
         return $this->driver->escape($value, dibi::BOOL);
     } elseif ($value === NULL) {
         return 'NULL';
     } elseif ($value instanceof DateTime) {
         return $this->driver->escape($value, dibi::DATETIME);
     } else {
         $this->hasError = TRUE;
         return '**Unexpected ' . gettype($value) . '**';
     }
 }
Example #3
0
 public function formatValue($value, $modifier)
 {
     if ($value instanceof ArrayObject) {
         $value = (array) $value;
     }
     if (is_array($value)) {
         $vx = $kx = array();
         switch ($modifier) {
             case 'and':
             case 'or':
                 if (empty($value)) {
                     return $this->driver->escape(TRUE, 'b');
                 }
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $pair = explode('%', $k, 2);
                         $k = $this->delimite($pair[0]) . ' ';
                         if (!isset($pair[1])) {
                             $v = $this->formatValue($v, FALSE);
                             $vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
                         } elseif ($pair[1] === 'ex') {
                             $vx[] = $k . $this->formatValue($v, 'ex');
                         } else {
                             $v = $this->formatValue($v, $pair[1]);
                             $vx[] = $k . ($pair[1] === 'l' ? 'IN ' : ($v === 'NULL' ? 'IS ' : '= ')) . $v;
                         }
                     } else {
                         $vx[] = $this->formatValue($v, 'ex');
                     }
                 }
                 return implode(' ' . strtoupper($modifier) . ' ', $vx);
             case 'n':
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $vx[] = $this->delimite($k) . (empty($v) ? '' : ' AS ' . $v);
                     } else {
                         $vx[] = $this->delimite($v);
                     }
                 }
                 return implode(', ', $vx);
             case 'a':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $vx[] = $this->delimite($pair[0]) . '=' . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return implode(', ', $vx);
             case 'l':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return '(' . implode(', ', $vx) . ')';
             case 'v':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $kx[] = $this->delimite($pair[0]);
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
             case 'by':
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $v = is_string($v) && strncasecmp($v, 'd', 1) || $v > 0 ? 'ASC' : 'DESC';
                         $vx[] = $this->delimite($k) . ' ' . $v;
                     } else {
                         $vx[] = $this->delimite($v);
                     }
                 }
                 return implode(', ', $vx);
             case 'ex':
             case 'sql':
                 $translator = new self($this->driver);
                 return $translator->translate($value);
             default:
                 foreach ($value as $v) {
                     $vx[] = $this->formatValue($v, $modifier);
                 }
                 return implode(', ', $vx);
         }
     }
     if ($modifier) {
         if ($value instanceof IDibiVariable) {
             return $value->toSql($this, $modifier);
         } elseif ($value instanceof DateTime) {
             $value = $value->format('U');
         } elseif ($value !== NULL && !is_scalar($value)) {
             $this->hasError = TRUE;
             return '**Unexpected type ' . gettype($value) . '**';
         }
         switch ($modifier) {
             case 's':
             case 'bin':
             case 'b':
                 return $value === NULL ? 'NULL' : $this->driver->escape($value, $modifier);
             case 'sn':
                 return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::TEXT);
             case 'i':
             case 'u':
                 if (is_string($value) && preg_match('#[+-]?\\d+(e\\d+)?$#A', $value)) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
                 }
             case 'f':
                 if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
                 }
             case 'd':
             case 't':
                 if ($value === NULL) {
                     return 'NULL';
                 } else {
                     return $this->driver->escape(is_numeric($value) ? (int) $value : strtotime($value), $modifier);
                 }
             case 'by':
             case 'n':
                 return $this->delimite($value);
             case 'ex':
             case 'sql':
                 $value = (string) $value;
                 $toSkip = strcspn($value, '`[\'":');
                 if (strlen($value) === $toSkip) {
                     return $value;
                 } else {
                     return substr($value, 0, $toSkip) . preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\\[(.+?)\\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\\S*?:)([a-zA-Z0-9._]?))/s', array($this, 'cb'), substr($value, $toSkip));
                 }
             case 'SQL':
                 return (string) $value;
             case 'and':
             case 'or':
             case 'a':
             case 'l':
             case 'v':
                 $this->hasError = TRUE;
                 return '**Unexpected type ' . gettype($value) . '**';
             default:
                 $this->hasError = TRUE;
                 return "**Unknown or invalid modifier %{$modifier}**";
         }
     }
     if (is_string($value)) {
         return $this->driver->escape($value, dibi::TEXT);
     }
     if (is_int($value) || is_float($value)) {
         return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
     }
     if (is_bool($value)) {
         return $this->driver->escape($value, dibi::BOOL);
     }
     if ($value === NULL) {
         return 'NULL';
     }
     if ($value instanceof IDibiVariable) {
         return $value->toSql($this, NULL);
     }
     $this->hasError = TRUE;
     return '**Unexpected ' . gettype($value) . '**';
 }
Example #4
0
 public function formatValue($value, $modifier)
 {
     if ($value instanceof Traversable) {
         $value = iterator_to_array($value);
     }
     if (is_array($value)) {
         $vx = $kx = array();
         switch ($modifier) {
             case 'and':
             case 'or':
                 if (empty($value)) {
                     return '1=1';
                 }
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $pair = explode('%', $k, 2);
                         $k = $this->identifiers->{$pair[0]} . ' ';
                         if (!isset($pair[1])) {
                             $v = $this->formatValue($v, FALSE);
                             $vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
                         } elseif ($pair[1] === 'ex') {
                             $vx[] = $k . $this->formatValue($v, 'ex');
                         } else {
                             $v = $this->formatValue($v, $pair[1]);
                             $vx[] = $k . ($pair[1] === 'l' || $pair[1] === 'in' ? 'IN ' : ($v === 'NULL' ? 'IS ' : '= ')) . $v;
                         }
                     } else {
                         $vx[] = $this->formatValue($v, 'ex');
                     }
                 }
                 return '(' . implode(') ' . strtoupper($modifier) . ' (', $vx) . ')';
             case 'n':
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $vx[] = $this->identifiers->{$k} . (empty($v) ? '' : ' AS ' . $v);
                     } else {
                         $pair = explode('%', $v, 2);
                         $vx[] = $this->identifiers->{$pair[0]};
                     }
                 }
                 return implode(', ', $vx);
             case 'a':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $vx[] = $this->identifiers->{$pair[0]} . '=' . $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return implode(', ', $vx);
             case 'in':
             case 'l':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return '(' . ($vx || $modifier === 'l' ? implode(', ', $vx) : 'NULL') . ')';
             case 'v':
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     $kx[] = $this->identifiers->{$pair[0]};
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
                 }
                 return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
             case 'm':
                 foreach ($value as $k => $v) {
                     if (is_array($v)) {
                         if (isset($proto)) {
                             if ($proto !== array_keys($v)) {
                                 $this->hasError = TRUE;
                                 return '**Multi-insert array "' . $k . '" is different.**';
                             }
                         } else {
                             $proto = array_keys($v);
                         }
                     } else {
                         $this->hasError = TRUE;
                         return '**Unexpected type ' . gettype($v) . '**';
                     }
                     $pair = explode('%', $k, 2);
                     $kx[] = $this->identifiers->{$pair[0]};
                     foreach ($v as $k2 => $v2) {
                         $vx[$k2][] = $this->formatValue($v2, isset($pair[1]) ? $pair[1] : (is_array($v2) ? 'ex' : FALSE));
                     }
                 }
                 foreach ($vx as $k => $v) {
                     $vx[$k] = '(' . implode(', ', $v) . ')';
                 }
                 return '(' . implode(', ', $kx) . ') VALUES ' . implode(', ', $vx);
             case 'by':
                 foreach ($value as $k => $v) {
                     if (is_array($v)) {
                         $vx[] = $this->formatValue($v, 'ex');
                     } elseif (is_string($k)) {
                         $v = is_string($v) && strncasecmp($v, 'd', 1) || $v > 0 ? 'ASC' : 'DESC';
                         $vx[] = $this->identifiers->{$k} . ' ' . $v;
                     } else {
                         $vx[] = $this->identifiers->{$v};
                     }
                 }
                 return implode(', ', $vx);
             case 'ex':
             case 'sql':
                 $translator = new self($this->driver);
                 return $translator->translate($value);
             default:
                 foreach ($value as $v) {
                     $vx[] = $this->formatValue($v, $modifier);
                 }
                 return implode(', ', $vx);
         }
     }
     if ($modifier) {
         if ($value !== NULL && !is_scalar($value) && !$value instanceof DateTime) {
             $this->hasError = TRUE;
             return '**Unexpected type ' . gettype($value) . '**';
         }
         switch ($modifier) {
             case 's':
             case 'bin':
             case 'b':
                 return $value === NULL ? 'NULL' : $this->driver->escape($value, $modifier);
             case 'sN':
             case 'sn':
                 return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::TEXT);
             case 'iN':
             case 'in':
                 if ($value == '') {
                     $value = NULL;
                 }
             case 'i':
             case 'u':
                 if (is_string($value) && preg_match('#[+-]?\\d++(e\\d+)?$#A', $value)) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
                 }
             case 'f':
                 if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value + 0, 5, '.', ''), '0'), '.');
                 }
             case 'd':
             case 't':
                 if ($value === NULL) {
                     return 'NULL';
                 } else {
                     if (is_numeric($value)) {
                         $value = (int) $value;
                     } elseif (is_string($value)) {
                         $value = new DateTime($value);
                     }
                     return $this->driver->escape($value, $modifier);
                 }
             case 'by':
             case 'n':
                 return $this->identifiers->{$value};
             case 'ex':
             case 'sql':
                 $value = (string) $value;
                 $toSkip = strcspn($value, '`[\'":');
                 if (strlen($value) !== $toSkip) {
                     $value = substr($value, 0, $toSkip) . preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\\[(.+?)\\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\\S*?:)([a-zA-Z0-9._]?))/s', array($this, 'cb'), substr($value, $toSkip));
                     if (preg_last_error()) {
                         throw new PcreException();
                     }
                 }
                 return $value;
             case 'SQL':
                 return (string) $value;
             case 'like~':
                 return $this->driver->escapeLike($value, 1);
             case '~like':
                 return $this->driver->escapeLike($value, -1);
             case '~like~':
                 return $this->driver->escapeLike($value, 0);
             case 'and':
             case 'or':
             case 'a':
             case 'l':
             case 'v':
                 $this->hasError = TRUE;
                 return '**Unexpected type ' . gettype($value) . '**';
             default:
                 $this->hasError = TRUE;
                 return "**Unknown or invalid modifier %{$modifier}**";
         }
     }
     if (is_string($value)) {
         return $this->driver->escape($value, dibi::TEXT);
     } elseif (is_int($value)) {
         return (string) $value;
     } elseif (is_float($value)) {
         return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
     } elseif (is_bool($value)) {
         return $this->driver->escape($value, dibi::BOOL);
     } elseif ($value === NULL) {
         return 'NULL';
     } elseif ($value instanceof DateTime) {
         return $this->driver->escape($value, dibi::DATETIME);
     } else {
         $this->hasError = TRUE;
         return '**Unexpected ' . gettype($value) . '**';
     }
 }
 /**
  * Apply modifier to single value.
  * @param  mixed
  * @param  string
  * @return string
  */
 public function formatValue($value, $modifier)
 {
     // array processing (with or without modifier)
     if ($value instanceof ArrayObject) {
         $value = (array) $value;
     }
     if (is_array($value)) {
         $vx = $kx = array();
         switch ($modifier) {
             case 'and':
             case 'or':
                 // key=val AND key IS NULL AND ...
                 if (empty($value)) {
                     return '1=1';
                 }
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $pair = explode('%', $k, 2);
                         // split into identifier & modifier
                         $k = $this->delimite($pair[0]) . ' ';
                         if (!isset($pair[1])) {
                             $v = $this->formatValue($v, FALSE);
                             $vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
                         } elseif ($pair[1] === 'ex') {
                             // TODO: this will be removed
                             $vx[] = $k . $this->formatValue($v, 'ex');
                         } else {
                             $v = $this->formatValue($v, $pair[1]);
                             $vx[] = $k . ($pair[1] === 'l' ? 'IN ' : ($v === 'NULL' ? 'IS ' : '= ')) . $v;
                         }
                     } else {
                         $vx[] = $this->formatValue($v, 'ex');
                     }
                 }
                 return implode(' ' . strtoupper($modifier) . ' ', $vx);
             case 'n':
                 // identifier names
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $vx[] = $this->delimite($k) . (empty($v) ? '' : ' AS ' . $v);
                     } else {
                         $vx[] = $this->delimite($v);
                     }
                 }
                 return implode(', ', $vx);
             case 'a':
                 // key=val, key=val, ...
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $vx[] = $this->delimite($pair[0]) . '=' . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return implode(', ', $vx);
             case 'l':
                 // (val, val, ...)
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return '(' . ($vx ? implode(', ', $vx) : 'NULL') . ')';
             case 'v':
                 // (key, key, ...) VALUES (val, val, ...)
                 foreach ($value as $k => $v) {
                     $pair = explode('%', $k, 2);
                     // split into identifier & modifier
                     $kx[] = $this->delimite($pair[0]);
                     $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
                 }
                 return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
             case 'by':
                 // key ASC, key DESC
                 foreach ($value as $k => $v) {
                     if (is_string($k)) {
                         $v = is_string($v) && strncasecmp($v, 'd', 1) || $v > 0 ? 'ASC' : 'DESC';
                         $vx[] = $this->delimite($k) . ' ' . $v;
                     } else {
                         $vx[] = $this->delimite($v);
                     }
                 }
                 return implode(', ', $vx);
             case 'ex':
             case 'sql':
                 $translator = new self($this->driver);
                 return $translator->translate($value);
             default:
                 // value, value, value - all with the same modifier
                 foreach ($value as $v) {
                     $vx[] = $this->formatValue($v, $modifier);
                 }
                 return $vx ? implode(', ', $vx) : 'NULL';
         }
     }
     // with modifier procession
     if ($modifier) {
         if ($value instanceof IDibiVariable) {
             return $value->toSql($this, $modifier);
         } elseif ($value instanceof DateTime) {
             $value = $value->format('U');
         } elseif ($value !== NULL && !is_scalar($value)) {
             // array is already processed
             $this->hasError = TRUE;
             return '**Unexpected type ' . gettype($value) . '**';
         }
         switch ($modifier) {
             case 's':
                 // string
             // string
             case 'bin':
                 // binary
             // binary
             case 'b':
                 // boolean
                 return $value === NULL ? 'NULL' : $this->driver->escape($value, $modifier);
             case 'sn':
                 // string or NULL
                 return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::TEXT);
                 // notice two equal signs
             // notice two equal signs
             case 'i':
                 // signed int
             // signed int
             case 'u':
                 // unsigned int, ignored
                 // support for long numbers - keep them unchanged
                 if (is_string($value) && preg_match('#[+-]?\\d+(e\\d+)?$#A', $value)) {
                     return $value;
                 } else {
                     return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
                 }
             case 'f':
                 // float
                 // support for extreme numbers - keep them unchanged
                 if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
                     return $value;
                     // something like -9E-005 is accepted by SQL, HEX values are not
                 } else {
                     return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
                 }
             case 'd':
                 // date
             // date
             case 't':
                 // datetime
                 if ($value === NULL) {
                     return 'NULL';
                 } else {
                     return $this->driver->escape(is_numeric($value) ? (int) $value : strtotime($value), $modifier);
                 }
             case 'by':
             case 'n':
                 // identifier name
                 return $this->delimite($value);
             case 'ex':
             case 'sql':
                 // preserve as dibi-SQL  (TODO: leave only %ex)
                 $value = (string) $value;
                 // speed-up - is regexp required?
                 $toSkip = strcspn($value, '`[\'":');
                 if (strlen($value) === $toSkip) {
                     // needn't be translated
                     return $value;
                 } else {
                     return substr($value, 0, $toSkip) . preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\\[(.+?)\\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\\S*?:)([a-zA-Z0-9._]?))/s', array($this, 'cb'), substr($value, $toSkip));
                 }
             case 'SQL':
                 // preserve as real SQL (TODO: rename to %sql)
                 return (string) $value;
             case 'and':
             case 'or':
             case 'a':
             case 'l':
             case 'v':
                 $this->hasError = TRUE;
                 return '**Unexpected type ' . gettype($value) . '**';
             default:
                 $this->hasError = TRUE;
                 return "**Unknown or invalid modifier %{$modifier}**";
         }
     }
     // without modifier procession
     if (is_string($value)) {
         return $this->driver->escape($value, dibi::TEXT);
     }
     if (is_int($value) || is_float($value)) {
         return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
     }
     if (is_bool($value)) {
         return $this->driver->escape($value, dibi::BOOL);
     }
     if ($value === NULL) {
         return 'NULL';
     }
     if ($value instanceof IDibiVariable) {
         return $value->toSql($this, NULL);
     }
     $this->hasError = TRUE;
     return '**Unexpected ' . gettype($value) . '**';
 }