'File Example', 'page callback' => 'file_example_intro', 'access callback' => TRUE, 'expanded' => TRUE, ); $items['examples/file_example/fileapi'] = array( 'title' => 'Use File API to read/write a file', 'page callback' => 'drupal_get_form', 'access arguments' => array('use file example'), 'page arguments' => array('file_example_readwrite'), ); $items['examples/file_example/access_session'] = array( 'page callback' => 'file_example_session_contents', 'access arguments' => array('use file example'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_permission(). */ function file_example_permission() { return array( 'use file example' => array( 'title' => t('Use the examples in the File Example module'), ), ); } /** * A simple introduction to the workings of this module. */ function file_example_intro() { $markup = t('The file example module provides a form and code to demonstrate the Drupal 7 file api. Experiment with the form, and then look at the submit handlers in the code to understand the file api.'); return array('#markup' => $markup); } /** * Form builder function. * * A simple form that allows creation of a file, managed or unmanaged. It * also allows reading/deleting a file and creation of a directory. */ function file_example_readwrite($form, &$form_state) { if (empty($_SESSION['file_example_default_file'])) { $_SESSION['file_example_default_file'] = 'session://drupal.txt'; } $default_file = $_SESSION['file_example_default_file']; if (empty($_SESSION['file_example_default_directory'])) { $_SESSION['file_example_default_directory'] = 'session://directory1'; } $default_directory = $_SESSION['file_example_default_directory']; $form['write_file'] = array( '#type' => 'fieldset', '#title' => t('Write to a file'), ); $form['write_file']['write_contents'] = array( '#type' => 'textfield', '#title' => t('Enter something you would like to write to a file') . ' ' . date('m'), '#default_value' => t('Put some text here or just use this text'), ); $form['write_file']['destination'] = array( '#type' => 'textfield', '#default_value' => $default_file, '#title' => t('Optional: Enter the streamwrapper saying where it should be written'), '#description' => t('This may be public://some_dir/test_file.txt or private://another_dir/some_file.txt, for example. If you include a directory, it must already exist. The default is "public://". Since this example supports session://, you can also use something like session://somefile.txt.'), ); $form['write_file']['managed_submit'] = array( '#type' => 'submit', '#value' => t('Write managed file'), '#submit' => array('file_example_managed_write_submit'), ); $form['write_file']['unmanaged_submit'] = array( '#type' => 'submit', '#value' => t('Write unmanaged file'), '#submit' => array('file_example_unmanaged_write_submit'), ); $form['write_file']['unmanaged_php'] = array( '#type' => 'submit', '#value' => t('Unmanaged using PHP'), '#submit' => array('file_example_unmanaged_php_submit'), ); $form['fileops'] = array( '#type' => 'fieldset', '#title' => t('Read from a file'), ); $form['fileops']['fileops_file'] = array( '#type' => 'textfield', '#default_value' => $default_file, '#title' => t('Enter the URI of a file'), '#description' => t('This must be a stream-type description like public://some_file.txt or http://drupal.org or private://another_file.txt or (for this example) session://yet_another_file.txt.'), ); $form['fileops']['read_submit'] = array( '#type' => 'submit', '#value' => t('Read the file and store it locally'), '#submit' => array('file_example_read_submit'), ); $form['fileops']['delete_submit'] = array( '#type' => 'submit', '#value' => t('Delete file'), '#submit' => array('file_example_delete_submit'), ); $form['fileops']['check_submit'] = array( '#type' => 'submit', '#value' => t('Check to see if file exists'), '#submit' => array('file_example_file_check_exists_submit'), ); $form['directory'] = array( '#type' => 'fieldset', '#title' => t('Create or prepare a directory'), ); $form['directory']['directory_name'] = array( '#type' => 'textfield', '#title' => t('Directory to create/prepare/delete'), '#default_value' => $default_directory, '#description' => t('This is a directory as in public://some/directory or private://another/dir.'), ); $form['directory']['create_directory'] = array( '#type' => 'submit', '#value' => t('Create directory'), '#submit' => array('file_example_create_directory_submit'), ); $form['directory']['delete_directory'] = array( '#type' => 'submit', '#value' => t('Delete directory'), '#submit' => array('file_example_delete_directory_submit'), ); $form['directory']['check_directory'] = array( '#type' => 'submit', '#value' => t('Check to see if directory exists'), '#submit' => array('file_example_check_directory_submit'), ); $form['debug'] = array( '#type' => 'fieldset', '#title' => t('Debugging'), ); $form['debug']['show_raw_session'] = array( '#type' => 'submit', '#value' => t('Show raw $_SESSION contents'), '#submit' => array('file_example_show_session_contents_submit'), ); return $form; } /** * Submit handler to write a managed file. * * The key functions used here are: * - file_save_data(), which takes a buffer and saves it to a named file and * also creates a tracking record in the database and returns a file object. * In this function we use FILE_EXISTS_RENAME (the default) as the argument, * which means that if there's an existing file, create a new non-colliding * filename and use it. * - file_create_url(), which converts a URI in the form public://junk.txt or * private://something/test.txt into a URL like * http://example.com/sites/default/files/junk.txt. */ function file_example_managed_write_submit($form, &$form_state) { $data = $form_state['values']['write_contents']; $uri = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; // Managed operations work with a file object. $file_object = file_save_data($data, $uri, FILE_EXISTS_RENAME); if (!empty($file_object)) { $url = file_create_url($file_object->uri); $_SESSION['file_example_default_file'] = $file_object->uri; drupal_set_message( t('Saved managed file: %file to destination %destination (accessible via !url, actual uri=@uri)', array( '%file' => print_r($file_object, TRUE), '%destination' => $uri, '@uri' => $file_object->uri, '!url' => l(t('this URL'), $url), ) ) ); } else { drupal_set_message(t('Failed to save the managed file'), 'error'); } } /** * Submit handler to write an unmanaged file. * * The key functions used here are: * - file_unmanaged_save_data(), which takes a buffer and saves it to a named * file, but does not create any kind of tracking record in the database. * This example uses FILE_EXISTS_REPLACE for the third argument, meaning * that if there's an existing file at this location, it should be replaced. * - file_create_url(), which converts a URI in the form public://junk.txt or * private://something/test.txt into a URL like * http://example.com/sites/default/files/junk.txt. */ function file_example_unmanaged_write_submit($form, &$form_state) { $data = $form_state['values']['write_contents']; $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; // With the unmanaged file we just get a filename back. $filename = file_unmanaged_save_data($data, $destination, FILE_EXISTS_REPLACE); if ($filename) { $url = file_create_url($filename); $_SESSION['file_example_default_file'] = $filename; drupal_set_message( t('Saved file as %filename (accessible via !url, uri=@uri)', array( '%filename' => $filename, '@uri' => $filename, '!url' => l(t('this URL'), $url), ) ) ); } else { drupal_set_message(t('Failed to save the file'), 'error'); } } /** * Submit handler to write an unmanaged file using plain PHP functions. * * The key functions used here are: * - file_unmanaged_save_data(), which takes a buffer and saves it to a named * file, but does not create any kind of tracking record in the database. * - file_create_url(), which converts a URI in the form public://junk.txt or * private://something/test.txt into a URL like * http://example.com/sites/default/files/junk.txt. * - drupal_tempnam() generates a temporary filename for use. */ function file_example_unmanaged_php_submit($form, &$form_state) { $data = $form_state['values']['write_contents']; $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; if (empty($destination)) { // If no destination has been provided, use a generated name. $destination = drupal_tempnam('public://', 'file'); } // With all traditional PHP functions we can use the stream wrapper notation // for a file as well. $fp = fopen($destination, 'w'); // To demonstrate the fact that everything is based on streams, we'll do // multiple 5-character writes to put this to the file. We could easily // (and far more conveniently) write it in a single statement with // fwrite($fp, $data). $length = strlen($data); $write_size = 5; for ($i = 0; $i < $length; $i += $write_size) { $result = fwrite($fp, substr($data, $i, $write_size)); if ($result === FALSE) { drupal_set_message(t('Failed writing to the file %file', array('%file' => $destination)), 'error'); fclose($fp); return; } } $url = file_create_url($destination); $_SESSION['file_example_default_file'] = $destination; drupal_set_message( t('Saved file as %filename (accessible via !url, uri=@uri)', array( '%filename' => $destination, '@uri' => $destination, '!url' => l(t('this URL'), $url), ) ) ); } /** * Submit handler for reading a stream wrapper. * * Drupal now has full support for PHP's stream wrappers, which means that * instead of the traditional use of all the file functions * ($fp = fopen("/tmp/some_file.txt");) far more sophisticated and generalized * (and extensible) things can be opened as if they were files. Drupal itself * provides the public:// and private:// schemes for handling public and * private files. PHP provides file:// (the default) and http://, so that a * URL can be read or written (as in a POST) as if it were a file. In addition, * new schemes can be provided for custom applications, as will be demonstrated * below. * * Here we take the stream wrapper provided in the form. We grab the * contents with file_get_contents(). Notice that's it's as simple as that: * file_get_contents("http://example.com") or * file_get_contents("public://somefile.txt") just works. Although it's * not necessary, we use file_unmanaged_save_data() to save this file locally * and then find a local URL for it by using file_create_url(). */ function file_example_read_submit($form, &$form_state) { $uri = $form_state['values']['fileops_file']; if (!is_file($uri)) { drupal_set_message(t('The file %uri does not exist', array('%uri' => $uri)), 'error'); return; } // Make a working filename to save this by stripping off the (possible) // file portion of the streamwrapper. If it's an evil file extension, // file_munge_filename() will neuter it. $filename = file_munge_filename(preg_replace('@^.*/@', '', $uri), '', TRUE); $buffer = file_get_contents($uri); if ($buffer) { $sourcename = file_unmanaged_save_data($buffer, 'public://' . $filename); if ($sourcename) { $url = file_create_url($sourcename); $_SESSION['file_example_default_file'] = $sourcename; drupal_set_message( t('The file was read and copied to %filename which is accessible at !url', array( '%filename' => $sourcename, '!url' => l($url, $url), ) ) ); } else { drupal_set_message(t('Failed to save the file')); } } else { // We failed to get the contents of the requested file. drupal_set_message(t('Failed to retrieve the file %file', array('%file' => $uri))); } } /** * Submit handler to delete a file. */ function file_example_delete_submit($form, &$form_state) { $uri = $form_state['values']['fileops_file']; // Since we don't know if the file is managed or not, look in the database // to see. Normally, code would be working with either managed or unmanaged // files, so this is not a typical situation. $file_object = file_example_get_managed_file($uri); // If a managed file, use file_delete(). if (!empty($file_object)) { $result = file_delete($file_object); if ($result !== TRUE) { drupal_set_message(t('Failed deleting managed file %uri. Result was %result', array( '%uri' => $uri, '%result' => print_r($result, TRUE), ) ), 'error'); } else { drupal_set_message(t('Successfully deleted managed file %uri', array('%uri' => $uri))); $_SESSION['file_example_default_file'] = $uri; } } // Else use file_unmanaged_delete(). else { $result = file_unmanaged_delete($uri); if ($result !== TRUE) { drupal_set_message(t('Failed deleting unmanaged file %uri', array('%uri' => $uri, 'error'))); } else { drupal_set_message(t('Successfully deleted unmanaged file %uri', array('%uri' => $uri))); $_SESSION['file_example_default_file'] = $uri; } } } /** * Submit handler to check existence of a file. */ function file_example_file_check_exists_submit($form, &$form_state) { $uri = $form_state['values']['fileops_file']; if (is_file($uri)) { drupal_set_message(t('The file %uri exists.', array('%uri' => $uri))); } else { drupal_set_message(t('The file %uri does not exist.', array('%uri' => $uri))); } } /** * Submit handler for directory creation. * * Here we create a directory and set proper permissions on it using * file_prepare_directory(). */ function file_example_create_directory_submit($form, &$form_state) { $directory = $form_state['values']['directory_name']; // The options passed to file_prepare_directory are a bitmask, so we can // specify either FILE_MODIFY_PERMISSIONS (set permissions on the directory), // FILE_CREATE_DIRECTORY, or both together: // FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY. // FILE_MODIFY_PERMISSIONS will set the permissions of the directory by // by default to 0755, or to the value of the variable 'file_chmod_directory'. if (!file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY)) { drupal_set_message(t('Failed to create %directory.', array('%directory' => $directory)), 'error'); } else { drupal_set_message(t('Directory %directory is ready for use.', array('%directory' => $directory))); $_SESSION['file_example_default_directory'] = $directory; } } /** * Submit handler for directory deletion. * * @see file_unmanaged_delete_recursive() */ function file_example_delete_directory_submit($form, &$form_state) { $directory = $form_state['values']['directory_name']; $result = file_unmanaged_delete_recursive($directory); if (!$result) { drupal_set_message(t('Failed to delete %directory.', array('%directory' => $directory)), 'error'); } else { drupal_set_message(t('Recursively deleted directory %directory.', array('%directory' => $directory))); $_SESSION['file_example_default_directory'] = $directory; } } /** * Submit handler to test directory existence. * * This actually just checks to see if the directory is writable * * @param array $form * FormAPI form. * @param array $form_state * FormAPI form state. */ function file_example_check_directory_submit($form, &$form_state) { $directory = $form_state['values']['directory_name']; $result = is_dir($directory); if (!$result) { drupal_set_message(t('Directory %directory does not exist.', array('%directory' => $directory))); } else { drupal_set_message(t('Directory %directory exists.', array('%directory' => $directory))); } } /** * Utility submit function to show the contents of $_SESSION. */ function file_example_show_session_contents_submit($form, &$form_state) { // If the devel module is installed, use it's nicer message format. if (module_exists('devel')) { dsm($_SESSION['file_example'], t('Entire $_SESSION["file_example"]')); } else { drupal_set_message('
' . print_r($_SESSION['file_example'], TRUE) . '
'); } } /** * Utility function to check for and return a managed file. * * In this demonstration code we don't necessarily know if a file is managed * or not, so often need to check to do the correct behavior. Normal code * would not have to do this, as it would be working with either managed or * unmanaged files. * * @param string $uri * The URI of the file, like public://test.txt. */ function file_example_get_managed_file($uri) { $fid = db_query('SELECT fid FROM {file_managed} WHERE uri = :uri', array(':uri' => $uri))->fetchField(); if (!empty($fid)) { $file_object = file_load($fid); return $file_object; } return FALSE; } /** * Implements hook_stream_wrappers(). * * hook_stream_wrappers() is Drupal's way of exposing the class that PHP will * use to provide a new stream wrapper class. In this case, we'll expose the * 'session' scheme, so a file reference like "session://example/example.txt" * is readable and writable as a location in the $_SESSION variable. * * @see FileExampleSessionStreamWrapper */ function file_example_stream_wrappers() { $wrappers = array( 'session' => array( 'name' => t('Example: $_SESSION variable storage'), 'class' => 'FileExampleSessionStreamWrapper', 'description' => t('Store files in the $_SESSION variable as an example.'), ), ); return $wrappers; } /** * Show the contents of a session file. * * This page callback function is called by the Menu API for the path * examples/file_example/access_session. Any extra path elements * beyond this are considered to be the session path. E.g.: * examples/file_example/access_session/foo/bar.txt would be the * equivalent of session://foo/bar.txt, which will map into * $_SESSION as keys: $_SESSION['foo']['bar.txt'] * * Menu API will pass in additional path elements as function arguments. You * can obtain these with func_get_args(). * * @return string * A message containing the contents of the session file. * * @see file_get_contents() */ function file_example_session_contents() { $path_components = func_get_args(); $session_path = 'session://' . implode('/', $path_components); $content = file_get_contents($session_path); if ($content !== FALSE) { return t('Contents of @path :', array('@path' => check_plain($session_path))) . ' ' . print_r($content, TRUE); } return t('Unable to load contents of: @path', array('@path' => check_plain($session_path))); } /** * @} End of "defgroup file_example". */