/** * 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; }
/** * Moves an uploaded file from the temp directory to a permanent location * * @throws fValidationException When `$directory` is somehow invalid or ::validate() thows an exception * * @param string|fDirectory $directory The directory to upload the file to * @param string $field The file upload field to get the file from * @param mixed $index If the field was an array file upload field, upload the file corresponding to this index * @return fFile|NULL An fFile (or fImage) object, or `NULL` if no file was uploaded */ public function move($directory, $field, $index = NULL) { if (!is_object($directory)) { $directory = new fDirectory($directory); } if (!$directory->isWritable()) { throw new fProgrammerException('The directory specified, %s, is not writable', $directory->getPath()); } if (!self::check($field)) { throw new fProgrammerException('The field specified, %s, does not appear to be a file upload field', $field); } $file_array = $this->extractFileUploadArray($field, $index); $error = $this->validateField($file_array); if ($error) { throw new fValidationException($error); } // This will only ever be true if the file is optional if ($file_array['name'] == '' || $file_array['tmp_name'] == '' || $file_array['size'] == 0) { return NULL; } $file_name = fFilesystem::makeURLSafe($file_array['name']); $file_name = $directory->getPath() . $file_name; if (!$this->enable_overwrite) { $file_name = fFilesystem::makeUniqueName($file_name); } if (!move_uploaded_file($file_array['tmp_name'], $file_name)) { throw new fEnvironmentException('There was an error moving the uploaded file'); } if (!chmod($file_name, 0644)) { throw new fEnvironmentException('Unable to change permissions on the uploaded file'); } return fFilesystem::createObject($file_name); }
/** * Moves the current directory into a different directory * * Please note that ::rename() will rename a directory in its current * parent directory or rename it into a different parent directory. * * If the current directory's name already exists in the new parent * directory and the overwrite flag is set to false, the name will be * changed to a unique name. * * This operation will be reverted if a filesystem transaction is in * progress and is later rolled back. * * @throws fValidationException When the new parent directory passed is not a directory, is not readable or is a sub-directory of this directory * * @param fDirectory|string $new_parent_directory The directory to move this directory into * @param boolean $overwrite If the current filename already exists in the new directory, `TRUE` will cause the file to be overwritten, `FALSE` will cause the new filename to change * @return fDirectory The directory object, to allow for method chaining */ public function move($new_parent_directory, $overwrite) { if (!$new_parent_directory instanceof fDirectory) { $new_parent_directory = new fDirectory($new_parent_directory); } if (strpos($new_parent_directory->getPath(), $this->getPath()) === 0) { throw new fValidationException('It is not possible to move a directory into one of its sub-directories'); } return $this->rename($new_parent_directory->getPath() . $this->getName(), $overwrite); }
/** * Sets the path to store session files in * * This method should always be called with a non-standard directory * whenever ::setLength() is called to ensure that another site on the * server does not garbage collect the session files for this site. * * Standard session directories usually include `/tmp` and `/var/tmp`. * * @param string|fDirectory $directory The directory to store session files in * @return void */ public static function setPath($directory) { if (self::$open || isset($_SESSION)) { throw new fProgrammerException('%1$s must be called before any of %2$s, %3$s, %4$s, %5$s, %6$s, %7$s or %8$s', __CLASS__ . '::setPath()', __CLASS__ . '::add()', __CLASS__ . '::clear()', __CLASS__ . '::enablePersistence()', __CLASS__ . '::get()', __CLASS__ . '::open()', __CLASS__ . '::set()', 'session_start()'); } if (!$directory instanceof fDirectory) { $directory = new fDirectory($directory); } if (!$directory->isWritable()) { throw new fEnvironmentException('The directory specified, %s, is not writable', $directory->getPath()); } session_save_path($directory->getPath()); }
/** * Moves the current file to a different directory * * Please note that ::rename() will rename a file in its directory or rename * it into a different directory. * * If the current file's filename already exists in the new directory and * the overwrite flag is set to false, the filename will be changed to a * unique name. * * This operation will be reverted if a filesystem transaction is in * progress and is later rolled back. * * @throws fValidationException When the directory passed is not a directory or is not readable * * @param fDirectory|string $new_directory The directory to move this file into * @param boolean $overwrite If the current filename already exists in the new directory, `TRUE` will cause the file to be overwritten, `FALSE` will cause the new filename to change * @return fFile The file object, to allow for method chaining */ public function move($new_directory, $overwrite) { if (!$new_directory instanceof fDirectory) { $new_directory = new fDirectory($new_directory); } return $this->rename($new_directory->getPath() . $this->getName(), $overwrite); }
/** * Moves an uploaded file from the temp directory to a permanent location * * @throws fValidationException When `$directory` is somehow invalid or ::validate() thows an exception * * @param string|fDirectory $directory The directory to upload the file to * @param string $field The file upload field to get the file from * @param integer $index If the field was an array file upload field, upload the file corresponding to this index * @return fFile An fFile (or fImage) object */ public function move($directory, $field, $index = NULL, $param_filename = NULL) { if (!is_object($directory)) { $directory = new fDirectory($directory); } if (!$directory->isWritable()) { throw new fProgrammerException('The directory specified, %s, is not writable', $directory->getPath()); } if (!self::check($field)) { throw new fProgrammerException('The field specified, %s, does not appear to be a file upload field', $field); } $file_array = $this->validate($field, $index); $file_name = fFilesystem::makeURLSafe($param_filename == NULL ? $file_array['name'] : $param_filename); $file_name = $directory->getPath() . $file_name; if (!$this->enable_overwrite) { $file_name = fFilesystem::makeUniqueName($file_name); } if (!move_uploaded_file($file_array['tmp_name'], $file_name)) { throw new fEnvironmentException('There was an error moving the uploaded file'); } if (!chmod($file_name, 0644)) { throw new fEnvironmentException('Unable to change permissions on the uploaded file'); } return fFilesystem::createObject($file_name); }
/** * Sets a custom directory to use for the ImageMagick temporary files * * @param string $temp_dir The directory to use for the ImageMagick temp dir * @return void */ public static function setImageMagickTempDir($temp_dir) { $temp_dir = new fDirectory($temp_dir); if (!$temp_dir->isWritable()) { throw new fEnvironmentException('The ImageMagick temp directory specified, %s, does not appear to be writable', $temp_dir->getPath()); } self::$imagemagick_temp_dir = $temp_dir->getPath(); }
public function testScanDirs() { $this->createScannableFiles(); $dir = new fDirectory('output/fDirectory_scan/'); $files = $dir->scanRecursive('#/$#'); $filenames = array(); foreach ($files as $file) { $filenames[] = str_replace($dir->getPath(), '', $file->getPath()); } $this->assertEquals(array('subdir' . DIRECTORY_SEPARATOR, 'subdir' . DIRECTORY_SEPARATOR . 'subsubdir' . DIRECTORY_SEPARATOR, 'subdir' . DIRECTORY_SEPARATOR . 'subsubdir' . DIRECTORY_SEPARATOR . 'subsubsubdir' . DIRECTORY_SEPARATOR, 'subdir' . DIRECTORY_SEPARATOR . 'subsubdir2' . DIRECTORY_SEPARATOR, 'subdir' . DIRECTORY_SEPARATOR . 'subsubdir3' . DIRECTORY_SEPARATOR), $filenames); }
/** * Creates a new file object with a copy of this file * * If no directory is specified, the file is created with a new name in * the current directory. If a new directory is specified, you must also * indicate if you wish to overwrite an existing file with the same name * in the new directory or create a unique name. * * This operation will be reverted by a filesystem transaction being rolled * back. * * @param string|fDirectory $new_directory The directory to duplicate the file into if different than the current directory * @param boolean $overwrite If a new directory is specified, this indicates if a file with the same name should be overwritten. * @return fFile The new fFile object */ public function duplicate($new_directory = NULL, $overwrite = NULL, $param_filename = NULL) { $this->tossIfException(); if ($new_directory === NULL) { $new_directory = $this->getDirectory(); } if (!is_object($new_directory)) { $new_directory = new fDirectory($new_directory); } $fname = $param_filename == NULL ? $this->getFilename() : $param_filename; $new_filename = $new_directory->getPath() . $fname; $check_dir_permissions = FALSE; if (file_exists($new_filename)) { if (!$overwrite) { $new_filename = fFilesystem::makeUniqueName($new_filename); $check_dir_permissions = TRUE; } elseif (!is_writable($new_filename)) { throw new fEnvironmentException('The new directory specified, %1$s, already contains a file with the name %2$s, but it is not writable', $new_directory->getPath(), $this->getFilename()); } } else { $check_dir_permissions = TRUE; } if ($check_dir_permissions) { if (!$new_directory->isWritable()) { throw new fEnvironmentException('The new directory specified, %s, is not writable', $new_directory); } } copy($this->getPath(), $new_filename); chmod($new_filename, fileperms($this->getPath())); $class = get_class($this); $file = new $class($new_filename); // Allow filesystem transactions if (fFilesystem::isInsideTransaction()) { fFilesystem::recordDuplicate($file); } return $file; }