Skip to content

Commit

Permalink
Added cron queue for processing csv export files.
Browse files Browse the repository at this point in the history
  • Loading branch information
yanniboi committed Jun 21, 2018
1 parent f399146 commit d7a69fc
Show file tree
Hide file tree
Showing 9 changed files with 548 additions and 221 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
langcode: en
status: true
dependencies:
config:
- field.storage.gdpr_task.sar_export_assets
- gdpr_tasks.gdpr_task_type.gdpr_sar
module:
- file
id: gdpr_task.gdpr_sar.sar_export_assets
field_name: sar_export_assets
entity_type: gdpr_task
bundle: gdpr_sar
label: 'Export Assets'
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
file_directory: 'gdpr-exports'
file_extensions: 'txt jpg png csv'
max_filesize: ''
description_field: false
handler: 'default:file'
handler_settings: { }
field_type: file
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
langcode: en
status: true
dependencies:
config:
- field.storage.gdpr_task.sar_export_parts
- gdpr_tasks.gdpr_task_type.gdpr_sar
module:
- file
id: gdpr_task.gdpr_sar.sar_export_parts
field_name: sar_export_parts
entity_type: gdpr_task
bundle: gdpr_sar
label: 'Sar Export Parts'
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
file_directory: 'gdpr-exports'
file_extensions: csv
max_filesize: ''
description_field: false
handler: 'default:file'
handler_settings: { }
field_type: file
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
module:
- file
- gdpr_tasks
id: gdpr_task.sar_export_assets
field_name: sar_export_assets
entity_type: gdpr_task
type: file
settings:
display_field: false
display_default: false
uri_scheme: private
target_type: file
module: file
locked: false
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
module:
- file
- gdpr_tasks
id: gdpr_task.sar_export_parts
field_name: sar_export_parts
entity_type: gdpr_task
type: file
settings:
display_field: false
display_default: false
uri_scheme: private
target_type: file
module: file
locked: false
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
173 changes: 0 additions & 173 deletions modules/gdpr_tasks/gdpr_tasks.module
Original file line number Diff line number Diff line change
Expand Up @@ -76,179 +76,6 @@ function gdpr_tasks_theme_suggestions_gdpr_task(array $variables) {
return $suggestions;
}

/**
* Build export data for a user.
*
* @param \Drupal\user\UserInterface $user
* The user to generate data for.
*
* @return array
* Structured array of user related data.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
function gdpr_tasks_generate_sar_report(UserInterface $user) {
/* @var \Drupal\gdpr_fields\EntityTraversalFactory $traversalFactory */
$traversalFactory = Drupal::service('gdpr_tasks.rta_traversal');
$traversal = $traversalFactory->getTraversal($user);
$data = $traversal->getResults();
return $data;
}

/**
* Implements hook_ENTITY_TYPE_presave().
*
* Process data for task requests.
*
* @todo Consider creating plugin or event listeners for task processing.
*/
function gdpr_tasks_gdpr_task_presave(TaskInterface $gdprTask) {
switch ($gdprTask->bundle()) {
case 'gdpr_remove':
break;

// Collect relevant data and save to downloadable csv.
case 'gdpr_sar':
if (0 < $gdprTask->get('sar_export')->count()) {
break;
}

/* @var \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $field */
$field = $gdprTask->get('sar_export');
/* @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
$field_definition = $field->getFieldDefinition();
$settings = $field_definition->getSettings();

$config = [
'field_definition' => $field_definition,
'name' => $field->getName(),
'parent' => $field->getParent(),
];
/* @var \Drupal\file\Plugin\Field\FieldType\FileItem $field_type */
$field_type = \Drupal::service('plugin.manager.field.field_type')->createInstance($field_definition->getType(), $config);

// Prepare destination.
$dirname = $field_type->getUploadLocation();
\file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);

$user = $gdprTask->getOwner();
$data = gdpr_tasks_generate_sar_report($user);

$inc = [];
$maybe = [];
foreach ($data as $key => $values) {
$rta = $values['gdpr_rta'];
unset($values['gdpr_rta']);
$inc[$key] = $values;

if ('maybe' === $rta) {
$maybe[$key] = $values;
}
}

/* @var \Drupal\gdpr_tasks\TaskManager $task_manager */
$task_manager = \Drupal::service('gdpr_tasks.manager');
$destination = $task_manager->toCsv($inc, $dirname);
$export = \file_get_contents($destination);

// Generate a file entity.
// @todo Add headers to csv export.
/** @var \Drupal\file\FileInterface $file */
$file = _gdpr_tasks_file_save_data($export, $user, $destination, FILE_EXISTS_REPLACE);

if (FALSE === $file) {
drupal_set_message(t('An error occurred while saving the data export file!'), 'error');
}
else {
$values = [
'target_id' => $file->id(),
'display' => (int) $settings['display_default'],
'description' => '',
];

$gdprTask->sar_export = $values;

$temp = $task_manager->toCsv($maybe, $dirname);
$gdprTask->manual_data = \file_get_contents($temp);
}

break;
}
}

