コード例 #1
0
ファイル: fActiveRecord.php プロジェクト: mrjwc/printmaster
 /**
  * Creates the fDatabase::translatedQuery() update statement params
  *
  * @return array  The parameters for an fDatabase::translatedQuery() SQL update statement
  */
 protected function constructUpdateParams()
 {
     $class = get_class($this);
     $schema = fORMSchema::retrieve($class);
     $table = fORM::tablize($class);
     $column_info = $schema->getColumnInfo($table);
     $assignments = array();
     $params = array($table);
     foreach ($column_info as $column => $info) {
         if ($info['auto_increment'] && !fActiveRecord::changed($this->values, $this->old_values, $column) && count($column_info) > 1) {
             continue;
         }
         $assignments[] = '%r = ' . $info['placeholder'];
         $value = fORM::scalarize($class, $column, $this->values[$column]);
         if ($value === NULL && $info['not_null'] && $info['default'] !== NULL) {
             $value = $info['default'];
         }
         $params[] = $column;
         $params[] = $value;
     }
     $sql = 'UPDATE %r SET ' . join(', ', $assignments) . ' WHERE ';
     array_unshift($params, $sql);
     return fORMDatabase::addPrimaryKeyWhereParams($schema, $params, $table, $table, $this->values, $this->old_values);
 }
