public function setUp()
 {
     if (defined('SKIPPING')) {
         $this->markTestSkipped();
     }
     self::$db->execute('BEGIN');
     fActiveRecord::clearIdentityMap();
 }
Example #2
0
 public static function import_from_array_to_graph($input, $graph_id)
 {
     $result = true;
     if (!empty($input)) {
         $columns_to_ignore = array('line_id', 'graph_id');
         $new_line = fActiveRecord::array_to_dbentry($input, __CLASS__, $columns_to_ignore);
         if ($new_line !== NULL) {
             $new_line->setGraphId($graph_id);
             $new_line->store();
         } else {
             $result = false;
         }
     }
     return $result;
 }
Example #3
0
 /**
  * Sets the timezone column and then tries to objectify the related timestamp column
  *
  * @internal
  *
  * @param  fActiveRecord $object            The fActiveRecord instance
  * @param  array         &$values           The current values
  * @param  array         &$old_values       The old values
  * @param  array         &$related_records  Any records related to this record
  * @param  array         &$cache            The cache array for the record
  * @param  string        $method_name       The method that was called
  * @param  array         $parameters        The parameters passed to the method
  * @return fActiveRecord  The record object, to allow for method chaining
  */
 public static function setTimezoneColumn($object, &$values, &$old_values, &$related_records, &$cache, $method_name, $parameters)
 {
     list($action, $subject) = fORM::parseMethod($method_name);
     $column = fGrammar::underscorize($subject);
     $class = get_class($object);
     if (!isset($parameters[0])) {
         throw new fProgrammerException('The method, %s(), requires at least one parameter', $method_name);
     }
     fActiveRecord::assign($values, $old_values, $column, $parameters[0]);
     // See if we can make an fTimestamp object out of the values
     self::objectifyTimestampWithTimezone($values, $old_values, self::$timezone_columns[$class][$column], $column);
     return $object;
 }
 /**
  * Returns a new fRecordSet containing only unique records in the record set
  * 
  * @param  boolean $remember_original_count  If the number of records in the current set should be saved as the non-limited count for the new set - the page will be reset to `1` either way
  * @return fRecordSet  The new record set with only unique records
  */
 public function unique($remember_original_count = FALSE)
 {
     $records = array();
     foreach ($this->records as $record) {
         $class = get_class($record);
         $hash = fActiveRecord::hash($record);
         if (isset($records[$class . '::' . $hash])) {
             continue;
         }
         $records[$class . '::' . $hash] = $record;
     }
     $set = new fRecordSet($this->class, array_values($records));
     if ($remember_original_count) {
         $set->non_limited_count = $this->count();
     }
     return $set;
 }
 /**
  * Validates values against unique constraints
  *
  * @param  fSchema        $schema       The schema object for the object
  * @param  fActiveRecord  $object       The instance of the class to check
  * @param  array          &$values      The values to check
  * @param  array          &$old_values  The old values for the record
  * @return array  An aray of error messages for the unique constraints
  */
 private static function checkUniqueConstraints($schema, $object, &$values, &$old_values)
 {
     $class = get_class($object);
     $table = fORM::tablize($class);
     $db = fORMDatabase::retrieve($class, 'read');
     $key_info = $schema->getKeys($table);
     $pk_columns = $key_info['primary'];
     $unique_keys = $key_info['unique'];
     $messages = array();
     foreach ($unique_keys as $unique_columns) {
         settype($unique_columns, 'array');
         // NULL values are unique
         $found_not_null = FALSE;
         foreach ($unique_columns as $unique_column) {
             if ($values[$unique_column] !== NULL) {
                 $found_not_null = TRUE;
             }
         }
         if (!$found_not_null) {
             continue;
         }
         $params = array("SELECT %r FROM %r WHERE ", $key_info['primary'], $table);
         $column_info = $schema->getColumnInfo($table);
         $conditions = array();
         foreach ($unique_columns as $unique_column) {
             $value = $values[$unique_column];
             // This makes sure the query performs the way an insert will
             if ($value === NULL && $column_info[$unique_column]['not_null'] && $column_info[$unique_column]['default'] !== NULL) {
                 $value = $column_info[$unique_column]['default'];
             }
             if (self::isCaseInsensitive($class, $unique_column) && self::stringlike($value)) {
                 $condition = fORMDatabase::makeCondition($schema, $table, $unique_column, '=', $value);
                 $conditions[] = str_replace('%r', 'LOWER(%r)', $condition);
                 $params[] = $table . '.' . $unique_column;
                 $params[] = fUTF8::lower($value);
             } else {
                 $conditions[] = fORMDatabase::makeCondition($schema, $table, $unique_column, '=', $value);
                 $params[] = $table . '.' . $unique_column;
                 $params[] = $value;
             }
         }
         $params[0] .= join(' AND ', $conditions);
         if ($object->exists()) {
             foreach ($pk_columns as $pk_column) {
                 $value = fActiveRecord::retrieveOld($old_values, $pk_column, $values[$pk_column]);
                 $params[0] .= ' AND ' . fORMDatabase::makeCondition($schema, $table, $pk_column, '<>', $value);
                 $params[] = $table . '.' . $pk_column;
                 $params[] = $value;
             }
         }
         try {
             $result = call_user_func_array($db->translatedQuery, $params);
             $result->tossIfNoRows();
             // If an exception was not throw, we have existing values
             $column_names = array();
             foreach ($unique_columns as $unique_column) {
                 $column_names[] = fORM::getColumnName($class, $unique_column);
             }
             if (sizeof($column_names) == 1) {
                 $messages[join('', $unique_columns)] = self::compose('%sThe value specified must be unique, however it already exists', fValidationException::formatField(join('', $column_names)));
             } else {
                 $messages[join(',', $unique_columns)] = self::compose('%sThe values specified must be a unique combination, however the specified combination already exists', fValidationException::formatField(join(', ', $column_names)));
             }
         } catch (fNoRowsException $e) {
         }
     }
     return $messages;
 }
 /**
  * Makes sure the ordering value is sane, removes error messages about missing values
  *
  * @internal
  *
  * @param  fActiveRecord $object                The fActiveRecord instance
  * @param  array         &$values               The current values
  * @param  array         &$old_values           The old values
  * @param  array         &$related_records      Any records related to this record
  * @param  array         &$cache                The cache array for the record
  * @param  array         &$validation_messages  An array of ordered validation messages
  * @return void
  */
 public static function validate($object, &$values, &$old_values, &$related_records, &$cache, &$validation_messages)
 {
     $class = get_class($object);
     $table = fORM::tablize($class);
     $db = fORMDatabase::retrieve($class, 'read');
     $schema = fORMSchema::retrieve($class);
     foreach (self::$ordering_columns[$class] as $column => $other_columns) {
         $current_value = $values[$column];
         $old_value = fActiveRecord::retrieveOld($old_values, $column);
         $params = array("SELECT MAX(%r) FROM %r", $column, $table);
         if ($other_columns) {
             $params[0] .= " WHERE ";
             $params = self::addOtherFieldsWhereParams($schema, $params, $table, $other_columns, $values);
         }
         $current_max_value = (int) call_user_func_array($db->translatedQuery, $params)->fetchScalar();
         $new_max_value = $current_max_value;
         if ($new_set = self::isInNewSet($column, $other_columns, $values, $old_values)) {
             $new_max_value = $current_max_value + 1;
             $new_set_new_value = fActiveRecord::changed($values, $old_values, $column);
         }
         $column_name = fORM::getColumnName($class, $column);
         // Remove any previous validation warnings
         $filtered_messages = array();
         foreach ($validation_messages as $validation_column => $validation_message) {
             if (!preg_match('#(^|,)' . preg_quote($column, '#') . '(,|$)#D', $validation_column)) {
                 $filtered_messages[$validation_column] = $validation_message;
             }
         }
         $validation_messages = $filtered_messages;
         // If we have a completely empty value, we don't need to validate since a valid value will be generated
         if ($current_value === '' || $current_value === NULL) {
             continue;
         }
         if (!is_numeric($current_value) || strlen((int) $current_value) != strlen($current_value)) {
             $validation_messages[$column] = self::compose('%sPlease enter an integer', fValidationException::formatField($column_name));
         } elseif ($current_value < 1) {
             $validation_messages[$column] = self::compose('%sThe value can not be less than 1', fValidationException::formatField($column_name));
         }
     }
 }