/**
* Saves a file to the specified destination and creates a database entry.
*
* @param string $data
* A string containing the contents of the file.
* @param \Drupal\Core\Session\AccountInterface $user
* The owner of the file.
* @param string|null $destination
* (optional) A string containing the destination URI. This must be a stream
* wrapper URI. If no value or NULL is provided, a randomized name will be
* generated and the file will be saved using Drupal's default files scheme,
* usually "public://".
* @param int $replace
* (optional) The replace behavior when the destination file already exists.
* Possible values include:
* - FILE_EXISTS_REPLACE: Replace the existing file. If a managed file with
* the destination name exists, then its database entry will be updated. If
* no database entry is found, then a new one will be created.
* - FILE_EXISTS_RENAME: (default) Append _{incrementing number} until the
* filename is unique.
* - FILE_EXISTS_ERROR: Do nothing and return FALSE.
*
* @return \Drupal\file\FileInterface|false
* A file entity, or FALSE on error.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Core\Entity\EntityStorageException
*
* @see file_unmanaged_save_data()
*/
function _gdpr_tasks_file_save_data($data, AccountInterface $user, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
if (!file_valid_uri($destination)) {
\Drupal::logger('file')->notice('The data could not be saved because the destination %destination is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.', ['%destination' => $destination]);
drupal_set_message(t('The data could not be saved because the destination is invalid. More information is available in the system log.'), 'error');
return FALSE;
}

if ($uri = \file_unmanaged_save_data($data, $destination, $replace)) {
/** @var \Drupal\file\FileStorageInterface $fileStorage */
$fileStorage = \Drupal::entityTypeManager()->getStorage('file');
// Create a file entity.
/** @var \Drupal\file\FileInterface $file */
$file = $fileStorage->create([
'uri' => $uri,
'uid' => $user->id(),
'status' => FILE_STATUS_PERMANENT,
]);
// If we are replacing an existing file re-use its database record.
// @todo Do not create a new entity in order to update it. See
// https://www.drupal.org/node/2241865.
if ($replace === FILE_EXISTS_REPLACE) {
$existing_files = $fileStorage->loadByProperties(['uri' => $uri]);
if (\count($existing_files)) {
$existing = reset($existing_files);
$file->fid = $existing->id();
$file->setOriginalId($existing->id());
$file->setFilename($existing->getFilename());
}
}
// If we are renaming around an existing file (rather than a directory),
// use its basename for the filename.
elseif ($replace === FILE_EXISTS_RENAME && \is_file($destination)) {
$file->setFilename(\Drupal::service('file_system')->basename($destination));
}

$file->save();
return $file;
}
return FALSE;
}

/**
* Implements hook_ENTITY_TYPE_access().
*/
Expand Down
12 changes: 11 additions & 1 deletion modules/gdpr_tasks/src/Entity/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,15 @@ public function label() {
* {@inheritdoc}
*/
public function getStatus() {
return $this->status->value;
}

/**
* {@inheritdoc}
*/
public function getStatusLabel() {
$statuses = $this->getStatuses();
$value = $this->status->value;
$value = $this->getStatus();
if (isset($statuses[$value])) {
$value = $statuses[$value];
}
Expand Down Expand Up @@ -284,6 +291,9 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
public static function getStatuses() {
return [
'requested' => t('Requested'),
'building' => t('Building data'),
'reviewing' => t('Needs review'),
'processed' => t('Processed'),
'closed' => t('Closed'),
];
}
Expand Down
8 changes: 8 additions & 0 deletions modules/gdpr_tasks/src/Entity/TaskInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ public function setCreatedTime($timestamp);
*/
public function getStatus();

/**
* Gets the current human readable status of the task.
*
* @return string
* The human readable status of the Task entity.
*/
public function getStatusLabel();

}
Loading

0 comments on commit d7a69fc

Please sign in to comment.