예제 #1
0
 public function testIterating()
 {
     $args = new ArgumentArray();
     $args->add(new Bind('name', 'John'));
     $args->add(new Bind('foo', 'FooBar'));
     foreach ($args as $n => $v) {
         ok(is_string($n));
         ok(in_array($v, array('John', 'FooBar')));
     }
 }
예제 #2
0
 public function toSql(BaseDriver $driver, ArgumentArray $args)
 {
     foreach ($this->args as $k => $a) {
         if ($a instanceof Bind) {
             $args->add($a);
         } else {
             $args->add(new Bind($k, $a));
         }
     }
     return $this->str;
 }
예제 #3
0
 /**
  * For variable placeholder like PDO, we need 1 or 0 for boolean type,
  *
  * For pgsql and mysql sql statement, 
  * we use TRUE or FALSE for boolean type.
  *
  * FOr sqlite sql statement:
  * we use 1 or 0 for boolean type.
  */
 public function deflate($value, ArgumentArray $args = NULL)
 {
     if ($this->alwaysBindValues) {
         if ($value instanceof Raw) {
             return $value->__toString();
         } elseif ($value instanceof Bind) {
             if ($args) {
                 $args->bind($value);
             }
             return $value->getMarker();
         } elseif ($value instanceof ParamMarker) {
             if ($args) {
                 $args->bind(new Bind($value->getMarker(), NULL));
             }
             return $value->getMarker();
         } else {
             $bind = $this->allocateBind($value);
             if ($args) {
                 $args->bind($bind);
             }
             return $bind->getMarker();
         }
     }
     if ($value === NULL) {
         return 'NULL';
     } elseif ($value === true) {
         return 'TRUE';
     } elseif ($value === false) {
         return 'FALSE';
     } elseif (is_integer($value)) {
         return intval($value);
     } elseif (is_float($value)) {
         return floatval($value);
     } elseif (is_string($value)) {
         return $this->quote($value);
     } elseif (is_callable($value)) {
         return call_user_func($value);
     } elseif (is_object($value)) {
         if ($value instanceof Bind) {
             if ($args) {
                 $args->bind($value);
             }
             if ($this->paramMarkerType === self::QMARK_PARAM_MARKER) {
                 return '?';
             } elseif ($this->paramMarkerType === self::NAMED_PARAM_MARKER) {
                 return $value->getMarker();
             } else {
                 return $value->getMarker();
             }
         } elseif ($value instanceof ParamMarker) {
             if ($args) {
                 $args->bind(new Bind($value->getMarker(), NULL));
             }
             if ($this->paramMarkerType === self::QMARK_PARAM_MARKER) {
                 return '?';
             } elseif ($this->paramMarkerType === self::NAMED_PARAM_MARKER) {
                 return $value->getMarker();
             } else {
                 return $value->getMarker();
             }
             return $value->getMarker();
         } elseif ($value instanceof Unknown) {
             return 'UNKNOWN';
         } else {
             if ($value instanceof DateTime) {
                 // convert DateTime object into string
                 // return $this->quote($value->format(DateTime::ISO8601));
                 return $this->quote($value->format(DateTime::ATOM));
                 // sqlite use ATOM format
             } elseif ($value instanceof ToSqlInterface) {
                 return $value->toSql($this, $args);
             } elseif ($value instanceof Raw) {
                 return $value->__toString();
             } else {
                 throw new LogicException('Unsupported class: ' . get_class($value));
             }
         }
     } elseif (is_array($value)) {
         // error_log("LazyRecord: deflating array type value", 0);
         return $value[0];
     } else {
         throw new LogicException('BaseDriver::deflate: Unsupported variable type');
     }
     return $value;
 }