Example #7
0
 /**
  * Validates values against unique constraints
  *
  * @param  fActiveRecord  $object       The instance of the class to check
  * @param  array          &$values      The values to check
  * @param  array          &$old_values  The old values for the record
  * @return string  An error message for the unique constraints
  */
 private static function checkUniqueConstraints($object, &$values, &$old_values)
 {
     $class = get_class($object);
     $table = fORM::tablize($class);
     $key_info = fORMSchema::retrieve()->getKeys($table);
     $primary_keys = $key_info['primary'];
     $unique_keys = $key_info['unique'];
     foreach ($unique_keys as $unique_columns) {
         settype($unique_columns, 'array');
         // NULL values are unique
         $found_not_null = FALSE;
         foreach ($unique_columns as $unique_column) {
             if ($values[$unique_column] !== NULL) {
                 $found_not_null = TRUE;
             }
         }
         if (!$found_not_null) {
             continue;
         }
         $sql = "SELECT " . join(', ', $key_info['primary']) . " FROM " . $table . " WHERE ";
         $first = TRUE;
         foreach ($unique_columns as $unique_column) {
             if ($first) {
                 $first = FALSE;
             } else {
                 $sql .= " AND ";
             }
             $value = $values[$unique_column];
             if (self::isCaseInsensitive($class, $unique_column) && self::stringlike($value)) {
                 $sql .= 'LOWER(' . $unique_column . ')' . fORMDatabase::escapeBySchema($table, $unique_column, fUTF8::lower($value), '=');
             } else {
                 $sql .= $unique_column . fORMDatabase::escapeBySchema($table, $unique_column, $value, '=');
             }
         }
         if ($object->exists()) {
             foreach ($primary_keys as $primary_key) {
                 $value = fActiveRecord::retrieveOld($old_values, $primary_key, $values[$primary_key]);
                 $sql .= ' AND ' . $primary_key . fORMDatabase::escapeBySchema($table, $primary_key, $value, '<>');
             }
         }
         try {
             $result = fORMDatabase::retrieve()->translatedQuery($sql);
             $result->tossIfNoRows();
             // If an exception was not throw, we have existing values
             $column_names = array();
             foreach ($unique_columns as $unique_column) {
                 $column_names[] = fORM::getColumnName($class, $unique_column);
             }
             if (sizeof($column_names) == 1) {
                 return self::compose('%sThe value specified must be unique, however it already exists', fValidationException::formatField(join('', $column_names)));
             } else {
                 return self::compose('%sThe values specified must be a unique combination, however the specified combination already exists', fValidationException::formatField(join(', ', $column_names)));
             }
         } catch (fNoRowsException $e) {
         }
     }
 }
