added example for developpers module

This commit is contained in:
Bachir Soussi Chiadmi
2018-01-06 11:28:03 +01:00
parent 5017966908
commit 5ec2f4311c
396 changed files with 26299 additions and 0 deletions
@@ -0,0 +1,15 @@
name: File Example
type: module
description: Demonstrates using the Drupal File API and stream wrappers.
package: Example modules
# core: 8.x
dependencies:
- drupal:file
- examples:examples
- examples:stream_wrapper_example
# Information added by Drupal.org packaging script on 2017-12-17
version: '8.x-1.x-dev'
core: '8.x'
project: 'examples'
datestamp: 1513537386
@@ -0,0 +1,7 @@
#
# This link will appear in the "Tools" menu.
#
file_example.fileapi:
title: File Example
parent: file_example.description
route_name: file_example.fileapi
@@ -0,0 +1,97 @@
<?php
/**
* @file
* Examples demonstrating the Drupal File API.
*/
/**
* @defgroup file_example Example: Files
* @ingroup examples
* @{
* Examples demonstrating the Drupal File API.
*
* The File Example module is part of the Examples for Developers Project and
* provides a variety of examples for the Developers project page. Some
* concepts we demonstrate with this module:
*
* * Creating, moving and deleting files, and reading and writing from them.
*
* * Using files that Drupal can manage via its Entity API ("managed files"),
* and unmanaged files (the usual kind of file programs deal with).
*
* * Creating and setting up directories with the right permissions, and with
* .htaccess files that prevent unwanted accesses.
*
* * Allowing restricted access to files the way Drupal private files are
* downloaded.
*
* * Using special "stream" URIs like public://, private://, and temporary://.
* Drupal has good support for this PHP language feature. You can implement
* new file schemes as well; see the Stream Wrapper Example for how to do
* that.If you enable the stream_wrapper_example module, you can use it
* together with the File Example to test how a custom stream works.
*
* To demonstrate all of this, the File Example implements a form that lets you
* play with files. Read src/Form/FileExampleReadWriteForm.php to see
* demonstrations of the various File API functions you will want to use in your
* code.
*
* Some links for further information on the File API and related information:
*
* @link http://drupal.org/project/examples Examples for Developers project
* page. @endlink
* @link file File summary on api.drupal.org @endlink for the function summary.
*/
/**
* Implements hook_file_download().
*
* This hook allows modules to enforce permissions on file downloads whenever
* Drupal is handling file download, as opposed to the web server bypassing
* Drupal and returning the file from a public directory. Modules can also
* provide headers to specify information like the file's name or MIME type.
*
* For our example module, we want to be able to see the temporary, private,
* and session (our test stream wrapper / file scheme). In general, you really
* would NEVER give general access to your temporary, and you certainly wouldn't
* do it for your private files. So we demonstrate this here, but kids, don't
* try this at home ;-) Remember: keep your files secure!
*
* For hook_file_download() to get called at all, your code needs set up your
* routes so that the download link uses FileDownloadController::download() as
* a controller. FileDownloadController::download() enforces access restrictions
* on the files it managed, in part by invoking hook_file_downloads(). See the
* File Example's routing file to see how to do this.
*
* @param string $uri
* The URI of the file.
*
* @return mixed
* If the user does not have permission to access the file, return -1. If the
* user has permission, return an array with the appropriate headers. If the
* file is not controlled by the current module, the return value should be
* NULL.
*
* @see file_download()
* @see hook_file_download()
* @see file_example.routing.yml
* @see \Drupal\system\FileDownloadController::download()
*/
function file_example_file_download($uri) {
$scheme = file_uri_scheme($uri);
if (in_array($scheme, ['private', 'temporary', 'session'])) {
$permission = "read $scheme files";
$current_user = \Drupal::currentUser();
$account = $current_user->getAccount();
if ($account->hasPermission($permission)) {
return [
'Content-Type: text/plain',
];
}
}
}
/**
* @} End of "defgroup file_example".
*/
@@ -0,0 +1,13 @@
'use file example':
title: Use the examples in the File Example module.
#
# We use the following permissions in our hook_file_download implementation.
# See file_example.module for details.
#
'read private files':
title: See private files in the File Example module demo.
'read temporary files':
title: See temporary files in the File Example module demo.
'read session files':
title: See session files in the File Example module demo.
@@ -0,0 +1,8 @@
# Main page for our example.
file_example.fileapi:
path: '/examples/file_example'
defaults:
_form: '\Drupal\file_example\Form\FileExampleReadWriteForm'
_title: 'File Example: Use the File API to read/write a file'
requirements:
_permission: 'use file example'
@@ -0,0 +1,861 @@
<?php
namespace Drupal\file_example\Form;
use Drupal\Core\Database\Database;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\stream_wrapper_example\StreamWrapper\SessionWrapper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* File test form class.
*
* @ingroup file_example
*/
class FileExampleReadWriteForm extends FormBase {
/**
* Interface of the "state" service for site-specific data.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Object used to get request data, such as the session.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* Service for manipulating a file system.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* Service for fetching a stream wrapper for a file or directory.
*
* @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
*/
protected $streamWrapperManager;
/**
* Indicator variable for the session:// scheme being available.
*
* @var bool
*/
protected $sessionSchemeEnabled;
/**
* Service for invoking hooks and other module operations.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a new FileExampleReadWriteForm page.
*
* @param \Drupal\Core\State\StateInterface $state
* Storage interface for state data.
* @param \Drupal\Core\File\FileSystemInterface $file_system
* Interface for common file system operations.
* @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager
* Interface to obtain stream wrappers used to manipulate a given file
* scheme.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* Interface to get information about the status of modules and other
* extensions.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* Access to the current request, including to session objects.
*/
public function __construct(
StateInterface $state,
FileSystemInterface $file_system,
StreamWrapperManagerInterface $stream_wrapper_manager,
ModuleHandlerInterface $module_handler,
RequestStack $request_stack
) {
$this->state = $state;
$this->fileSystem = $file_system;
$this->moduleHandler = $module_handler;
$this->requestStack = $request_stack;
$this->streamWrapperManager = $stream_wrapper_manager;
$this->sessionSchemeEnabled = $this->moduleHandler->moduleExists('stream_wrapper_example');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$state = $container->get('state');
$file_system = $container->get('file_system');
$module_handler = $container->get('module_handler');
$request_stack = $container->get('request_stack');
$stream_wrapper_manager = $container->get('stream_wrapper_manager');
return new static($state, $file_system, $stream_wrapper_manager, $module_handler, $request_stack);
}
/**
* Returns a unique string identifying the form.
*
* @return string
* The unique string identifying the form.
*/
public function getFormId() {
return 'file_example_readwrite';
}
/**
* Get the default file.
*
* This appears in the first block of the form.
*
* @return string
* The URI of the default file.
*/
protected function getDefaultFile() {
$fall_back_value = $this->sessionSchemeEnabled ? 'session://drupal.txt' : 'public://drupal.txt';
$default_file = $this->state->get('file_example_default_file', $fall_back_value);
return $default_file;
}
/**
* Fetch a SessionWrapper object.
*
* This is used to change relevant attributes of the Session. This will return
* FALSE if the stream_wrapper_example is not enabled.
*
* @return Drupal\stream_wrapper_example\StreamWrapper\SessionWrapper|bool
* Wrapper object to manipulate the SESSION storage or FALSE if the session
* wrapper is unavailable.
*/
protected function getSessionWrapper() {
if ($this->sessionSchemeEnabled) {
return new SessionWrapper($this->requestStack);
}
return FALSE;
}
/**
* Set the default file.
*
* Set a default URI of the file used for read and write operations.
*
* @param string $uri
* URI to save for future display in the form.
*/
protected function setDefaultFile($uri) {
$this->state->set('file_example_default_file', (string) $uri);
}
/**
* Get the default directory.
*
* @return string
* The URI of the default directory.
*/
protected function getDefaultDirectory() {
$fall_back_value = $this->sessionSchemeEnabled ? 'session://directory1' : 'public://directory1';
$default_directory = $this->state->get('file_example_default_directory', $fall_back_value);
return $default_directory;
}
/**
* Set the default directory.
*
* @param string $uri
* URI to save for later form display.
*/
protected function setDefaultDirectory($uri) {
$this->state->set('file_example_default_directory', (string) $uri);
}
/**
* 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.
*
* @return \Drupal\file\Entity\FileInterface|bool
* A file object that matches the URI, or FALSE if not a managed file.
*
* @todo This should still work. An entity query could be used instead.
* May be other alternatives.
*/
private static function getManagedFile($uri) {
$fid = Database::getConnection('default')->query(
'SELECT fid FROM {file_managed} WHERE uri = :uri',
[':uri' => $uri]
)->fetchField();
if (!empty($fid)) {
$file_object = File::load($fid);
return $file_object;
}
return FALSE;
}
/**
* Prepare Url objects to prevent exceptions by the URL generator.
*
* Helper function to get us an external URL if this is legal, and to catch
* the exception Drupal throws if this is not possible.
*
* In Drupal 8, the URL generator is very sensitive to how you set things
* up, and some functions, in particular LinkGeneratorTrait::l(), will throw
* exceptions if you deviate from what's expected. This function will raise
* the chances your URL will be valid, and not do this.
*
* @param \Drupal\file\Entity\File|string $file_object
* A file entity object.
*
* @return \Drupal\Core\Url
* A Url object that can be displayed as an internal URL.
*/
protected function getExternalUrl($file_object) {
if ($file_object instanceof FileInterface) {
$uri = $file_object->getFileUri();
}
else {
// A little tricky, since file.inc is a little inconsistent, but often
// this is a Uri.
$uri = file_create_url($file_object);
}
try {
// If we have been given a PHP stream URI, ask the stream itself if it
// knows how to create an external URL.
$wrapper = $this->streamWrapperManager->getViaUri($uri);
if ($wrapper) {
$external_url = $wrapper->getExternalUrl();
// Some streams may not have the concept of an external URL, so we
// check here to make sure, since the example assumes this.
if ($external_url) {
$url = Url::fromUri($external_url);
return $url;
}
}
else {
$url = Url::fromUri($uri);
// If we did not throw on ::fromUri (you can), we return the URL.
return $url;
}
}
catch (\Exception $e) {
return FALSE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$default_file = $this->getDefaultFile();
$default_directory = $this->getDefaultDirectory();
$form['description'] = [
'#markup' => $this->t('This form demonstrates the Drupal 8 file api. Experiment with the form, and then look at the submit handlers in the code to understand the file api.'),
];
$form['write_file'] = [
'#type' => 'fieldset',
'#title' => $this->t('Write to a file'),
];
$form['write_file']['write_contents'] = [
'#type' => 'textfield',
'#title' => $this->t('Enter something you would like to write to a file'),
'#default_value' => $this->t('Put some text here or just use this text'),
];
$form['write_file']['destination'] = [
'#type' => 'textfield',
'#default_value' => $default_file,
'#title' => $this->t('Optional: Enter the streamwrapper saying where it should be written'),
'#description' => $this->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'] = [
'#type' => 'submit',
'#value' => $this->t('Write managed file'),
'#submit' => ['::handleManagedFile'],
];
$form['write_file']['unmanaged_submit'] = [
'#type' => 'submit',
'#value' => $this->t('Write unmanaged file'),
'#submit' => ['::handleUnmanagedFile'],
];
$form['write_file']['unmanaged_php'] = [
'#type' => 'submit',
'#value' => $this->t('Unmanaged using PHP'),
'#submit' => ['::handleUnmanagedPhp'],
];
$form['fileops'] = [
'#type' => 'fieldset',
'#title' => $this->t('Read from a file'),
];
$form['fileops']['fileops_file'] = [
'#type' => 'textfield',
'#default_value' => $default_file,
'#title' => $this->t('Enter the URI of a file'),
'#description' => $this->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'] = [
'#type' => 'submit',
'#value' => $this->t('Read the file and store it locally'),
'#submit' => ['::handleFileRead'],
];
$form['fileops']['delete_submit'] = [
'#type' => 'submit',
'#value' => $this->t('Delete file'),
'#submit' => ['::handleFileDelete'],
];
$form['fileops']['check_submit'] = [
'#type' => 'submit',
'#value' => $this->t('Check to see if file exists'),
'#submit' => ['::handleFileExists'],
];
$form['directory'] = [
'#type' => 'fieldset',
'#title' => $this->t('Create or prepare a directory'),
];
$form['directory']['directory_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Directory to create/prepare/delete'),
'#default_value' => $default_directory,
'#description' => $this->t('This is a directory as in public://some/directory or private://another/dir.'),
];
$form['directory']['create_directory'] = [
'#type' => 'submit',
'#value' => $this->t('Create directory'),
'#submit' => ['::handleDirectoryCreate'],
];
$form['directory']['delete_directory'] = [
'#type' => 'submit',
'#value' => $this->t('Delete directory'),
'#submit' => ['::handleDirectoryDelete'],
];
$form['directory']['check_directory'] = [
'#type' => 'submit',
'#value' => $this->t('Check to see if directory exists'),
'#submit' => ['::handleDirectoryExists'],
];
$form['debug'] = [
'#type' => 'fieldset',
'#title' => $this->t('Debugging'),
];
// The Session Wrapper Exampple is not yet committed, so
// we hide this button until this happens.
$form['debug']['show_raw_session'] = [
'#type' => 'submit',
'#value' => $this->t('Show raw $_SESSION contents'),
'#submit' => ['::handleShowSession'],
'#access' => $this->sessionSchemeEnabled,
];
$form['debug']['reset_session'] = [
'#type' => 'submit',
'#value' => t('Reset the Session'),
'#submit' => ['::handleResetSession'],
];
return $form;
}
/**
* Submit handler to write a managed file.
*
* A "managed file" is a file that Drupal tracks as a file entity. It's the
* standard way Drupal manages files in file fields and elsewhere.
*
* 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.
* * @param array $form
* An associative array containing the structure of the form.
*
* @param array &$form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function handleManagedFile(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$data = $form_values['write_contents'];
$uri = !empty($form_values['destination']) ? $form_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 = $this->getExternalUrl($file_object);
$this->setDefaultFile($file_object->getFileUri());
$file_data = $file_object->toArray();
if ($url) {
drupal_set_message(
$this->t('Saved managed file: %file to destination %destination (accessible via <a href=":url">this URL</a>, actual uri=<span id="uri">@uri</span>)',
[
'%file' => print_r($file_data, TRUE),
'%destination' => $uri,
'@uri' => $file_object->getFileUri(),
':url' => $url->toString(),
]
)
);
}
else {
// This Uri is not routable, so we cannot give a link to it.
drupal_set_message(
$this->t('Saved managed file: %file to destination %destination (no URL, since this stream type does not support it)',
[
'%file' => print_r($file_data, TRUE),
'%destination' => $uri,
'@uri' => $file_object->getFileUri(),
]
)
);
}
}
else {
drupal_set_message(t('Failed to save the managed file'), 'error');
}
}
/**
* Submit handler to write an unmanaged file.
*
* An unmanaged file is a file that Drupal does not track. A standard
* operating system file, in other words.
*
* 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.
* * @param array $form
* An associative array containing the structure of the form.
*
* @param array &$form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function handleUnmanagedFile(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$data = $form_values['write_contents'];
$destination = !empty($form_values['destination']) ? $form_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 = $this->getExternalUrl($filename);
$this->setDefaultFile($filename);
if ($url) {
drupal_set_message(
$this->t('Saved file as %filename (accessible via <a href=":url">this URL</a>, uri=<span id="uri">@uri</span>)',
[
'%filename' => $filename,
'@uri' => $filename,
':url' => $url->toString(),
]
)
);
}
else {
drupal_set_message(
$this->t('Saved file as %filename (not accessible externally)',
[
'%filename' => $filename,
'@uri' => $filename,
]
)
);
}
}
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.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function handleUnmanagedPhp(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$data = $form_values['write_contents'];
$destination = !empty($form_values['destination']) ? $form_values['destination'] : NULL;
if (empty($destination)) {
// If no destination has been provided, use a generated name.
$destination = $this->fileSystem->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', ['%file' => $destination]), 'error');
fclose($fp);
return;
}
}
$url = $this->getExternalUrl($destination);
$this->setDefaultFile($destination);
if ($url) {
drupal_set_message(
$this->t('Saved file as %filename (accessible via <a href=":url">this URL</a>, uri=<span id="uri">@uri</span>)',
[
'%filename' => $destination,
'@uri' => $destination,
':url' => $url->toString(),
]
)
);
}
else {
drupal_set_message(
$this->t('Saved file as %filename (not accessible externally)',
[
'%filename' => $destination,
'@uri' => $destination,
]
)
);
}
}
/**
* 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. The Stream
* Wrapper Example, if installed, impleents a custom 'session' scheme that
* you can test with this example.
*
* 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().
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function handleFileRead(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$uri = $form_values['fileops_file'];
if (empty($uri) or !is_file($uri)) {
drupal_set_message(t('The file "%uri" does not exist', ['%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 = $this->getExternalUrl($sourcename);
$this->setDefaultFile($sourcename);
if ($url) {
drupal_set_message(
$this->t('The file was read and copied to %filename which is accessible at <a href=":url">this URL</a>',
[
'%filename' => $sourcename,
':url' => $url->toString(),
]
)
);
}
else {
drupal_set_message(
$this->t('The file was read and copied to %filename (not accessible externally)',
[
'%filename' => $sourcename,
]
)
);
}
}
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', ['%file' => $uri]));
}
}
/**
* Submit handler to delete a file.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function handleFileDelete(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$uri = $form_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 = self::getManagedFile($uri);
// If a managed file, use file_delete().
if (!empty($file_object)) {
// While file_delete should return FALSE on failure,
// it can currently throw an exception on certain cache states.
try {
// This no longer returns a result code. If things go bad,
// it will throw an exception:
file_delete($file_object->id());
drupal_set_message(t('Successfully deleted managed file %uri', ['%uri' => $uri]));
$this->setDefaultFile($uri);
}
catch (\Exception $e) {
drupal_set_message(t('Failed deleting managed file %uri. Result was %result',
[
'%uri' => $uri,
'%result' => print_r($e->getMessage(), TRUE),
]
), 'error');
}
}
// Else use file_unmanaged_delete().
else {
$result = file_unmanaged_delete($uri);
if ($result !== TRUE) {
drupal_set_message(t('Failed deleting unmanaged file %uri', ['%uri' => $uri, 'error']));
}
else {
drupal_set_message(t('Successfully deleted unmanaged file %uri', ['%uri' => $uri]));
$this->setDefaultFile('file_example_default_file', $uri);
}
}
}
/**
* Submit handler to check existence of a file.
*/
public function handleFileExists(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$uri = $form_values['fileops_file'];
if (is_file($uri)) {
drupal_set_message(t('The file %uri exists.', ['%uri' => $uri]));
}
else {
drupal_set_message(t('The file %uri does not exist.', ['%uri' => $uri]));
}
}
/**
* Submit handler for directory creation.
*
* Here we create a directory and set proper permissions on it using
* file_prepare_directory().
*/
public function handleDirectoryCreate(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$directory = $form_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.', ['%directory' => $directory]), 'error');
}
else {
$result = is_dir($directory);
drupal_set_message(t('Directory %directory is ready for use.', ['%directory' => $directory]));
$this->setDefaultDirectory($directory);
}
}
/**
* Submit handler for directory deletion.
*
* @see file_unmanaged_delete_recursive()
*/
public function handleDirectoryDelete(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$directory = $form_values['directory_name'];
$result = file_unmanaged_delete_recursive($directory);
if (!$result) {
drupal_set_message(t('Failed to delete %directory.', ['%directory' => $directory]), 'error');
}
else {
drupal_set_message(t('Recursively deleted directory %directory.', ['%directory' => $directory]));
$this->setDefaultDirectory($directory);
}
}
/**
* Submit handler to test directory existence.
*
* This actually just checks to see if the directory is writable.
*
* @param array $form
* FormAPI form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* FormAPI form state.
*/
public function handleDirectoryExists(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
$directory = $form_values['directory_name'];
$result = is_dir($directory);
if (!$result) {
drupal_set_message(t('Directory %directory does not exist.', ['%directory' => $directory]));
}
else {
drupal_set_message(t('Directory %directory exists.', ['%directory' => $directory]));
}
}
/**
* Utility submit function to show the contents of $_SESSION.
*/
public function handleShowSession(array &$form, FormStateInterface $form_state) {
$form_values = $form_state->getValues();
// If the devel module is installed, use it's nicer message format.
if ($this->moduleHandler->moduleExists('devel')) {
// @codingStandardsIgnoreStart
// We wrap this in the coding standards ignore tags because the use of
// function dsm() is discouraged.
dsm($this->getStoredData(), $this->t('Entire $_SESSION["file_example"]'));
// @codingStandardsIgnoreEnd
}
else {
drupal_set_message('<pre>' . print_r($this->getStoredData(), TRUE) . '</pre>');
}
}
/**
* Utility submit function to reset the demo.
*
* @param array $form
* FormAPI form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* FormAPI form state.
*
* @todo Note this does NOT clear any managed file references in Drupal's DB.
* It might be a good idea to add this.
*/
public function handleResetSession(array &$form, FormStateInterface $form_state) {
$this->state->delete('file_example_default_file');
$this->state->delete('file_example_default_directory');
$this->clearStoredData();
drupal_set_message('Session reset.');
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
// We don't use this, but the interface requires us to implement it.
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// We don't use this, but the interface requires us to implement it.
}
/**
* Get our stored data for display.
*/
protected function getStoredData() {
$handle = $this->getSessionWrapper();
if ($handle) {
return $handle->getPath('');
}
return "SESSION STORE IS NOT ENABLED";
}
/**
* Reset our stored data.
*/
protected function clearStoredData() {
$handle = $this->getSessionWrapper();
if ($handle) {
return $handle->cleanUpStore();
}
}
}
@@ -0,0 +1,152 @@
<?php
namespace Drupal\Tests\file_example\Functional;
use Drupal\Tests\examples\Functional\ExamplesBrowserTestBase;
/**
* Functional tests for the File Example module.
*
* @ingroup file_example
*
* @group file_example
* @group examples
*/
class FileExampleTest extends ExamplesBrowserTestBase {
/**
* Modules to enable.
*
* @var array
*
* @todo Add the stream_wrapper_example when it is completed.
*/
public static $modules = ['file_example'];
/**
* Test the basic File Example UI.
*
* - Create a directory to work with.
* - For each scheme create and read files using each of the three methods.
*/
public function testFileExampleBasic() {
$assert = $this->assertSession();
// Our test user needs to access some non-standard file types,
// so we bless it accordingly.
$permissions = [
'use file example',
'read private files',
'read temporary files',
'read session files',
];
$priviledged_user = $this->drupalCreateUser($permissions);
$this->drupalLogin($priviledged_user);
$expected_text = [
'Write managed file' => 'Saved managed file',
'Write unmanaged file' => 'Saved file as',
'Unmanaged using PHP' => 'Saved file as',
];
// For each of the three buttons == three write types.
$buttons = [
'Write managed file',
'Write unmanaged file',
'Unmanaged using PHP',
];
foreach ($buttons as $button) {
// For each scheme supported by Drupal + the session:// wrapper,
// which is defined in the stream_wrapper_exampnle.
$schemes = ['public', 'private', 'temporary', 'session'];
foreach ($schemes as $scheme) {
// Create a directory for use.
$dirname = $scheme . '://' . $this->randomMachineName(10);
// Directory does not yet exist; assert that.
$edit = [
'directory_name' => $dirname,
];
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if directory exists');
$assert->pageTextContains(t('Directory @dirname does not exist', ['@dirname' => $dirname]));
$this->drupalPostForm('examples/file_example', $edit, 'Create directory');
$assert->pageTextContains(t('Directory @dirname is ready for use', ['@dirname' => $dirname]));
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if directory exists');
$assert->pageTextContains(t('Directory @dirname exists', ['@dirname' => $dirname]));
// Create a file in the directory we created.
$content = $this->randomMachineName(30);
$filename = $dirname . '/' . $this->randomMachineName(30) . '.txt';
// Assert that the file we're about to create does not yet exist.
$edit = [
'fileops_file' => $filename,
];
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if file exists');
$assert->pageTextContains(t('The file @filename does not exist', ['@filename' => $filename]));
$this->verbose("Processing button=$button, scheme=$scheme, dir=$dirname, file=$filename");
$edit = [
'write_contents' => $content,
'destination' => $filename,
];
$this->drupalPostForm('examples/file_example', $edit, $button);
$this->verbose($expected_text[$button], "Button Text");
$assert->pageTextContains($expected_text[$button]);
// Capture the name of the output file, as it might have changed due
// to file renaming.
$element = $this->xpath('//span[@id="uri"]');
$output_filename = (string) $element[0]->getText();
$this->verbose($output_filename, 'Name of output file');
// Click the link provided that is an easy way to get the data for
// checking and make sure that the data we put in is what we get out.
if (!in_array($scheme, [])) {
$this->clickLink(t('this URL'));
$assert->statusCodeEquals(200);
// assertText give sketchy answers when the content is *exactly* the
// contents of the buffer, so let's do something less fragile.
// $this->assertText($content);
$buffer = $this->getSession()->getPage()->getContent();
$this->assertEquals($content, $buffer);
}
// Verify that the file exists.
$edit = [
'fileops_file' => $filename,
];
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if file exists');
$assert->pageTextContains("The file $filename exists");
// Now read the file that got written above and verify that we can use
// the writing tools.
$edit = [
'fileops_file' => $output_filename,
];
$this->drupalPostForm('examples/file_example', $edit, 'Read the file and store it locally');
$assert->pageTextContains('The file was read and copied');
$edit = [
'fileops_file' => $filename,
];
$this->drupalPostForm('examples/file_example', $edit, 'Delete file');
$assert->pageTextContains('Successfully deleted');
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if file exists');
$assert->pageTextContains(t('The file @filename does not exist', ['@filename' => $filename]));
$edit = [
'directory_name' => $dirname,
];
$this->drupalPostForm('examples/file_example', $edit, 'Delete directory');
$this->drupalPostForm('examples/file_example', $edit, 'Check to see if directory exists');
$assert->pageTextContains(t('Directory @dirname does not exist', ['@dirname' => $dirname]));
}
}
}
}