file_example.module

Tracking 7.x-1.x branch
  1. drupal
    1. 7 contributions/examples/file_example/file_example.module
    2. 8 contributions/examples/file_example/file_example.module

Examples demonstrating the Drupal File API (and Stream Wrappers).

Functions & methods

NameDescription
file_example_check_directory_submitSubmit handler to test directory existence. This actually just checks to see if the directory is writable
file_example_create_directory_submitSubmit handler for directory creation. Here we create a directory and set proper permissions on it using file_prepare_directory().
file_example_delete_directory_submitSubmit handler for directory deletion.
file_example_delete_submitSubmit handler to delete a file.
file_example_file_check_exists_submitSubmit handler to check existence of a file.
file_example_get_managed_fileUtility 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…
file_example_introA simple introduction to the workings of this module.
file_example_managed_write_submitSubmit handler to write a managed file.
file_example_menuImplements hook_menu() to set up the URLs (menu entries) for the file examples.
file_example_permissionImplements hook_permission().
file_example_readwriteForm builder function for the file example readwrite and directory creation example.
file_example_read_submitSubmit handler for reading a stream wrapper.
file_example_session_contentsShow the contents of a session file.
file_example_show_session_contents_submitUtility submit function to show the contents of $_SESSION.
file_example_stream_wrappersImplements 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…
file_example_unmanaged_php_submit
file_example_unmanaged_write_submit

File

