/** * Sets a column to be a file upload column * * Configuring a column to be a file upload column means that whenever * fActiveRecord::populate() is called for an fActiveRecord object, any * appropriately named file uploads (via `$_FILES`) will be moved into * the directory for this column. * * Setting the column to a file path will cause the specified file to * be copied into the directory for this column. * * @param mixed $class The class name or instance of the class * @param string $column The column to set as a file upload column * @param fDirectory|string $directory The directory to upload/move to * @return void */ public static function configureFileUploadColumn($class, $column, $directory) { $class = fORM::getClass($class); $table = fORM::tablize($class); $schema = fORMSchema::retrieve($class); $data_type = $schema->getColumnInfo($table, $column, 'type'); $valid_data_types = array('varchar', 'char', 'text'); if (!in_array($data_type, $valid_data_types)) { throw new fProgrammerException('The column specified, %1$s, is a %2$s column. Must be one of %3$s to be set as a file upload column.', $column, $data_type, join(', ', $valid_data_types)); } if (!is_object($directory)) { $directory = new fDirectory($directory); } if (!$directory->isWritable()) { throw new fEnvironmentException('The file upload directory, %s, is not writable', $directory->getPath()); } $camelized_column = fGrammar::camelize($column, TRUE); fORM::registerActiveRecordMethod($class, 'upload' . $camelized_column, self::upload); fORM::registerActiveRecordMethod($class, 'set' . $camelized_column, self::set); fORM::registerActiveRecordMethod($class, 'encode' . $camelized_column, self::encode); fORM::registerActiveRecordMethod($class, 'prepare' . $camelized_column, self::prepare); fORM::registerReflectCallback($class, self::reflect); fORM::registerInspectCallback($class, $column, self::inspect); fORM::registerReplicateCallback($class, $column, self::replicate); fORM::registerObjectifyCallback($class, $column, self::objectify); $only_once_hooks = array('post-begin::delete()' => self::begin, 'pre-commit::delete()' => self::delete, 'post-commit::delete()' => self::commit, 'post-rollback::delete()' => self::rollback, 'post::populate()' => self::populate, 'post-begin::store()' => self::begin, 'post-validate::store()' => self::moveFromTemp, 'pre-commit::store()' => self::deleteOld, 'post-commit::store()' => self::commit, 'post-rollback::store()' => self::rollback, 'post::validate()' => self::validate); foreach ($only_once_hooks as $hook => $callback) { if (!fORM::checkHookCallback($class, $hook, $callback)) { fORM::registerHookCallback($class, $hook, $callback); } } if (empty(self::$file_upload_columns[$class])) { self::$file_upload_columns[$class] = array(); } self::$file_upload_columns[$class][$column] = $directory; }
/** * Sets a column to be formatted as an fMoney object * * @param mixed $class The class name or instance of the class to set the column format * @param string $column The column to format as an fMoney object * @param string $currency_column If specified, this column will store the currency of the fMoney object * @return void */ public static function configureMoneyColumn($class, $column, $currency_column = NULL) { $class = fORM::getClass($class); $table = fORM::tablize($class); $schema = fORMSchema::retrieve($class); $data_type = $schema->getColumnInfo($table, $column, 'type'); $valid_data_types = array('float'); if (!in_array($data_type, $valid_data_types)) { throw new fProgrammerException('The column specified, %1$s, is a %2$s column. Must be %3$s to be set as a money column.', $column, $data_type, join(', ', $valid_data_types)); } if ($currency_column !== NULL) { $currency_column_data_type = $schema->getColumnInfo($table, $currency_column, 'type'); $valid_currency_column_data_types = array('varchar', 'char', 'text'); if (!in_array($currency_column_data_type, $valid_currency_column_data_types)) { throw new fProgrammerException('The currency column specified, %1$s, is a %2$s column. Must be %3$s to be set as a currency column.', $currency_column, $currency_column_data_type, join(', ', $valid_currency_column_data_types)); } } $camelized_column = fGrammar::camelize($column, TRUE); fORM::registerActiveRecordMethod($class, 'encode' . $camelized_column, self::encodeMoneyColumn); fORM::registerActiveRecordMethod($class, 'prepare' . $camelized_column, self::prepareMoneyColumn); if (!fORM::checkHookCallback($class, 'post::validate()', self::validateMoneyColumns)) { fORM::registerHookCallback($class, 'post::validate()', self::validateMoneyColumns); } fORM::registerReflectCallback($class, self::reflect); fORM::registerInspectCallback($class, $column, self::inspect); $value = FALSE; if ($currency_column) { $value = $currency_column; if (empty(self::$currency_columns[$class])) { self::$currency_columns[$class] = array(); } self::$currency_columns[$class][$currency_column] = $column; if (!fORM::checkHookCallback($class, 'post::loadFromResult()', self::makeMoneyObjects)) { fORM::registerHookCallback($class, 'post::loadFromResult()', self::makeMoneyObjects); } if (!fORM::checkHookCallback($class, 'pre::validate()', self::makeMoneyObjects)) { fORM::registerHookCallback($class, 'pre::validate()', self::makeMoneyObjects); } fORM::registerActiveRecordMethod($class, 'set' . $camelized_column, self::setMoneyColumn); fORM::registerActiveRecordMethod($class, 'set' . fGrammar::camelize($currency_column, TRUE), self::setCurrencyColumn); } else { fORM::registerObjectifyCallback($class, $column, self::objectifyMoney); } if (empty(self::$money_columns[$class])) { self::$money_columns[$class] = array(); } self::$money_columns[$class][$column] = $value; }
/** * Restricts a column to having only a value from the list of valid values * * Please note that `NULL` values are always allowed, even if not listed in * the `$valid_values` array, if the column is not set as `NOT NULL`. * * This functionality can also be accomplished by added a `CHECK` constraint * on the column in the database, or using a MySQL `ENUM` data type. * * @param mixed $class The class name or instance of the class this rule applies to * @param string $column The column to validate * @param array $valid_values The valid values to check - `NULL` values are always allows if the column is not set to `NOT NULL` * @return void */ public static function addValidValuesRule($class, $column, $valid_values) { $class = fORM::getClass($class); if (!isset(self::$valid_values_rules[$class])) { self::$valid_values_rules[$class] = array(); } settype($valid_values, 'array'); self::$valid_values_rules[$class][$column] = $valid_values; fORM::registerInspectCallback($class, $column, self::inspect); }
/** * Sets a timestamp column to store the timezone in another column * * Since not all databases support timezone information in timestamp * columns, this method allows storing the timezone in another columns. * When the timestamp and timezone are retrieved from the database, they * will be automatically combined together into an fTimestamp object. * * @param mixed $class The class name or instance of the class to set the column format * @param string $timestamp_column The timestamp column to store the timezone for * @param string $timezone_column The column to store the timezone in * @return void */ public static function configureTimezoneColumn($class, $timestamp_column, $timezone_column) { $class = fORM::getClass($class); $table = fORM::tablize($class); $schema = fORMSchema::retrieve($class); $timestamp_data_type = $schema->getColumnInfo($table, $timestamp_column, 'type'); if ($timestamp_data_type != 'timestamp') { throw new fProgrammerException('The timestamp column specified, %1$s, is a %2$s column. Must be a %3$s to have a related timezone column.', $timestamp_column, $data_type, 'timestamp'); } $timezone_column_data_type = $schema->getColumnInfo($table, $timezone_column, 'type'); $valid_timezone_column_data_types = array('varchar', 'char', 'text'); if (!in_array($timezone_column_data_type, $valid_timezone_column_data_types)) { throw new fProgrammerException('The timezone column specified, %1$s, is a %2$s column. Must be %3$s to be set as a timezone column.', $timezone_column, $timezone_column_data_type, join(', ', $valid_timezone_column_data_types)); } if (!fORM::checkHookCallback($class, 'post::validate()', self::validateTimezoneColumns)) { fORM::registerHookCallback($class, 'post::validate()', self::validateTimezoneColumns); } if (!fORM::checkHookCallback($class, 'post::loadFromResult()', self::makeTimestampObjects)) { fORM::registerHookCallback($class, 'post::loadFromResult()', self::makeTimestampObjects); } if (!fORM::checkHookCallback($class, 'pre::validate()', self::makeTimestampObjects)) { fORM::registerHookCallback($class, 'pre::validate()', self::makeTimestampObjects); } fORM::registerInspectCallback($class, $timezone_column, self::inspect); fORM::registerActiveRecordMethod($class, 'set' . fGrammar::camelize($timestamp_column, TRUE), self::setTimestampColumn); fORM::registerActiveRecordMethod($class, 'set' . fGrammar::camelize($timezone_column, TRUE), self::setTimezoneColumn); if (empty(self::$timestamp_columns[$class])) { self::$timestamp_columns[$class] = array(); } self::$timestamp_columns[$class][$timestamp_column] = $timezone_column; if (empty(self::$timezone_columns[$class])) { self::$timezone_columns[$class] = array(); } self::$timezone_columns[$class][$timezone_column] = $timestamp_column; }
/** * Sets a column to be a random string column - a random string will be generated when the record is saved * * @param mixed $class The class name or instance of the class * @param string $column The column to set as a random column * @param string $type The type of random string, must be one of: `'alphanumeric'`, `'alpha'`, `'numeric'`, `'hexadecimal'` * @param integer $length The length of the random string * @return void */ public static function configureRandomColumn($class, $column, $type, $length) { $class = fORM::getClass($class); $table = fORM::tablize($class); $schema = fORMSchema::retrieve($class); $data_type = $schema->getColumnInfo($table, $column, 'type'); $valid_data_types = array('varchar', 'char', 'text'); if (!in_array($data_type, $valid_data_types)) { throw new fProgrammerException('The column specified, %1$s, is a %2$s column. Must be one of %3$s to be set as a random string column.', $column, $data_type, join(', ', $valid_data_types)); } $valid_types = array('alphanumeric', 'alpha', 'numeric', 'hexadecimal'); if (!in_array($type, $valid_types)) { throw new fProgrammerException('The type specified, %1$s, is an invalid type. Must be one of: %2$s.', $type, join(', ', $valid_types)); } if (!is_numeric($length) || $length < 1) { throw new fProgrammerException('The length specified, %s, needs to be an integer greater than zero.', $length); } fORM::registerActiveRecordMethod($class, 'generate' . fGrammar::camelize($column, TRUE), self::generate); if (!fORM::checkHookCallback($class, 'pre::validate()', self::setRandomStrings)) { fORM::registerHookCallback($class, 'pre::validate()', self::setRandomStrings); } fORM::registerInspectCallback($class, $column, self::inspect); if (empty(self::$random_columns[$class])) { self::$random_columns[$class] = array(); } self::$random_columns[$class][$column] = array('type' => $type, 'length' => (int) $length); }