Example #8
0
 /**
  * Sets the money column and then tries to objectify it with an related currency column
  * 
  * @internal
  * 
  * @param  fActiveRecord $object            The fActiveRecord instance
  * @param  array         &$values           The current values
  * @param  array         &$old_values       The old values
  * @param  array         &$related_records  Any records related to this record
  * @param  array         &$cache            The cache array for the record
  * @param  string        $method_name       The method that was called
  * @param  array         $parameters        The parameters passed to the method
  * @return fActiveRecord  The record object, to allow for method chaining
  */
 public static function setMoneyColumn($object, &$values, &$old_values, &$related_records, &$cache, $method_name, $parameters)
 {
     list($action, $column) = fORM::parseMethod($method_name);
     $class = get_class($object);
     if (count($parameters) < 1) {
         throw new fProgrammerException('The method, %s(), requires at least one parameter', $method_name);
     }
     $value = $parameters[0];
     fActiveRecord::assign($values, $old_values, $column, $value);
     $currency_column = self::$money_columns[$class][$column];
     // See if we can make an fMoney object out of the values
     self::objectifyMoneyWithCurrency($values, $old_values, $column, $currency_column);
     if ($currency_column) {
         if ($value instanceof fMoney) {
             fActiveRecord::assign($values, $old_values, $currency_column, $value->getCurrency());
         }
     }
     return $object;
 }