View source
  1. <?php
  2. /**
  3. * @file
  4. * Examples demonstrating the Drupal File API (and Stream Wrappers).
  5. */
  6. /**
  7. * @defgroup file_example Example: Files
  8. * @ingroup examples
  9. * @{
  10. * Examples demonstrating the Drupal File API (and Stream Wrappers).
  11. *
  12. * The File Example module is a part of the Examples for Developers Project
  13. * and provides various Drupal File API Examples. You can download and
  14. * experiment with this code at the
  15. * @link http://drupal.org/project/examples Examples for Developers project page. @endlink
  16. *
  17. * See @link http://drupal.org/node/555118 Drupal File API @endlink for handbook
  18. * documentation on the File API and
  19. * @link file File summary on api.drupal.org @endlink for the function summary.
  20. */
  21. /**
  22. * Implements hook_menu() to set up the URLs (menu entries) for the
  23. * file examples.
  24. */
  25. function file_example_menu() {
  26. $items = array();
  27. $items['examples/file_example'] = array(
  28. 'title' => 'File Example',
  29. 'page callback' => 'file_example_intro',
  30. 'access callback' => TRUE,
  31. 'expanded' => TRUE,
  32. );
  33. $items['examples/file_example/fileapi'] = array(
  34. 'title' => 'Use File API to read/write a file',
  35. 'page callback' => 'drupal_get_form',
  36. 'access arguments' => array('use file example'),
  37. 'page arguments' => array('file_example_readwrite'),
  38. );
  39. $items['examples/file_example/access_session'] = array(
  40. 'page callback' => 'file_example_session_contents',
  41. 'access arguments' => array('use file example'),
  42. 'type' => MENU_CALLBACK,
  43. );
  44. return $items;
  45. }
  46. /**
  47. * Implements hook_permission().
  48. */
  49. function file_example_permission() {
  50. return array(
  51. 'use file example' => array(
  52. 'title' => t('Use the examples in the File Example module'),
  53. ),
  54. );
  55. }
  56. /**
  57. * A simple introduction to the workings of this module.
  58. */
  59. function file_example_intro() {
  60. $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.');
  61. return array('#markup' => $markup);
  62. }
  63. /**
  64. * Form builder function for the file example readwrite and directory creation
  65. * example.
  66. *
  67. * A simple form that allows creation of a file, managed or unmanaged. It
  68. * also allows reading/deleting a file and creation of a directory.
  69. */
  70. function file_example_readwrite($form, &$form_state) {
  71. if (empty($_SESSION['file_example_default_file'])) {
  72. $_SESSION['file_example_default_file'] = 'session://drupal.txt';
  73. }
  74. $default_file = $_SESSION['file_example_default_file'];
  75. if (empty($_SESSION['file_example_default_directory'])) {
  76. $_SESSION['file_example_default_directory'] = 'session://directory1';
  77. }
  78. $default_directory = $_SESSION['file_example_default_directory'];
  79. $form['write_file'] = array(
  80. '#type' => 'fieldset',
  81. '#title' => t('Write to a file'),
  82. );
  83. $form['write_file']['write_contents'] = array(
  84. '#type' => 'textfield',
  85. '#title' => t('Enter something you would like to write to a file') . ' ' . date('m'),
  86. '#default_value' => t('Put some text here or just use this text'),
  87. );
  88. $form['write_file']['destination'] = array(
  89. '#type' => 'textfield',
  90. '#default_value' => $default_file,
  91. '#title' => t('Optional: Enter the streamwrapper saying where it should be written'),
  92. '#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.'),
  93. );
  94. $form['write_file']['managed_submit'] = array(
  95. '#type' => 'submit',
  96. '#value' => t('Write managed file'),
  97. '#submit' => array('file_example_managed_write_submit'),
  98. );
  99. $form['write_file']['unmanaged_submit'] = array(
  100. '#type' => 'submit',
  101. '#value' => t('Write unmanaged file'),
  102. '#submit' => array('file_example_unmanaged_write_submit'),
  103. );
  104. $form['write_file']['unmanaged_php'] = array(
  105. '#type' => 'submit',
  106. '#value' => t('Unmanaged using PHP'),
  107. '#submit' => array('file_example_unmanaged_php_submit'),
  108. );
  109. $form['fileops'] = array(
  110. '#type' => 'fieldset',
  111. '#title' => t('Read from a file'),
  112. );
  113. $form['fileops']['fileops_file'] = array(
  114. '#type' => 'textfield',
  115. '#default_value' => $default_file,
  116. '#title' => t('Enter the URI of a file'),
  117. '#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.'),
  118. );
  119. $form['fileops']['read_submit'] = array(
  120. '#type' => 'submit',
  121. '#value' => t('Read the file and store it locally'),
  122. '#submit' => array('file_example_read_submit'),
  123. );
  124. $form['fileops']['delete_submit'] = array(
  125. '#type' => 'submit',
  126. '#value' => t('Delete file'),
  127. '#submit' => array('file_example_delete_submit'),
  128. );
  129. $form['fileops']['check_submit'] = array(
  130. '#type' => 'submit',
  131. '#value' => t('Check to see if file exists'),
  132. '#submit' => array('file_example_file_check_exists_submit'),
  133. );
  134. $form['directory'] = array(
  135. '#type' => 'fieldset',
  136. '#title' => t('Create or prepare a directory'),
  137. );
  138. $form['directory']['directory_name'] = array(
  139. '#type' => 'textfield',
  140. '#title' => t('Directory to create/prepare/delete'),
  141. '#default_value' => $default_directory,
  142. '#description' => t('This is a directory as in public://some/directory or private://another/dir.'),
  143. );
  144. $form['directory']['create_directory'] = array(
  145. '#type' => 'submit',
  146. '#value' => t('Create directory'),
  147. '#submit' => array('file_example_create_directory_submit'),
  148. );
  149. $form['directory']['delete_directory'] = array(
  150. '#type' => 'submit',
  151. '#value' => t('Delete directory'),
  152. '#submit' => array('file_example_delete_directory_submit'),
  153. );
  154. $form['directory']['check_directory'] = array(
  155. '#type' => 'submit',
  156. '#value' => t('Check to see if directory exists'),
  157. '#submit' => array('file_example_check_directory_submit'),
  158. );
  159. $form['debug'] = array(
  160. '#type' => 'fieldset',
  161. '#title' => t('Debugging'),
  162. );
  163. $form['debug']['show_raw_session'] = array(
  164. '#type' => 'submit',
  165. '#value' => t('Show raw $_SESSION contents'),
  166. '#submit' => array('file_example_show_session_contents_submit'),
  167. );
  168. return $form;
  169. }
  170. /**
  171. * Submit handler to write a managed file.
  172. *
  173. * The key functions used here are:
  174. * - file_save_data(), which takes a buffer and saves it to a named file and
  175. * also creates a tracking record in the database and returns a file object.
  176. * In this function we use FILE_EXISTS_RENAME (the default) as the argument,
  177. * which means that if there's an existing file, create a new non-colliding
  178. * filename and use it.
  179. * - file_create_url(), which converts a URI in the form public://junk.txt or
  180. * private://something/test.txt into a URL like
  181. * http://example.com/sites/default/files/junk.txt.
  182. */
  183. function file_example_managed_write_submit($form, &$form_state) {
  184. $data = $form_state['values']['write_contents'];
  185. $uri = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL;
  186. // Managed operations work with a file object.
  187. $file_object = file_save_data($data, $uri, FILE_EXISTS_RENAME);
  188. if (!empty($file_object)) {
  189. $url = file_create_url($file_object->uri);
  190. $_SESSION['file_example_default_file'] = $file_object->uri;
  191. drupal_set_message(t('Saved managed file: %file to destination %destination (accessible via !url, actual uri=<span id="uri">@uri</span>)', array('%file' => print_r($file_object, TRUE), '%destination' => $uri, '@uri' => $file_object->uri, '!url' => l(t('this URL'), $url))));
  192. }
  193. else {
  194. drupal_set_message(t('Failed to save the managed file'), 'error');
  195. }
  196. }
  197. /**
  198. * Submit handler to write an unmanaged file.
  199. *
  200. * The key functions used here are:
  201. * - file_unmanaged_save_data(), which takes a buffer and saves it to a named
  202. * file, but does not create any kind of tracking record in the database.
  203. * This example uses FILE_EXISTS_REPLACE for the third argument, meaning
  204. * that if there's an existing file at this location, it should be replaced.
  205. * - file_create_url(), which converts a URI in the form public://junk.txt or
  206. * private://something/test.txt into a URL like
  207. * http://example.com/sites/default/files/junk.txt.
  208. */
  209. function file_example_unmanaged_write_submit($form, &$form_state) {
  210. $data = $form_state['values']['write_contents'];
  211. $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL;
  212. // With the unmanaged file we just get a filename back.
  213. $filename = file_unmanaged_save_data($data, $destination, FILE_EXISTS_REPLACE);
  214. if ($filename) {
  215. $url = file_create_url($filename);
  216. $_SESSION['file_example_default_file'] = $filename;
  217. drupal_set_message(t('Saved file as %filename (accessible via !url, uri=<span id="uri">@uri</span>)', array('%filename' => $filename, '@uri' => $filename, '!url' => l(t('this URL'), $url))));
  218. }
  219. else {
  220. drupal_set_message(t('Failed to save the file'), 'error');
  221. }
  222. }
  223. /**
  224. * Submit handler to write an unmanaged file using plain PHP functions.
  225. *
  226. * The key functions used here are:
  227. * - file_unmanaged_save_data(), which takes a buffer and saves it to a named
  228. * file, but does not create any kind of tracking record in the database.
  229. * - file_create_url(), which converts a URI in the form public://junk.txt or
  230. * private://something/test.txt into a URL like
  231. * http://example.com/sites/default/files/junk.txt.
  232. * - drupal_tempnam() generates a temporary filename for use.
  233. */
  234. function file_example_unmanaged_php_submit($form, &$form_state) {
  235. $data = $form_state['values']['write_contents'];
  236. $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL;
  237. if (empty($destination)) {
  238. // If no destination has been provided, use a generated name.
  239. $destination = drupal_tempnam('public://', 'file');
  240. }
  241. // With all traditional PHP functions we can use the stream wrapper notation
  242. // for a file as well.
  243. $fp = fopen($destination, 'w');
  244. // To demonstrate the fact that everything is based on streams, we'll do
  245. // multiple 5-character writes to put this to the file. We could easily
  246. // (and far more conveniently) write it in a single statement with
  247. // fwrite($fp, $data).
  248. $length = strlen($data);
  249. $write_size = 5;
  250. for ($i = 0; $i < $length; $i += $write_size) {
  251. $result = fwrite($fp, substr($data, $i, $write_size));
  252. if ($result === FALSE) {
  253. drupal_set_message(t('Failed writing to the file %file', array('%file' => $destination)), 'error');
  254. fclose($fp);
  255. return;
  256. }
  257. }
  258. $url = file_create_url($destination);
  259. $_SESSION['file_example_default_file'] = $destination;
  260. drupal_set_message(t('Saved file as %filename (accessible via !url, uri=<span id="uri">@uri</span>)', array('%filename' => $destination, '@uri' => $destination, '!url' => l(t('this URL'), $url))));
  261. }
  262. /**
  263. * Submit handler for reading a stream wrapper.
  264. *
  265. * Drupal now has full support for PHP's stream wrappers, which means that
  266. * instead of the traditional use of all the file functions
  267. * ($fp = fopen("/tmp/some_file.txt");) far more sophisticated and generalized
  268. * (and extensible) things can be opened as if they were files. Drupal itself
  269. * provides the public:// and private:// schemes for handling public and
  270. * private files. PHP provides file:// (the default) and http://, so that a
  271. * URL can be read or written (as in a POST) as if it were a file. In addition,
  272. * new schemes can be provided for custom applications, as will be demonstrated
  273. * below.
  274. *
  275. * Here we take the stream wrapper provided in the form. We grab the
  276. * contents with file_get_contents(). Notice that's it's as simple as that:
  277. * file_get_contents("http://example.com") or
  278. * file_get_contents("public://somefile.txt") just works. Although it's
  279. * not necessary, we use file_unmanaged_save_data() to save this file locally
  280. * and then find a local URL for it by using file_create_url().
  281. */
  282. function file_example_read_submit($form, &$form_state) {
  283. $uri = $form_state['values']['fileops_file'];
  284. if (!is_file($uri)) {
  285. drupal_set_message(t('The file %uri does not exist', array('%uri' => $uri)), 'error');
  286. return;
  287. }
  288. // Make a working filename to save this by stripping off the (possible)
  289. // file portion of the streamwrapper. If it's an evil file extension,
  290. // file_munge_filename() will neuter it.
  291. $filename = file_munge_filename(preg_replace('@^.*/@', '', $uri), '', TRUE);
  292. $buffer = file_get_contents($uri);
  293. if ($buffer) {
  294. $sourcename = file_unmanaged_save_data($buffer, 'public://' . $filename);
  295. if ($sourcename) {
  296. $url = file_create_url($sourcename);
  297. $_SESSION['file_example_default_file'] = $sourcename;
  298. drupal_set_message(t('The file was read and copied to %filename which is accessible at !url', array('%filename' => $sourcename, '!url' => l($url, $url))));
  299. }
  300. else {
  301. drupal_set_message(t('Failed to save the file'));
  302. }
  303. }
  304. else { // We failed to get the contents of the requested file
  305. drupal_set_message(t('Failed to retrieve the file %file', array('%file' => $uri)));
  306. }
  307. }
  308. /**
  309. * Submit handler to delete a file.
  310. */
  311. function file_example_delete_submit($form, &$form_state) {
  312. $uri = $form_state['values']['fileops_file'];
  313. // Since we don't know if the file is managed or not, look in the database
  314. // to see. Normally, code would be working with either managed or unmanaged
  315. // files, so this is not a typical situation.
  316. $file_object = file_example_get_managed_file($uri);
  317. // If a managed file, use file_delete().
  318. if (!empty($file_object)) {
  319. $result = file_delete($file_object);
  320. if ($result !== TRUE) {
  321. drupal_set_message(t('Failed deleting managed file %uri. Result was %result', array('%uri' => $uri, '%result' => print_r($result, TRUE))), 'error');
  322. }
  323. else {
  324. drupal_set_message(t('Successfully deleted managed file %uri', array('%uri' => $uri)));
  325. $_SESSION['file_example_default_file'] = $uri;
  326. }
  327. }
  328. // else use file_unmanaged_delete().
  329. else {
  330. $result = file_unmanaged_delete($uri);
  331. if ($result !== TRUE) {
  332. drupal_set_message(t('Failed deleting unmanaged file %uri', array('%uri' => $uri, 'error')));
  333. }
  334. else {
  335. drupal_set_message(t('Successfully deleted unmanaged file %uri', array('%uri' => $uri)));
  336. $_SESSION['file_example_default_file'] = $uri;
  337. }
  338. }
  339. }
  340. /**
  341. * Submit handler to check existence of a file.
  342. */
  343. function file_example_file_check_exists_submit($form, &$form_state) {
  344. $uri = $form_state['values']['fileops_file'];
  345. if (is_file($uri)) {
  346. drupal_set_message(t('The file %uri exists.', array('%uri' => $uri)));
  347. }
  348. else {
  349. drupal_set_message(t('The file %uri does not exist.', array('%uri' => $uri)));
  350. }
  351. }
  352. /**
  353. * Submit handler for directory creation.
  354. * Here we create a directory and set proper permissions on it using
  355. * file_prepare_directory().
  356. */
  357. function file_example_create_directory_submit($form, &$form_state) {
  358. $directory = $form_state['values']['directory_name'];
  359. // The options passed to file_prepare_directory are a bitmask, so we can
  360. // specify either FILE_MODIFY_PERMISSIONS (set permissions on the directory),
  361. // FILE_CREATE_DIRECTORY, or both together:
  362. // FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY.
  363. // FILE_MODIFY_PERMISSIONS will set the permissions of the directory by
  364. // by default to 0755, or to the value of the variable 'file_chmod_directory'.
  365. if (!file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY)) {
  366. drupal_set_message(t('Failed to create %directory.', array('%directory' => $directory)), 'error');
  367. }
  368. else {
  369. $result = is_dir($directory);
  370. drupal_set_message(t('Directory %directory is ready for use.', array('%directory' => $directory)));
  371. $_SESSION['file_example_default_directory'] = $directory;
  372. }
  373. }
  374. /**
  375. * Submit handler for directory deletion.
  376. *
  377. * @see file_unmanaged_delete_recursive()
  378. *
  379. */
  380. function file_example_delete_directory_submit($form, &$form_state) {
  381. $directory = $form_state['values']['directory_name'];
  382. $result = file_unmanaged_delete_recursive($directory);
  383. if (!$result) {
  384. drupal_set_message(t('Failed to delete %directory.', array('%directory' => $directory)), 'error');
  385. }
  386. else {
  387. drupal_set_message(t('Recursively deleted directory %directory.', array('%directory' => $directory)));
  388. $_SESSION['file_example_default_directory'] = $directory;
  389. }
  390. }
  391. /**
  392. * Submit handler to test directory existence.
  393. * This actually just checks to see if the directory is writable
  394. *
  395. * @param $form
  396. * @param $form_state
  397. */
  398. function file_example_check_directory_submit($form, &$form_state) {
  399. $directory = $form_state['values']['directory_name'];
  400. $result = is_dir($directory);
  401. if (!$result) {
  402. drupal_set_message(t('Directory %directory does not exist.', array('%directory' => $directory)));
  403. }
  404. else {
  405. drupal_set_message(t('Directory %directory exists.', array('%directory' => $directory)));
  406. }
  407. }
  408. /**
  409. * Utility submit function to show the contents of $_SESSION.
  410. */
  411. function file_example_show_session_contents_submit($form, &$form_state) {
  412. // If the devel module is installed, use it's nicer message format.
  413. if (module_exists('devel')) {
  414. dsm($_SESSION['file_example'], t('Entire $_SESSION["file_example"]'));
  415. }
  416. else {
  417. drupal_set_message('<pre>' . print_r($_SESSION['file_example'], TRUE) . '</pre>');
  418. }
  419. }
  420. /**
  421. * Utility function to check for and return a managed file.
  422. * In this demonstration code we don't necessarily know if a file is managed
  423. * or not, so often need to check to do the correct behavior. Normal code
  424. * would not have to do this, as it would be working with either managed or
  425. * unmanaged files.
  426. *
  427. * @param $uri
  428. * The URI of the file, like public://test.txt.
  429. */
  430. function file_example_get_managed_file($uri) {
  431. $fid = db_query('SELECT fid FROM {file_managed} WHERE uri = :uri', array(':uri' => $uri))->fetchField();
  432. if (!empty($fid)) {
  433. $file_object = file_load($fid);
  434. return $file_object;
  435. }
  436. return FALSE;
  437. }
  438. /**
  439. * Implements hook_stream_wrappers().
  440. * hook_stream_wrappers() is Drupal's way of exposing the class that PHP will
  441. * use to provide a new stream wrapper class. In this case, we'll expose the
  442. * 'session' scheme, so a file reference like "session://example/example.txt"
  443. * is readable and writable as a location in the $_SESSION variable.
  444. *
  445. * @see FileExampleSessionStreamWrapper
  446. */
  447. function file_example_stream_wrappers() {
  448. $wrappers = array(
  449. 'session' => array(
  450. 'name' => t('Example: $_SESSION variable storage'),
  451. 'class' => 'FileExampleSessionStreamWrapper',
  452. 'description' => t('Store files in the $_SESSION variable as an example.'),
  453. ),
  454. );
  455. return $wrappers;
  456. }
  457. /**
  458. * Show the contents of a session file.
  459. *
  460. * This page callback function is called by the Menu API for the path
  461. * examples/file_example/access_session. Any extra path elements
  462. * beyond this are considered to be the session path. E.g.:
  463. * examples/file_example/access_session/foo/bar.txt would be the
  464. * equivalent of session://foo/bar.txt, which will map into
  465. * $_SESSION as keys: $_SESSION['foo']['bar.txt']
  466. *
  467. * @param $path-elements
  468. * The elements of the path will come from Menu API as the
  469. * function arguments. See explanation above.
  470. *
  471. * @return A message containing the contents of the session file.
  472. *
  473. * @see file_get_contents()
  474. */
  475. function file_example_session_contents() {
  476. $path_components = func_get_args();
  477. $session_path = 'session://' . join('/', $path_components);
  478. $content = file_get_contents($session_path);
  479. if ($content !== FALSE) {
  480. return t('Contents of @path :',
  481. array('@path' => check_plain($session_path))) . ' ' .
  482. print_r($content, TRUE);
  483. }
  484. return t('Unable to load contents of: @path',
  485. array('@path' => check_plain($session_path)));
  486. }
  487. /**
  488. * @} End of "defgroup file_example".
  489. */