/** * Turns a monetary value into an fMoney object with a currency specified by another column * * @internal * * @param array &$values The current values * @param array &$old_values The old values * @param string $value_column The column holding the value * @param string $currency_column The column holding the currency code * @return void */ public static function objectifyMoneyWithCurrency(&$values, &$old_values, $value_column, $currency_column) { if (!is_string($values[$value_column]) && !is_numeric($values[$value_column]) && !is_object($values[$value_column]) || !strlen(trim($values[$value_column]))) { return; } try { $value = $values[$value_column]; if ($value instanceof fMoney) { $value = $value->__toString(); } $currency = $values[$currency_column]; if (!$currency && $currency !== '0' && $currency !== 0) { $currency = NULL; } $value = new fMoney($value, $currency); if (fActiveRecord::hasOld($old_values, $currency_column) && !fActiveRecord::hasOld($old_values, $value_column)) { fActiveRecord::assign($values, $old_values, $value_column, $value); } else { $values[$value_column] = $value; } if ($values[$currency_column] === NULL) { fActiveRecord::assign($values, $old_values, $currency_column, $value->getCurrency()); } // If there was some error creating the money object, we just leave all values alone } catch (fExpectedException $e) { } }
/** * Turns a timestamp value into an fTimestamp object with a timezone specified by another column * * @internal * * @param array &$values The current values * @param array &$old_values The old values * @param string $timestamp_column The column holding the timestamp * @param string $timezone_column The column holding the timezone * @return void */ public static function objectifyTimestampWithTimezone(&$values, &$old_values, $timestamp_column, $timezone_column) { if (!is_string($values[$timestamp_column]) && !is_object($values[$timestamp_column]) && !is_numeric($values[$timestamp_column]) || !strlen(trim($values[$timestamp_column]))) { return; } try { $value = $values[$timestamp_column]; if ($value instanceof fTimestamp) { $value = $value->__toString(); } $timezone = $values[$timezone_column]; if (!$timezone && $timezone !== '0' && $timezone !== 0) { $timezone = NULL; } $value = new fTimestamp($value, $timezone); if (fActiveRecord::hasOld($old_values, $timezone_column) && !fActiveRecord::hasOld($old_values, $timestamp_column)) { fActiveRecord::assign($values, $old_values, $timestamp_column, $value); } else { $values[$timestamp_column] = $value; } if ($values[$timezone_column] === NULL) { fActiveRecord::assign($values, $old_values, $timezone_column, $value->format('e')); } // If there was some error creating the timestamp object, we just leave all values alone } catch (fExpectedException $e) { } }
/** * Makes sure a record with the same primary keys is not already in the database * * @param fSchema $schema The schema object for the object * @param fActiveRecord $object The instance of the class to check * @param array &$values An associative array of all values going into the row (needs all for multi-field unique constraint checking) * @param array &$old_values The old values for the record * @return array A single element associative array with the key being the primary keys joined by ,s and the value being the error message */ private static function checkPrimaryKeys($schema, $object, &$values, &$old_values) { $class = get_class($object); $table = fORM::tablize($class); $db = fORMDatabase::retrieve($class, 'read'); $pk_columns = $schema->getKeys($table, 'primary'); $columns = array(); $found_value = FALSE; foreach ($pk_columns as $pk_column) { $columns[] = fORM::getColumnName($class, $pk_column); if ($values[$pk_column]) { $found_value = TRUE; } } if (!$found_value) { return; } $different = FALSE; foreach ($pk_columns as $pk_column) { if (!fActiveRecord::hasOld($old_values, $pk_column)) { continue; } $old_value = fActiveRecord::retrieveOld($old_values, $pk_column); $value = $values[$pk_column]; if (self::isCaseInsensitive($class, $pk_column) && self::stringlike($value) && self::stringlike($old_value)) { if (fUTF8::lower($value) != fUTF8::lower($old_value)) { $different = TRUE; } } elseif ($old_value != $value) { $different = TRUE; } } if (!$different) { return; } try { $params = array("SELECT %r FROM %r WHERE ", $pk_columns, $table); $column_info = $schema->getColumnInfo($table); $conditions = array(); foreach ($pk_columns as $pk_column) { $value = $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']; } if (self::isCaseInsensitive($class, $pk_column) && self::stringlike($value)) { $condition = fORMDatabase::makeCondition($schema, $table, $pk_column, '=', $value); $conditions[] = str_replace('%r', 'LOWER(%r)', $condition); $params[] = $pk_column; $params[] = fUTF8::lower($value); } else { $conditions[] = fORMDatabase::makeCondition($schema, $table, $pk_column, '=', $value); $params[] = $pk_column; $params[] = $value; } } $params[0] .= join(' AND ', $conditions); $result = call_user_func_array($db->translatedQuery, $params); $result->tossIfNoRows(); return array(join(',', $pk_columns) => self::compose('Another %1$s with the same %2$s already exists', fORM::getRecordName($class), fGrammar::joinArray($columns, 'and'))); } catch (fNoRowsException $e) { } }
/** * Checks to see if the values specified are part of a record that is new to its order set * * @param string $ordering_column The column being ordered by * @param array $other_columns The other columns in the multi-column unique constraint * @param array &$values The values of the record * @param array &$old_values The old values of the record * @return boolean If the record is part of a new ordering set */ private static function isInNewSet($ordering_column, $other_columns, &$values, &$old_values) { $value_empty = !$values[$ordering_column]; $old_value_empty = !fActiveRecord::retrieveOld($old_values, $ordering_column, TRUE); $no_old_value_set = !fActiveRecord::hasOld($old_values, $ordering_column); // If the value appears to be new, the record must be new to the order if ($old_value_empty || $value_empty && $no_old_value_set) { return TRUE; } // If there aren't any other columns to check, there is // only a single order, so it must have already existed if (!$other_columns) { return FALSE; } // Check through each of the other columns to see if the set could have // changed because of a new value in one of those columns foreach ($other_columns as $other_column) { if (fActiveRecord::changed($values, $old_values, $other_column)) { return TRUE; } } // If none of the multi-column values changed, the record must be part // of the same set it was return FALSE; }
/** * 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()); } }
/** * Makes sure a record with the same primary keys is not already in the database * * @param fActiveRecord $object The instance of the class to check * @param array &$values An associative array of all values going into the row (needs all for multi-field unique constraint checking) * @param array &$old_values The old values for the record * @return string An error message */ private static function checkPrimaryKeys($object, &$values, &$old_values) { $class = get_class($object); $table = fORM::tablize($class); $primary_keys = fORMSchema::retrieve()->getKeys($table, 'primary'); $columns = array(); $found_value = FALSE; foreach ($primary_keys as $primary_key) { $columns[] = fORM::getColumnName($class, $primary_key); if ($values[$primary_key]) { $found_value = TRUE; } } if (!$found_value) { return; } $different = FALSE; foreach ($primary_keys as $primary_key) { if (!fActiveRecord::hasOld($old_values, $primary_key)) { continue; } $old_value = fActiveRecord::retrieveOld($old_values, $primary_key); $value = $values[$primary_key]; if (self::isCaseInsensitive($class, $primary_key) && self::stringlike($value) && self::stringlike($old_value)) { if (fUTF8::lower($value) != fUTF8::lower($old_value)) { $different = TRUE; } } elseif ($old_value != $value) { $different = TRUE; } } if (!$different) { return; } try { $sql = "SELECT " . join(', ', $primary_keys) . " FROM " . $table . " WHERE "; $conditions = array(); foreach ($primary_keys as $primary_key) { if (self::isCaseInsensitive($class, $primary_key) && self::stringlike($values[$primary_key])) { $conditions[] = 'LOWER(' . $primary_key . ')' . fORMDatabase::escapeBySchema($table, $primary_key, fUTF8::lower($values[$primary_key]), '='); } else { $conditions[] = $primary_key . fORMDatabase::escapeBySchema($table, $primary_key, $values[$primary_key], '='); } } $sql .= join(' AND ', $conditions); $result = fORMDatabase::retrieve()->translatedQuery($sql); $result->tossIfNoRows(); return self::compose('Another %1$s with the same %2$s already exists', fORM::getRecordName($class), fGrammar::joinArray($columns, 'and')); } catch (fNoRowsException $e) { } }