Skip to content

Commit

Permalink
New file usage logic for json_form_widget (#3730)
Browse files Browse the repository at this point in the history
  • Loading branch information
dafeder authored Dec 23, 2021
1 parent 5adc4b7 commit 849c788
Showing 1 changed file with 115 additions and 20 deletions.
135 changes: 115 additions & 20 deletions modules/json_form_widget/json_form_widget.module
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@

/**
* @file
* Defines a multi-field form element based on a JSON Schema.
*/

use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\json_form_widget\Plugin\Field\FieldWidget\JsonFormWidget;


/**
* Submit handler for the "add-one-more" button.
Expand Down Expand Up @@ -46,33 +53,121 @@ function json_form_widget_remove_one(array &$form, FormStateInterface $form_stat
}

/**
* Add custom submit handler to data form.
* Implements hook_field_widget_multivalue_form_alter().
*
* Set json_form_widget flag for later.
*/
function json_form_widget_field_widget_multivalue_form_alter(array $elements, FormStateInterface $form_state, array $context) {
if ($context['widget'] instanceof JsonFormWidget) {
$form_state->has_json_form_widget = TRUE;
}
}

/**
* Implements hook_form_alter().
*
* Add custom submit handler to form if it contains an upload_or_link element.
*/
function json_form_widget_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if ($form_id === "node_data_form" || $form_id === "node_data_edit_form") {
$form['actions']['submit']['#submit'][] = 'json_form_widget_save_dkan_file_submit';
if (!isset($form['actions']['submit']) || !isset($form_state->has_json_form_widget)) {
return;
}
if ($form_state->has_json_form_widget) {
$form['actions']['submit']['#submit'][] = 'json_form_widget_file_submit';
}
}

/**
* Submit handler for uploaded elements on upload_or_link.
*
* Sets up file entities created by upload element.
*/
function json_form_widget_file_submit(array $form, FormStateInterface $form_state) {
$parents = $form_state->get('upload_or_link_element');
if (empty($parents)) {
return;
}

// Avoid double usage if URL is duplicated in form object.
$urls = [];
foreach ($parents as $parent) {
$urls[] = $form_state->getValue($parent);
}
$urls = array_unique(array_filter($urls));

foreach ($urls as $url) {
_json_form_widget_update_file($url, $form_state);
}
}

/**
* Find recently-uploaded file entity, set to permanent and add usage.
*
* @param string $url
* The URL of the file stored in the form submission.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form_state object.
*/
function json_form_widget_save_dkan_file_submit($form, FormStateInterface $form_state) {
if ($parents = $form_state->get('upload_or_link_element')) {
foreach ($parents as $parent) {
$uri = $form_state->getValue($parent);
$filename = \Drupal::service('file_system')->basename($uri);
$filename = urldecode($filename);
$files = \Drupal::entityTypeManager()
->getStorage('file')
->loadByProperties(['filename' => $filename]);
if (!empty($files)) {
$file = reset($files);
$file->setPermanent();
$file->save();
$file_usage = \Drupal::service('file.usage');
$file_usage->add($file, 'json_form_widget', 'json_form_widget', \Drupal::currentUser()->id());
}
}
function _json_form_widget_update_file(string $url, FormStateInterface $form_state) {
$fo = $form_state->getFormObject();
$storage = \Drupal::entityTypeManager()->getStorage('file');
$props = ['uri' => _json_form_widget_get_file_uri($url)];
$file = reset($storage->loadByProperties($props));

if ($file instanceof FileInterface) {
$file->setPermanent();
$file->save();
}
else {
return FALSE;
}
// If we're working with an entity form, set up usage.
if ($fo instanceof EntityFormInterface && $entity = $fo->getEntity()) {
$fu = \Drupal::service('file.usage');
$fu->add($file, 'json_form_widget', $entity->getEntityTypeId(), $entity->id());
}
}


/**
* Generate a Drupal internal URI from a URL in the widget.
*
* @todo The module should be using internal URIs which would make this step
* unnecessary.
*/
function _json_form_widget_get_file_uri($url) {
$path = urldecode(file_url_transform_relative($url));
// We're loading scheme from config, but this will probably break if not
// "public".
$scheme = \Drupal::config('system.file')->get('default_scheme') . "://";
$scheme_path = file_url_transform_relative(file_create_url($scheme));
$uri = str_replace($scheme_path, $scheme, $path, $count);

return $count ? $uri : $path;
}

/**
* Implements hook_entity_delete().
*
* Clean up file usage after entity delete.
*/
function json_form_widget_entity_delete(EntityInterface $entity) {
$type = $entity->getEntityTypeId();
$id = $entity->id();

// Find files by entity/module usage.
$fids = \Drupal::database()->select('file_usage', 'fu')
->fields('fu', ['fid'])
->condition('fu.type', $type)
->condition('fu.id', $id)
->condition('fu.module', 'json_form_widget')
->execute()
->fetchCol();

$files = File::loadMultiple($fids);

// Remove one usage for each file related to deleted entity.
foreach ($files as $file) {
\Drupal::service('file.usage')->delete($file, 'json_form_widget', $type, $id);
}
}

0 comments on commit 849c788

Please sign in to comment.