Example #9
0
function changed($object, &$values, &$old_values, &$related_records, &$cache, $method, $parameters)
{
    return fActiveRecord::changed($values, $old_values, $parameters[0]);
}
Example #10
0
 /**
  * Add the appropriate SQL and params for a `WHERE` clause condition for primary keys of the table specified
  * 
  * @internal
  * 
  * @param  fSchema $schema        The schema for the database the query will be run on
  * @param  array   $params        The currently constructed params for fDatabase::query() - the first param should be a SQL statement
  * @param  string  $table         The table to build the where clause for
  * @param  string  $table_alias   The alias for the table
  * @param  array   &$values       The values array for the fActiveRecord object
  * @param  array   &$old_values   The old values array for the fActiveRecord object
  * @return array  The params to pass to fDatabase::query(), including the new primary key where condition
  */
 public static function addPrimaryKeyWhereParams($schema, $params, $table, $table_alias, &$values, &$old_values)
 {
     $pk_columns = $schema->getKeys($table, 'primary');
     $column_info = $schema->getColumnInfo($table);
     $conditions = array();
     foreach ($pk_columns as $pk_column) {
         $value = fActiveRecord::retrieveOld($old_values, $pk_column, $values[$pk_column]);
         // This makes sure the query performs the way an insert will
         if ($value === NULL && $column_info[$pk_column]['not_null'] && $column_info[$pk_column]['default'] !== NULL) {
             $value = $column_info[$pk_column]['default'];
         }
         $params[] = $table_alias . '.' . $pk_column;
         $params[] = $value;
         $conditions[] = self::makeCondition($schema, $table, $pk_column, '=', $value);
     }
     $params[0] .= join(' AND ', $conditions);
     return $params;
 }
 /**
  * @see fActiveRecord::set()
  */
 protected function set($column, $value)
 {
     if (isset($this->columnAliases[$column])) {
         $column = $this->columnAliases[$column];
     }
     return parent::set($column, $value);
 }
 /**
  * Sets the appropriate column values to a random string if the object is new
  *
  * @internal
  *
  * @param  fActiveRecord $object            The fActiveRecord instance
  * @param  array         &$values           The current values
  * @param  array         &$old_values       The old values
  * @param  array         &$related_records  Any records related to this record
  * @param  array         &$cache            The cache array for the record
  * @return string  The formatted link
  */
 public static function setRandomStrings($object, &$values, &$old_values, &$related_records, &$cache)
 {
     if ($object->exists()) {
         return;
     }
     $class = get_class($object);
     $table = fORM::tablize($class);
     foreach (self::$random_columns[$class] as $column => $settings) {
         if (fActiveRecord::hasOld($old_values, $column) && $values[$column]) {
             continue;
         }
         self::generate($object, $values, $old_values, $related_records, $cache, 'generate' . fGrammar::camelize($column, TRUE), array());
     }
 }
