class GdprTasksSarWorker in General Data Protection Regulation 7
Queue worker callback for processing SARs requests.
Hierarchy
- class \GdprTasksSarWorker
Expanded class hierarchy of GdprTasksSarWorker
File
- modules/
gdpr_tasks/ src/ Plugin/ QueueWorker/ GdprTasksSarWorker.php, line 6
View source
class GdprTasksSarWorker {
/**
* Process the SARs request.
*/
public function processItem($data) {
/* @var \GDPRTask $task */
$task = gdpr_task_load($data);
// Work out where we are up to and what to do next.
switch ($task->status) {
// Received but not initialised.
case 'requested':
$this
->initialise($task);
break;
// Processed by staff and ready to compile.
case 'processed':
$this
->compile($task);
break;
}
}
/**
* Initialise our request.
*
* @param \GDPRTask $task
* The task.
*/
protected function initialise(\GDPRTask $task) {
$field_info = field_info_field('gdpr_tasks_sar_export');
$directory = $field_info['settings']['uri_scheme'] . '://gdpr_sars';
file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
// Get a suitable namespace for gathering our files.
do {
// Generate a UUID.
$uuid = ctools_uuid_generate();
// Check neither the file exists nor the directory.
if (file_exists("{$directory}/{$uuid}.zip") || file_exists("{$directory}/{$uuid}/")) {
continue;
}
// Generate the zip file to reserve our namespace.
$file = file_save_data('', "{$directory}/{$uuid}.zip", FILE_EXISTS_ERROR);
} while (!$file);
// Prepare the directory for our sub-files.
$content_directory = "{$directory}/{$uuid}";
file_prepare_directory($content_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
// Store the file against the task.
$task->gdpr_tasks_sar_export[LANGUAGE_NONE][0] = array(
'fid' => $file->fid,
'display' => TRUE,
);
$task->status = 'building';
$task
->save();
// Start the build process.
$this
->build($task);
}
/**
* Build the export files.
*
* @param \GDPRTask $task
* The task.
*/
protected function build(\GDPRTask $task) {
$wrapper = $task
->wrapper();
$field_info = field_info_field('gdpr_tasks_sar_export');
$directory = $field_info['settings']['uri_scheme'] . '://gdpr_sars/';
$directory .= basename($task
->wrapper()->gdpr_tasks_sar_export->file->url
->value(), '.zip');
// Gather our entities.
// @todo: Move this inline.
$all_data = gdpr_tasks_collect_rta_data($task
->getOwner());
// Build our export files.
$csvs = array();
foreach ($all_data as $plugin_id => $data) {
if ($plugin_id == '_assets') {
$wrapper->gdpr_tasks_sar_export_assets = $data;
continue;
}
// Build the headers if required.
if (!isset($csvs[$data['file']]['_header'][$data['plugin_name']])) {
$csvs[$data['file']]['_plugin_id'][$data['plugin_name']] = $data['plugin_name'];
$csvs[$data['file']]['_header'][$data['plugin_name']] = $data['label'];
}
// Initialise and fill out the row to make sure things come in a
// consistent order.
if (!isset($csvs[$data['file']][$data['row_id']])) {
$csvs[$data['file']][$data['row_id']] = array();
}
$csvs[$data['file']][$data['row_id']] += array_fill_keys(array_keys($csvs[$data['file']]['_header']), '');
// Put our piece of information in place.
$csvs[$data['file']][$data['row_id']][$data['plugin_name']] = $data['value'];
}
// Gather existing files.
$files = array();
foreach ($wrapper->gdpr_tasks_sar_export_parts as $item) {
$filename = basename($item->file->url
->value(), '.csv');
$files[$filename] = $item->file
->value();
}
// Write our CSV files.
foreach ($csvs as $filename => $data) {
if (!isset($files[$filename])) {
// Create an empty file.
$file = file_save_data('', "{$directory}/{$filename}.csv", FILE_EXISTS_REPLACE);
// Track the file.
$task->gdpr_tasks_sar_export_parts[LANGUAGE_NONE][] = array(
'fid' => $file->fid,
'display' => TRUE,
);
}
else {
$file = $files[$filename];
}
$this
->writeCsv($file->uri, $data);
// Clear file cache so filesize can be recalculated.
clearstatcache(TRUE, $file->uri);
file_save($file);
}
// Update the status.
$task->status = 'reviewing';
$task
->save();
}
/**
* Compile the SAR into a downloadable zip.
*
* @param \GDPRTask $task
* The task.
*/
protected function compile(\GDPRTask $task) {
// Compile all files into a single zip.
$wrapper = $task
->wrapper();
$file = $wrapper->gdpr_tasks_sar_export->file;
$file_path = drupal_realpath($file
->value()->uri);
$zip = new ZipArchive();
if (!$zip
->open($file_path, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
// @todo: Improve error handling.
drupal_set_message(t('Error opening file.'), 'error');
return;
}
// Gather all the files we need to include in this package.
$part_files = array();
foreach ($wrapper->gdpr_tasks_sar_export_parts as $item) {
$part_file = $item->file
->value();
$part_files[] = $part_file;
// Re-write the file to remove the header.
$data = $this
->readCsv($part_file->uri);
array_shift($data);
$this
->writeCsv($part_file->uri, $data);
file_save($part_file);
// Add the file to the zip.
// @todo: Add error handling.
$zip
->addFile(drupal_realpath($part_file->uri), $part_file->filename);
}
// Add in any attached files that need including.
foreach ($wrapper->gdpr_tasks_sar_export_assets as $item) {
$asset_file = $item->file
->value();
// Add the file to the zip.
$filename = "assets/{$asset_file->fid}." . pathinfo($asset_file->uri, PATHINFO_EXTENSION);
// @todo: Add error handling.
$zip
->addFile(drupal_realpath($asset_file->uri), $filename);
}
// Clear our parts and assets file lists.
$task->gdpr_tasks_sar_export_parts = NULL;
$task->gdpr_tasks_sar_export_assets = NULL;
// Close the zip to write it to disk.
// @todo: Add error handling.
$zip
->close();
// Make sure the user owns the compiled zip file.
$file
->value()->uid = $task
->getOwner()->uid;
// Save the file to update the file size.
$file
->save();
// Remove the partial files.
foreach ($part_files as $part_file) {
file_delete($part_file);
}
// @todo Clean up the parts directory.
// Update the status as completed.
$task->status = 'closed';
$task
->save();
// Send confirmation email.
gdpr_tasks_send_mail('task_processed', $task);
}
/**
* Read data from a CSV file.
*
* @param string $filename
* The filename to read from (supports streams).
*
* @return array
* CSV file data.
*/
public static function readCsv($filename) {
$data = array();
$handle = fopen($filename, 'r');
while (!feof($handle)) {
$data[] = fgetcsv($handle);
}
fclose($handle);
return $data;
}
/**
* Write data to a CSV file.
*
* @param string $filename
* The filename to write to (supports streams).
* @param array $content
* The data to write, an array containing each row as an array.
*/
protected function writeCsv($filename, array $content) {
$handler = fopen($filename, 'w');
// Write the UTF-8 BOM header so excel handles the encoding.
fprintf($handler, chr(0xef) . chr(0xbb) . chr(0xbf));
foreach ($content as $row) {
fputcsv($handler, $row);
}
fclose($handler);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
GdprTasksSarWorker:: |
protected | function | Build the export files. | |
GdprTasksSarWorker:: |
protected | function | Compile the SAR into a downloadable zip. | |
GdprTasksSarWorker:: |
protected | function | Initialise our request. | |
GdprTasksSarWorker:: |
public | function | Process the SARs request. | |
GdprTasksSarWorker:: |
public static | function | Read data from a CSV file. | |
GdprTasksSarWorker:: |
protected | function | Write data to a CSV file. |