stream_wrapper_example.module 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <?php
  2. /**
  3. * @file
  4. * Contains the module file for the Stream Wrapper Example.
  5. */
  6. /**
  7. * @defgroup stream_wrapper_example Example: Stream Wrappers
  8. * @group stream_wrapper_example
  9. * @ingroup examples
  10. * @{
  11. * Example demonstrating how to implement stream wrappers in Drupal.
  12. *
  13. * The Stream Wrapper Example module is part of the Examples for Developers
  14. * Project and provides a variety of examples for the Developers project page.
  15. * We demonstrate how to create a "pseudo file system" using PHP's stream
  16. * wrapper features, similar to what Drupal does to support the public://
  17. * private:// and temporary:// schemes.
  18. *
  19. * When we write a stream URI like "public://README.md", we can divide that URI
  20. * into two parts:
  21. *
  22. * - The "scheme" name ("public" in this case).
  23. * - The "target", in this case "README.md".
  24. *
  25. * Many PHP and Drupal file functions can take a stream URI and treat it almost
  26. * exactly like a file path. Because they behave so much like files, if you
  27. * want to know how to use a stream URI, you should also look at the File
  28. * Example. The Stream Wrapper Example is designed to work together with
  29. * that example, and if you enable both examples, the two will work seamlessly
  30. * together. This is all most developers need to know about stream wrappers.
  31. *
  32. * This example shows how to actually implement a new scheme. We demonstrate
  33. * a rather unpractical scheme, but one that covers most of what you can do
  34. * with a stream type in Drupal 8. We take the session object that is put up
  35. * in each web request, and we treat one of the session variables as if it were
  36. * a file system with directories and files. This code is for demonstration
  37. * purposes only, since this not something you would ever want to do on a
  38. * production web site. But the example is simple enough that we don't need
  39. * any external libraries, as one might need to create a stream over
  40. * Amazon Web Services S3 service, or other services you might use to store
  41. * files on a web site. Yet most of what you need to do in order to make a
  42. * stream implementation like that we will do in our "session" scheme.
  43. *
  44. * To implement a stream wrapper in Drupal, you should do the following:
  45. *
  46. * 1. Create a class that implements the StreamWrapperInterface
  47. * (Drupal\Core\StreamWrapper\StreamWrapperInterface).
  48. *
  49. * 2. Register the class with Drupal. The best way to do this is to
  50. * define a service in your MY_MODULE.services.yml file. The
  51. * service needs to be "tagged" with the scheme you want to implement,
  52. * and, as so:
  53. *
  54. * @code
  55. * tags:
  56. * - { name: stream_wrapper, scheme: session }
  57. * @endcode
  58. * See stream_wrapper_example.services.yml for an example.
  59. *
  60. * 3. (Optional) If you want to be able to access your files over the web,
  61. * you need to add a route that handles, and implement hook_file_download().
  62. * See stream_wrapper_example.routing.yml for an example of this, and
  63. * file_example.module for the hook implementation.
  64. *
  65. * In our example, the key files to look at are:
  66. *
  67. * - src/StreamWrapper/FileExampleSessionStreamWrapper.php (the stream wrapper
  68. * class).
  69. * - src/PathProcessorSessions.php, which implements something called a "path
  70. * processor".
  71. * A path processor is a class that lets us hook the "files" in a scheme's
  72. * file system into Drupal 8's routing system. This allows us to assign
  73. * external URLs to the files served out of the stream wrapper class. Like a
  74. * stream wrapper class, Drupal 8 implements this as a "tagged service".
  75. * - stream_wrapper_example.services.yml, which defines the services we need to
  76. * do all this magic. You should read the comments in that file to see how
  77. * this fits together.
  78. *
  79. * We also include two PHPUnit tests. Because stream wrappers require quite a
  80. * bit of code that gets called "behind our back" by PHP itself, good test
  81. * coverage is essential for writing usable stream wrapper implementations. The
  82. * tests should help get you started on that.
  83. *
  84. * @see http://php.net/manual/en/intro.stream.php.
  85. * @see core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php
  86. */
  87. /**
  88. * @} End of "defgroup stream_wrapper_example".
  89. */
  90. /**
  91. * Implements hook_theme().
  92. *
  93. * Since we have a lot to explain, we're going to use Twig to do it.
  94. */
  95. function stream_wrapper_example_theme() {
  96. return [
  97. 'example_description' => [
  98. 'template' => 'description',
  99. 'variables' => [
  100. 'admin_link' => NULL,
  101. ],
  102. ],
  103. ];
  104. }