Example #13
0
 /**
  * Generates a clone of the current record, removing any auto incremented primary key value and allowing for replicating related records
  * 
  * This method will accept three different sets of parameters:
  * 
  *  - No parameters: this object will be cloned
  *  - A single `TRUE` value: this object plus all many-to-many associations and all child records (recursively) will be cloned
  *  - Any number of plural related record class names: the many-to-many associations or child records that correspond to the classes specified will be cloned
  * 
  * The class names specified can be a simple class name if there is only a
  * single route between the two corresponding database tables. If there is 
  * more than one route between the two tables, the class name should be
  * substituted with a string in the format `'RelatedClass{route}'`.
  * 
  * @param  string $related_class  The plural related class to replicate - see method description for details
  * @param  string ...
  * @return fActiveRecord  The cloned record
  */
 public function replicate($related_class = NULL)
 {
     fActiveRecord::$replicate_level++;
     $class = get_class($this);
     $hash = self::hash($this->values, $class);
     $table = fORM::tablize($class);
     // If the object has not been replicated yet, do it now
     if (!isset(fActiveRecord::$replicate_map[$class])) {
         fActiveRecord::$replicate_map[$class] = array();
     }
     if (!isset(fActiveRecord::$replicate_map[$class][$hash])) {
         fActiveRecord::$replicate_map[$class][$hash] = clone $this;
         // We need the primary key to get a hash, otherwise certain recursive relationships end up losing members
         $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary');
         if (sizeof($pk_columns) == 1 && fORMSchema::retrieve()->getColumnInfo($table, $pk_columns[0], 'auto_increment')) {
             fActiveRecord::$replicate_map[$class][$hash]->values[$pk_columns[0]] = $this->values[$pk_columns[0]];
         }
     }
     $clone = fActiveRecord::$replicate_map[$class][$hash];
     $parameters = func_get_args();
     $recursive = FALSE;
     $many_to_many_relationships = fORMSchema::retrieve()->getRelationships($table, 'many-to-many');
     $one_to_many_relationships = fORMSchema::retrieve()->getRelationships($table, 'one-to-many');
     // When just TRUE is passed we recursively replicate all related records
     if (sizeof($parameters) == 1 && $parameters[0] === TRUE) {
         $parameters = array();
         $recursive = TRUE;
         foreach ($many_to_many_relationships as $relationship) {
             $parameters[] = fGrammar::pluralize(fORM::classize($relationship['related_table'])) . '{' . $relationship['join_table'] . '}';
         }
         foreach ($one_to_many_relationships as $relationship) {
             $parameters[] = fGrammar::pluralize(fORM::classize($relationship['related_table'])) . '{' . $relationship['related_column'] . '}';
         }
     }
     $record_sets = array();
     foreach ($parameters as $parameter) {
         // Parse the Class{route} strings
         if (strpos($parameter, '{') !== FALSE) {
             $brace = strpos($parameter, '{');
             $related_class = fGrammar::singularize(substr($parameter, 0, $brace));
             $related_table = fORM::tablize($related_class);
             $route = substr($parameter, $brace + 1, -1);
         } else {
             $related_class = fGrammar::singularize($parameter);
             $related_table = fORM::tablize($related_class);
             $route = fORMSchema::getRouteName($table, $related_table);
         }
         // Determine the kind of relationship
         $many_to_many = FALSE;
         $one_to_many = FALSE;
         foreach ($many_to_many_relationships as $relationship) {
             if ($relationship['related_table'] == $related_table && $relationship['join_table'] == $route) {
                 $many_to_many = TRUE;
                 break;
             }
         }
         foreach ($one_to_many_relationships as $relationship) {
             if ($relationship['related_table'] == $related_table && $relationship['related_column'] == $route) {
                 $one_to_many = TRUE;
                 break;
             }
         }
         if (!$many_to_many && !$one_to_many) {
             throw new fProgrammerException('The related class specified, %1$s, does not appear to be in a many-to-many or one-to-many relationship with %$2s', $parameter, get_class($this));
         }
         // Get the related records
         $record_set = fORMRelated::buildRecords($class, $this->values, $this->related_records, $related_class, $route);
         // One-to-many records need to be replicated, possibly recursively
         if ($one_to_many) {
             if ($recursive) {
                 $records = $record_set->call('replicate', TRUE);
             } else {
                 $records = $record_set->call('replicate');
             }
             $record_set = fRecordSet::buildFromArray($related_class, $records);
             $record_set->call('set' . fGrammar::camelize($route, TRUE), NULL);
         }
         // Cause the related records to be associated with the new clone
         fORMRelated::associateRecords($class, $clone->related_records, $related_class, $record_set, $route);
     }
     fActiveRecord::$replicate_level--;
     if (!fActiveRecord::$replicate_level) {
         // This removes the primary keys we had added back in for proper duplicate detection
         foreach (fActiveRecord::$replicate_map as $class => $records) {
             $table = fORM::tablize($class);
             $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary');
             if (sizeof($pk_columns) != 1 || !fORMSchema::retrieve()->getColumnInfo($table, $pk_columns[0], 'auto_increment')) {
                 continue;
             }
             foreach ($records as $hash => $record) {
                 $record->values[$pk_columns[0]] = NULL;
             }
         }
         fActiveRecord::$replicate_map = array();
     }
     return $clone;
 }