예제 #4
0
 /**
  * Update current record
  *
  * @param array $args
  *
  * @return Result operation result (success or error)
  */
 public function update(array $args, $options = array())
 {
     $schema = $this->getSchema();
     // check if the record is loaded.
     $k = static::PRIMARY_KEY;
     if ($k && !isset($args[$k]) && !isset($this->_data[$k])) {
         throw new Exception('Record is not loaded, Can not update record.', array('args' => $args));
     }
     if (!$this->currentUserCan($this->getCurrentUser(), 'update', $args)) {
         return $this->reportError('Permission denied. Can not update record.', array('args' => $args));
     }
     // check if we get primary key value
     // here we allow users to specifty primary key value from arguments if the record is not loaded.
     $kVal = null;
     if (isset($args[$k]) && is_scalar($args[$k])) {
         $kVal = intval($args[$k]);
     } else {
         if (isset($this->_data[$k])) {
             $kVal = intval($this->_data[$k]);
         }
     }
     if (!$kVal) {
         throw new Exception("Primary key value is undefined.");
     }
     $origArgs = $args;
     $dsId = $this->writeSourceId;
     $conn = $this->getWriteConnection();
     $driver = $this->getWriteQueryDriver();
     $sql = null;
     $vars = null;
     $arguments = new ArgumentArray();
     $query = new UpdateQuery();
     $validationError = false;
     $validationResults = array();
     $updateArgs = array();
     $schema = $this->getSchema();
     try {
         $args = $this->beforeUpdate($args);
         // foreach mixin schema, run their beforeUpdate method,
         $args = array_intersect_key($args, array_flip($schema->columnNames));
         foreach ($schema->columns as $n => $c) {
             if (isset($args[$n]) && !$args[$n] && !$c->primary) {
                 if ($val = $c->getDefaultValue($this, $args)) {
                     $args[$n] = $val;
                 }
             }
             // column validate (value is set.)
             if (!array_key_exists($n, $args)) {
                 continue;
             }
             // if column is required (can not be empty) //   and default is defined.
             if ($c->required && array_key_exists($n, $args) && $args[$n] === null) {
                 return $this->reportError("Value of {$n} is required.");
             }
             // TODO: Do not render immutable field in ActionKit
             if ($c->immutable) {
                 // TODO: render as a validation results?
                 // unset($args[$n]);
                 // continue;
                 return $this->reportError("You can not update {$n} column, which is immutable.", array('args' => $args));
             }
             if ($args[$n] !== null && !is_array($args[$n]) && !$args[$n] instanceof Raw) {
                 $args[$n] = $c->typeCasting($args[$n]);
             }
             // The is_array function here is for checking raw sql value.
             if ($args[$n] !== null && !is_array($args[$n]) && !$args[$n] instanceof Raw) {
                 if (false === $c->checkTypeConstraint($args[$n])) {
                     return $this->reportError($args[$n] . " is not " . $c->isa . " type");
                 }
             }
             if ($c->filter || $c->canonicalizer) {
                 $args[$n] = $c->canonicalizeValue($args[$n], $this, $args);
             }
             if ($validationResult = $this->_validateColumn($c, $args[$n], $args)) {
                 $validationResults[$n] = $validationResult;
                 if (!$validationResult['valid']) {
                     $validationError = true;
                 }
             }
             // deflate the values into query
             /*
             if ($args[$n] instanceof Raw) {
                 $updateArgs[$n] = $args[$n];
             } else {
                 $updateArgs[$n] = $c->deflate($args[$n], $driver);
             }
             */
             // use parameter binding for binding
             $val = $args[$n];
             if (is_scalar($args[$n]) || is_null($args[$n])) {
                 $updateArgs[$n] = $bind = new Bind($n, $driver->cast($args[$n]));
                 $arguments->bind($bind);
             } else {
                 if ($args[$n] instanceof Raw) {
                     $updateArgs[$n] = $args[$n];
                 } else {
                     $updateArgs[$n] = $bind = new Bind($n, $c->deflate($args[$n], $driver));
                     $arguments->bind($bind);
                 }
             }
         }
         if ($validationError) {
             return $this->reportError("Validation failed.", array('validations' => $validationResults));
         }
         // TODO: optimized to built cache
         $query->set($updateArgs);
         $query->update($this->table);
         $query->where()->equal($k, $kVal);
         $sql = $query->toSql($driver, $arguments);
         $stm = $conn->prepare($sql);
         $stm->execute($arguments->toArray());
         // Merge updated data.
         //
         // if $args contains a raw SQL string,
         // we should reload data from database
         if (isset($options['reload'])) {
             $this->reload();
         } else {
             $this->_data = array_merge($this->_data, $args);
         }
         $this->afterUpdate($origArgs);
     } catch (PDOException $e) {
         throw new QueryException("Record update failed", $this, $e, array('driver' => get_class($driver), 'args' => $args, 'sql' => $sql, 'validations' => $validationResults));
     }
     return $this->reportSuccess('Updated', array('id' => $kVal, 'sql' => $sql, 'args' => $args, 'type' => Result::TYPE_UPDATE));
 }