コード例 #2
0
ファイル: fActiveRecord.php プロジェクト: jsuarez/MyDesign
 /**
  * Stores a record in the database, whether existing or new
  * 
  * This method will start database and filesystem transactions if they have
  * not already been started.
  * 
  * @throws fValidationException  When ::validate() throws an exception
  * 
  * @return fActiveRecord  The record object, to allow for method chaining
  */
 public function store()
 {
     $class = get_class($this);
     if (fORM::getActiveRecordMethod($class, 'store')) {
         return $this->__call('store', array());
     }
     fORM::callHookCallbacks($this, 'pre::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
     try {
         $table = fORM::tablize($class);
         $column_info = fORMSchema::retrieve()->getColumnInfo($table);
         // New auto-incrementing records require lots of special stuff, so we'll detect them here
         $new_autoincrementing_record = FALSE;
         if (!$this->exists()) {
             $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary');
             if (sizeof($pk_columns) == 1 && $column_info[$pk_columns[0]]['auto_increment'] && !$this->values[$pk_columns[0]]) {
                 $new_autoincrementing_record = TRUE;
                 $pk_column = $pk_columns[0];
             }
         }
         $inside_db_transaction = fORMDatabase::retrieve()->isInsideTransaction();
         if (!$inside_db_transaction) {
             fORMDatabase::retrieve()->translatedQuery('BEGIN');
         }
         fORM::callHookCallbacks($this, 'post-begin::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
         $this->validate();
         fORM::callHookCallbacks($this, 'post-validate::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
         // Storing main table
         $sql_values = array();
         foreach ($column_info as $column => $info) {
             $value = fORM::scalarize($class, $column, $this->values[$column]);
             $sql_values[$column] = fORMDatabase::escapeBySchema($table, $column, $value);
         }
         // Most databases don't like the auto incrementing primary key to be set to NULL
         if ($new_autoincrementing_record && $sql_values[$pk_column] == 'NULL') {
             unset($sql_values[$pk_column]);
         }
         if (!$this->exists()) {
             $sql = $this->constructInsertSQL($sql_values);
         } else {
             $sql = $this->constructUpdateSQL($sql_values);
         }
         $result = fORMDatabase::retrieve()->translatedQuery($sql);
         // If there is an auto-incrementing primary key, grab the value from the database
         if ($new_autoincrementing_record) {
             $this->set($pk_column, $result->getAutoIncrementedValue());
         }
         // Storing *-to-many relationships
         fORMRelated::store($class, $this->values, $this->related_records);
         fORM::callHookCallbacks($this, 'pre-commit::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
         if (!$inside_db_transaction) {
             fORMDatabase::retrieve()->translatedQuery('COMMIT');
         }
         fORM::callHookCallbacks($this, 'post-commit::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
     } catch (fException $e) {
         if (!$inside_db_transaction) {
             fORMDatabase::retrieve()->translatedQuery('ROLLBACK');
         }
         fORM::callHookCallbacks($this, 'post-rollback::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
         if ($new_autoincrementing_record && self::hasOld($this->old_values, $pk_column)) {
             $this->values[$pk_column] = self::retrieveOld($this->old_values, $pk_column);
             unset($this->old_values[$pk_column]);
         }
         throw $e;
     }
     fORM::callHookCallbacks($this, 'post::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
     $was_new = !$this->exists();
     // If we got here we succefully stored, so update old values to make exists() work
     foreach ($this->values as $column => $value) {
         $this->old_values[$column] = array($value);
     }
     // If the object was just inserted into the database, save it to the identity map
     if ($was_new) {
         $hash = self::hash($this->values, $class);
         if (!isset(self::$identity_map[$class])) {
             self::$identity_map[$class] = array();
         }
         self::$identity_map[$class][$hash] = $this;
     }
     return $this;
 }
コード例 #3
0
 /**
  * Validates values for an fActiveRecord object against the database schema and any additional rules that have been added
  *
  * @internal
  *
  * @param  fActiveRecord  $object      The instance of the class to validate
  * @param  array          $values      The values to validate
  * @param  array          $old_values  The old values for the record
  * @return array  An array of messages
  */
 public static function validate($object, $values, $old_values)
 {
     $class = get_class($object);
     $table = fORM::tablize($class);
     $schema = fORMSchema::retrieve($class);
     self::initializeRuleArrays($class);
     $validation_messages = array();
     // Convert objects into values for validation
     foreach ($values as $column => $value) {
         $values[$column] = fORM::scalarize($class, $column, $value);
     }
     foreach ($old_values as $column => $column_values) {
         foreach ($column_values as $key => $value) {
             $old_values[$column][$key] = fORM::scalarize($class, $column, $value);
         }
     }
     $message_array = self::checkPrimaryKeys($schema, $object, $values, $old_values);
     if ($message_array) {
         $validation_messages[key($message_array)] = current($message_array);
     }
     $column_info = $schema->getColumnInfo($table);
     foreach ($column_info as $column => $info) {
         $message = self::checkAgainstSchema($schema, $object, $column, $values, $old_values);
         if ($message) {
             $validation_messages[$column] = $message;
         }
     }
     $messages = self::checkUniqueConstraints($schema, $object, $values, $old_values);
     if ($messages) {
         $validation_messages = array_merge($validation_messages, $messages);
     }
     foreach (self::$valid_values_rules[$class] as $column => $valid_values) {
         $message = self::checkValidValuesRule($class, $values, $column, $valid_values);
         if ($message) {
             $validation_messages[$column] = $message;
         }
     }
     foreach (self::$regex_rules[$class] as $column => $rule) {
         $message = self::checkRegexRule($class, $values, $column, $rule['regex'], $rule['message']);
         if ($message) {
             $validation_messages[$column] = $message;
         }
     }
     foreach (self::$conditional_rules[$class] as $rule) {
         $messages = self::checkConditionalRule($schema, $class, $values, $rule['main_columns'], $rule['conditional_values'], $rule['conditional_columns']);
         if ($messages) {
             $validation_messages = array_merge($validation_messages, $messages);
         }
     }
     foreach (self::$one_or_more_rules[$class] as $rule) {
         $message = self::checkOneOrMoreRule($schema, $class, $values, $rule['columns']);
         if ($message) {
             $validation_messages[join(',', $rule['columns'])] = $message;
         }
     }
     foreach (self::$only_one_rules[$class] as $rule) {
         $message = self::checkOnlyOneRule($schema, $class, $values, $rule['columns']);
         if ($message) {
             $validation_messages[join(',', $rule['columns'])] = $message;
         }
     }
     return $validation_messages;
 }
コード例 #4
0
ファイル: fORMDatabase.php プロジェクト: jsuarez/MyDesign
 /**
  * Escapes a value for a DB call based on database schema
  * 
  * @internal
  * 
  * @param  string $table                The table to store the value
  * @param  string $column               The column to store the value in, may also be shorthand column name like `table.column` or `table=>related_table.column` or concatenated column names like `table.column||table.other_column`
  * @param  mixed  $value                The value to escape
  * @param  string $comparison_operator  Optional: should be `'='`, `'!='`, `'!'`, `'<>'`, `'<'`, `'<='`, `'>'`, `'>='`, `'IN'`, `'NOT IN'`
  * @return string  The SQL-ready representation of the value
  */
 public static function escapeBySchema($table, $column, $value, $comparison_operator = NULL)
 {
     // handle concatenated column names
     if (preg_match('#\\|\\|#', $column)) {
         if (is_object($value) && is_callable(array($value, '__toString'))) {
             $value = $value->__toString();
         } elseif (is_object($value)) {
             $value = (string) $value;
         }
         $column_info = array('not_null' => FALSE, 'default' => NULL, 'type' => 'varchar');
     } else {
         // Handle shorthand column names like table.column and table=>related_table.column
         if (preg_match('#(\\w+)(?:\\{\\w+\\})?\\.(\\w+)$#D', $column, $match)) {
             $table = $match[1];
             $column = $match[2];
         }
         $column_info = fORMSchema::retrieve()->getColumnInfo($table, $column);
         // Some of the tables being escaped for are linking tables that might break with classize()
         if (is_object($value)) {
             $class = fORM::classize($table);
             $value = fORM::scalarize($class, $column, $value);
         }
     }
     if ($comparison_operator !== NULL) {
         $comparison_operator = strtr($comparison_operator, array('!' => '<>', '!=' => '<>'));
     }
     $valid_comparison_operators = array('=', '!=', '!', '<>', '<=', '<', '>=', '>', 'IN', 'NOT IN');
     if ($comparison_operator !== NULL && !in_array(strtoupper($comparison_operator), $valid_comparison_operators)) {
         throw new fProgrammerException('The comparison operator specified, %1$s, is invalid. Must be one of: %2$s.', $comparison_operator, join(', ', $valid_comparison_operators));
     }
     $co = is_null($comparison_operator) ? '' : ' ' . strtoupper($comparison_operator) . ' ';
     if ($column_info['not_null'] && $value === NULL && $column_info['default'] !== NULL) {
         $value = $column_info['default'];
     }
     if (is_null($value)) {
         $prepared_value = 'NULL';
     } else {
         $prepared_value = self::retrieve()->escape($column_info['type'], $value);
     }
     if ($prepared_value == 'NULL') {
         if ($co) {
             if (in_array(trim($co), array('=', 'IN'))) {
                 $co = ' IS ';
             } elseif (in_array(trim($co), array('<>', 'NOT IN'))) {
                 $co = ' IS NOT ';
             }
         }
     }
     return $co . $prepared_value;
 }