Example #14
0
 public static function import_from_json_to_group($json, $group_id = NULL)
 {
     $result = true;
     $json_array = json_decode($json, TRUE);
     if (!empty($json_array)) {
         if (array_key_exists("name", $json_array)) {
             // In this case, we only have a dashboard, not an array of dashboard
             // We convert it into an array
             $json_array = array($json_array);
         }
         foreach ($json_array as $dashboard_to_create) {
             $column_to_ignore = array('dashboard_id', 'group_id', 'graphs');
             $new_dashboard = fActiveRecord::array_to_dbentry($dashboard_to_create, __CLASS__, $column_to_ignore);
             if ($new_dashboard !== NULL) {
                 $new_dashboard->setGroupId(empty($group_id) ? $GLOBALS['DEFAULT_GROUP_ID'] : $group_id);
                 $new_dashboard->setUserId(fSession::get('user_id', 1));
                 $new_dashboard->store();
                 if (in_array('graphs', array_keys($dashboard_to_create))) {
                     $new_dashboard_id = $new_dashboard->getDashboardId();
                     foreach ($dashboard_to_create['graphs'] as $graph) {
                         $result_graph = Graph::import_from_array_to_dashboard($graph, $new_dashboard_id);
                         $result = $result && $result_graph;
                     }
                 }
             } else {
                 $result = false;
             }
         }
     } else {
         fMessaging::create('error', "/" . Dashboard::makeUrl('list'), "Empty or malformed file");
         $result = false;
     }
     return $result;
 }
 /**
  * Sets the related records for *-to-many relationships
  *
  * @internal
  *
  * @param  string $class             The class to set the related records for
  * @param  array  &$related_records  The related records existing for the fActiveRecord class
  * @param  string $related_class     The class we are associating with the current record
  * @param  fRecordSet $records       The records are associating
  * @param  string $route             The route to use between the current class and the related class
  * @return void
  */
 public static function setRecordSet($class, &$related_records, $related_class, fRecordSet $records, $route = NULL)
 {
     fActiveRecord::validateClass($related_class);
     fActiveRecord::forceConfigure($related_class);
     $table = fORM::tablize($class);
     $related_table = fORM::tablize($related_class);
     $schema = fORMSchema::retrieve($class);
     $route = fORMSchema::getRouteName($schema, $table, $related_table, $route);
     if (!isset($related_records[$related_table])) {
         $related_records[$related_table] = array();
     }
     if (!isset($related_records[$related_table][$route])) {
         $related_records[$related_table][$route] = array();
     }
     $related_records[$related_table][$route]['record_set'] = $records;
     $related_records[$related_table][$route]['count'] = $records->count();
     $related_records[$related_table][$route]['associate'] = FALSE;
     $related_records[$related_table][$route]['primary_keys'] = NULL;
 }
Example #16
0
 /**
  * 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
  * 
  * @param  boolean $force_cascade  When storing related records, this will force deleting child records even if they have their own children in a relationship with an RESTRICT or NO ACTION for the ON DELETE clause
  * @return fActiveRecord  The record object, to allow for method chaining
  */
 public function store($force_cascade = FALSE)
 {
     $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);
     $db = fORMDatabase::retrieve($class, 'write');
     $schema = fORMSchema::retrieve($class);
     try {
         $table = fORM::tablize($class);
         // New auto-incrementing records require lots of special stuff, so we'll detect them here
         $new_autoincrementing_record = FALSE;
         if (!$this->exists()) {
             $pk_columns = $schema->getKeys($table, 'primary');
             $pk_column = $pk_columns[0];
             $pk_auto_incrementing = $schema->getColumnInfo($table, $pk_column, 'auto_increment');
             if (sizeof($pk_columns) == 1 && $pk_auto_incrementing && !$this->values[$pk_column]) {
                 $new_autoincrementing_record = TRUE;
             }
         }
         $inside_db_transaction = $db->isInsideTransaction();
         if (!$inside_db_transaction) {
             $db->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
         if (!$this->exists()) {
             $params = $this->constructInsertParams();
         } else {
             $params = $this->constructUpdateParams();
         }
         $result = call_user_func_array($db->translatedQuery, $params);
         // If there is an auto-incrementing primary key, grab the value from the database
         if ($new_autoincrementing_record) {
             $this->set($pk_column, $result->getAutoIncrementedValue());
         }
         // Fix cascade updated columns for in-memory objects to prevent issues when saving
         $one_to_one_relationships = $schema->getRelationships($table, 'one-to-one');
         $one_to_many_relationships = $schema->getRelationships($table, 'one-to-many');
         $relationships = array_merge($one_to_one_relationships, $one_to_many_relationships);
         foreach ($relationships as $relationship) {
             $type = in_array($relationship, $one_to_one_relationships) ? 'one-to-one' : 'one-to-many';
             $route = fORMSchema::getRouteNameFromRelationship($type, $relationship);
             $related_table = $relationship['related_table'];
             $related_class = fORM::classize($related_table);
             $related_class = fORM::getRelatedClass($class, $related_class);
             if ($relationship['on_update'] != 'cascade') {
                 continue;
             }
             $column = $relationship['column'];
             if (!fActiveRecord::changed($this->values, $this->old_values, $column)) {
                 continue;
             }
             if (!isset($this->related_records[$related_table][$route]['record_set'])) {
                 continue;
             }
             $record_set = $this->related_records[$related_table][$route]['record_set'];
             $related_column = $relationship['related_column'];
             $old_value = fActiveRecord::retrieveOld($this->old_values, $column);
             $value = $this->values[$column];
             if ($old_value === NULL) {
                 continue;
             }
             foreach ($record_set as $record) {
                 if (isset($record->old_values[$related_column])) {
                     foreach (array_keys($record->old_values[$related_column]) as $key) {
                         if ($record->old_values[$related_column][$key] === $old_value) {
                             $record->old_values[$related_column][$key] = $value;
                         }
                     }
                 }
                 if ($record->values[$related_column] === $old_value) {
                     $record->values[$related_column] = $value;
                 }
             }
         }
         // Storing *-to-many and one-to-one relationships
         fORMRelated::store($class, $this->values, $this->related_records, $force_cascade);
         fORM::callHookCallbacks($this, 'pre-commit::store()', $this->values, $this->old_values, $this->related_records, $this->cache);
         if (!$inside_db_transaction) {
             $db->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) {
             $db->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;
 }
Example #17
0
 /**
  * Makes sure the ordering value is sane, removes error messages about missing values
  * 
  * @internal
  * 
  * @param  fActiveRecord $object                The fActiveRecord instance
  * @param  array         &$values               The current values
  * @param  array         &$old_values           The old values
  * @param  array         &$related_records      Any records related to this record
  * @param  array         &$cache                The cache array for the record
  * @param  array         &$validation_messages  An array of ordered validation messages
  * @return void
  */
 public static function validate($object, &$values, &$old_values, &$related_records, &$cache, &$validation_messages)
 {
     $class = get_class($object);
     $table = fORM::tablize($class);
     $column = self::$ordering_columns[$class]['column'];
     $other_columns = self::$ordering_columns[$class]['other_columns'];
     $current_value = $values[$column];
     $old_value = fActiveRecord::retrieveOld($old_values, $column);
     $sql = "SELECT max(" . $column . ") FROM " . $table;
     if ($other_columns) {
         $sql .= " WHERE " . self::createOtherFieldsWhereClause($table, $other_columns, $values);
     }
     $current_max_value = (int) fORMDatabase::retrieve()->translatedQuery($sql)->fetchScalar();
     $new_max_value = $current_max_value;
     if ($new_set = self::isInNewSet($column, $other_columns, $values, $old_values)) {
         $new_max_value = $current_max_value + 1;
         $new_set_new_value = fActiveRecord::changed($values, $old_values, $column);
     }
     $column_name = fORM::getColumnName($class, $column);
     // Remove any previous validation warnings
     $filtered_messages = array();
     foreach ($validation_messages as $validation_message) {
         if (!preg_match('#^' . str_replace('___', '(.*?)', preg_quote(fValidationException::formatField('___' . $column_name . '___'), '#')) . '#', $validation_message)) {
             $filtered_messages[] = $validation_message;
         }
     }
     $validation_messages = $filtered_messages;
     // If we have a completely empty value, we don't need to validate since a valid value will be generated
     if ($current_value === '' || $current_value === NULL) {
         return;
     }
     if (!is_numeric($current_value) || strlen((int) $current_value) != strlen($current_value)) {
         $validation_messages[] = self::compose('%sPlease enter an integer', fValidationException::formatField($column_name));
     } elseif ($current_value < 1) {
         $validation_messages[] = self::compose('%sThe value can not be less than 1', fValidationException::formatField($column_name));
     }
 }
Example #18
0
 /**
  * Uploads a file
  * 
  * @internal
  * 
  * @param  fActiveRecord $object            The fActiveRecord instance
  * @param  array         &$values           The current values
  * @param  array         &$old_values       The old values
  * @param  array         &$related_records  Any records related to this record
  * @param  array         &$cache            The cache array for the record
  * @param  string        $method_name       The method that was called
  * @param  array         $parameters        The parameters passed to the method
  * @return fFile  The uploaded file
  */
 public static function upload($object, &$values, &$old_values, &$related_records, &$cache, $method_name, $parameters)
 {
     $class = get_class($object);
     list($action, $column) = fORM::parseMethod($method_name);
     $existing_temp_file = FALSE;
     // Try to upload the file putting it in the temp dir incase there is a validation problem with the record
     try {
         $upload_dir = self::$file_upload_columns[$class][$column];
         $temp_dir = self::prepareTempDir($upload_dir);
         if (!fUpload::check($column)) {
             throw new fExpectedException('Please upload a file');
         }
         $uploader = self::setUpFUpload($class, $column);
         $file = $uploader->move($temp_dir, $column);
         // If there was an eror, check to see if we have an existing file
     } catch (fExpectedException $e) {
         // If there is an existing file and none was uploaded, substitute the existing file
         $existing_file = fRequest::get('existing-' . $column);
         $delete_file = fRequest::get('delete-' . $column, 'boolean');
         $no_upload = $e->getMessage() == self::compose('Please upload a file');
         if ($existing_file && $delete_file && $no_upload) {
             $file = NULL;
         } elseif ($existing_file) {
             $file_path = $upload_dir->getPath() . $existing_file;
             $file = fFilesystem::createObject($file_path);
             $current_file = $values[$column];
             // If the existing file is the same as the current file, we can just exit now
             if ($current_file && $file->getPath() == $current_file->getPath()) {
                 return;
             }
             $existing_temp_file = TRUE;
         } else {
             $file = NULL;
         }
     }
     // Assign the file
     fActiveRecord::assign($values, $old_values, $column, $file);
     // Perform the file upload inheritance
     if (!empty(self::$column_inheritence[$class][$column])) {
         foreach (self::$column_inheritence[$class][$column] as $other_column) {
             if ($file) {
                 // Image columns will only inherit if it is an fImage object
                 if (!$file instanceof fImage && isset(self::$image_upload_columns[$class][$other_column])) {
                     continue;
                 }
                 $other_upload_dir = self::$file_upload_columns[$class][$other_column];
                 $other_temp_dir = self::prepareTempDir($other_upload_dir);
                 if ($existing_temp_file) {
                     $other_file = fFilesystem::createObject($other_temp_dir->getPath() . $file->getName());
                 } else {
                     $other_file = $file->duplicate($other_temp_dir, FALSE);
                 }
             } else {
                 $other_file = $file;
             }
             fActiveRecord::assign($values, $old_values, $other_column, $other_file);
             if (!$existing_temp_file && $other_file) {
                 self::processImage($class, $other_column, $other_file);
             }
         }
     }
     // Process the file
     if (!$existing_temp_file && $file) {
         self::processImage($class, $column, $file);
     }
     return $file;
 }
Example #19
0
 public static function import_from_array_to_dashboard($input, $dashboard_id)
 {
     $result = true;
     if (!empty($input)) {
         $columns_to_ignore = array('graph_id', 'dashboard_id', 'lines');
         $new_graph = fActiveRecord::array_to_dbentry($input, __CLASS__, $columns_to_ignore);
         if ($new_graph !== NULL) {
             $new_graph->setDashboardId($dashboard_id);
             $new_graph->store();
             if (in_array('lines', array_keys($input))) {
                 $new_graph_id = $new_graph->getGraphId();
                 foreach ($input['lines'] as $line) {
                     $result_line = Line::import_from_array_to_graph($line, $new_graph_id);
                     $result = $result && $result_line;
                 }
             }
         } else {
             $result = false;
         }
     }
     return $result;
 }