Commit 5486d24e authored by jaapjansma's avatar jaapjansma
Browse files

Made CSV Export download available for anonymous users.

parent b3040c76
# Version 1.2.0 (not yet released)
* Made CSV Export download available for anonymous users.
# Version 1.1.0
* Respect selected permissions for outputs
......
......@@ -125,6 +125,8 @@ class CRM_Dataprocessor_Form_DataProcessor extends CRM_Core_Form {
$outputClass = $factory->getOutputByName($output['type']);
if ($outputClass instanceof \Civi\DataProcessor\Output\UIOutputInterface) {
$outputs[$idx]['navigation_url'] = CRM_Utils_System::url($outputClass->getUrlToUi($output, $this->dataProcessor), array('reset' => '1'));
} elseif ($outputClass instanceof \Civi\DataProcessor\Output\UrlOutputInterface && $outputClass->checkPermission($output, $this->dataProcessor)) {
$outputs[$idx]['navigation_url'] = $outputClass->getUrl($output, $this->dataProcessor);
}
if (isset($types[$output['type']])) {
......
......@@ -41,7 +41,11 @@ class CRM_Dataprocessor_Form_ManageDataProcessors extends CRM_Core_Form {
if ($outputClass instanceof \Civi\DataProcessor\Output\UIOutputInterface) {
$dataProcessors[$idx]['navigation'][$outputIndex]['url'] = CRM_Utils_System::url($outputClass->getUrlToUi($output, $dataProcessor), array('reset' => '1'));
$dataProcessors[$idx]['navigation'][$outputIndex]['title'] = $outputClass->getTitleForUiLink($output, $dataProcessor);
} elseif ($outputClass instanceof \Civi\DataProcessor\Output\UrlOutputInterface && $outputClass->checkPermission($output, $dataProcessor)) {
$dataProcessors[$idx]['navigation'][$outputIndex]['url'] = $outputClass->getUrl($output, $dataProcessor);
$dataProcessors[$idx]['navigation'][$outputIndex]['title'] = $outputClass->getTitleForLink($output, $dataProcessor);
}
}
}
......@@ -78,4 +82,4 @@ class CRM_Dataprocessor_Form_ManageDataProcessors extends CRM_Core_Form {
}
}
\ No newline at end of file
}
......@@ -5,10 +5,11 @@
*/
use Civi\DataProcessor\Output\ExportOutputInterface;
use Civi\DataProcessor\Output\DirectDownloadExportOutputInterface;
use CRM_Dataprocessor_ExtensionUtil as E;
class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface, DirectDownloadExportOutputInterface {
const MAX_DIRECT_SIZE = 500;
......@@ -34,6 +35,7 @@ class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
$form->add('text', 'delimiter', E::ts('Delimiter'), array(), true);
$form->add('text', 'enclosure', E::ts('Enclosure'), array(), true);
$form->add('text', 'escape_char', E::ts('Escape char'), array(), true);
$form->add('checkbox', 'anonymous', E::ts('Available for anonymous users'), array(), false);
$configuration = false;
if ($output && isset($output['configuration'])) {
......@@ -54,6 +56,9 @@ class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
} else {
$defaults['escape_char'] = '\\';
}
if ($configuration && isset($configuration['anonymous'])) {
$defaults['anonymous'] = $configuration['anonymous'];
}
$form->setDefaults($defaults);
}
......@@ -80,6 +85,7 @@ class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
$configuration['delimiter'] = $submittedValues['delimiter'];
$configuration['enclosure'] = $submittedValues['enclosure'];
$configuration['escape_char'] = $submittedValues['escape_char'];
$configuration['anonymous'] = $submittedValues['anonymous'];
return $configuration;
}
......@@ -139,16 +145,17 @@ class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
* @param array $selectedIds
* Array with the selectedIds.
* @return string
* @throws \Exception
*/
public function downloadExport(\Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessorClass, $dataProcessor, $outputBAO, $formValues, $sortFieldName = null, $sortDirection = 'ASC', $idField=null, $selectedIds=array()) {
if ($dataProcessorClass->getDataFlow()->recordCount() > self::MAX_DIRECT_SIZE) {
if (!$dataProcessorClass->getDataFlow()->recordCount() > self::MAX_DIRECT_SIZE) {
$this->startBatchJob($dataProcessorClass, $dataProcessor, $outputBAO, $formValues, $sortFieldName, $sortDirection, $idField, $selectedIds);
} else {
$this->doDirectDownload($dataProcessorClass, $dataProcessor, $outputBAO, $sortFieldName, $sortDirection, $idField, $selectedIds);
}
}
protected function doDirectDownload(\Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessorClass, $dataProcessor, $outputBAO, $sortFieldName = null, $sortDirection = 'ASC', $idField, $selectedIds=array()) {
public function doDirectDownload(\Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessorClass, $dataProcessor, $outputBAO, $sortFieldName = null, $sortDirection = 'ASC', $idField, $selectedIds=array()) {
$filename = date('Ymdhis').'_'.$dataProcessor['id'].'_'.$outputBAO['id'].'_'.CRM_Core_Session::getLoggedInContactID().'_'.$dataProcessor['name'].'.csv';
$download_name = date('Ymdhis').'_'.$dataProcessor['name'].'.csv';
......@@ -306,5 +313,51 @@ class CRM_DataprocessorOutputExport_CSV implements ExportOutputInterface {
CRM_Core_Session::setStatus(E::ts('<a href="%1">Download CSV file</a>', array(1=>$downloadLink)), E::ts('Exported data'), 'success');
}
/**
* Returns the url for the page/form this output will show to the user
*
* @param array $output
* @param array $dataProcessor
* @return string
*/
public function getUrl($output, $dataProcessor) {
return CRM_Utils_System::url('civicrm/dataprocessor/output/export', array(
'name' => $dataProcessor['name'],
'type' => $output['type']
));
}
/**
* Returns the url for the page/form this output will show to the user
*
* @param array $output
* @param array $dataProcessor
* @return string
*/
public function getTitleForLink($output, $dataProcessor) {
return $dataProcessor['title'];
}
/**
* Checks whether the current user has access to this output
*
* @param array $output
* @param array $dataProcessor
* @return bool
*/
public function checkPermission($output, $dataProcessor) {
$anonymous = false;
if (isset($output['configuration']) && isset($output['configuration']['anonymous'])) {
$anonymous = $output['configuration']['anonymous'] ? true : false;
}
$userId = \CRM_Core_Session::getLoggedInContactID();
if ($userId) {
return true;
} elseif ($anonymous) {
return true;
}
return false;
}
}
<?php
/**
* @author Jaap Jansma <jaap.jansma@civicoop.org>
* @license AGPL-3.0
*/
class CRM_DataprocessorOutputExport_Page_Export extends CRM_Core_Page {
/**
* @var array
*/
protected $dataProcessor;
/**
* @var \Civi\DataProcessor\ProcessorType\AbstractProcessorType;
*/
protected $dataProcessorClass;
/**
* @var int
*/
protected $dataProcessorId;
/**
* @var \CRM_Dataprocessor_BAO_Output
*/
protected $dataProcessorOutput;
/**
* Run page.
*/
public function run() {
$this->loadDataProcessor();
$sortFields = $this->addColumnHeaders();
$this->sort = new CRM_Utils_Sort($sortFields);
$this->runExport();
}
protected function runExport() {
$factory = dataprocessor_get_factory();
CRM_Dataprocessor_Form_Output_AbstractUIOutputForm::applyFilters($this->dataProcessorClass, array());
// Set the sort
$sortDirection = 'ASC';
$sortFieldName = null;
if (!empty($this->sort->_vars[$this->sort->getCurrentSortID()])) {
$sortField = $this->sort->_vars[$this->sort->getCurrentSortID()];
if ($this->sort->getCurrentSortDirection() == CRM_Utils_Sort::DESCENDING) {
$sortDirection = 'DESC';
}
$sortFieldName = $sortField['name'];
}
$outputClass = $factory->getOutputByName($this->dataProcessorOutput['type']);
if ($outputClass instanceof \Civi\DataProcessor\Output\DirectDownloadExportOutputInterface) {
$outputClass->doDirectDownload($this->dataProcessorClass, $this->dataProcessor, $this->dataProcessorOutput, array(), $sortFieldName, $sortDirection);
}
throw new \Exception('Unable to export');
}
protected function getDataProcessorName() {
return CRM_Utils_Request::retrieve('name', 'String', CRM_Core_DAO::$_nullObject, TRUE);
}
protected function getOutputName() {
return CRM_Utils_Request::retrieve('type', 'String', CRM_Core_DAO::$_nullObject, TRUE);
}
/**
* Retrieve the data processor and the output configuration
*
* @throws \Exception
*/
protected function loadDataProcessor() {
$factory = dataprocessor_get_factory();
if (!$this->dataProcessorId) {
$dataProcessorName = $this->getDataProcessorName();
$sql = "
SELECT civicrm_data_processor.id as data_processor_id, civicrm_data_processor_output.id AS output_id
FROM civicrm_data_processor
INNER JOIN civicrm_data_processor_output ON civicrm_data_processor.id = civicrm_data_processor_output.data_processor_id
WHERE is_active = 1 AND civicrm_data_processor.name = %1 AND civicrm_data_processor_output.type = %2
";
$params[1] = [$dataProcessorName, 'String'];
$params[2] = [$this->getOutputName(), 'String'];
$dao = CRM_Dataprocessor_BAO_DataProcessor::executeQuery($sql, $params, TRUE, 'CRM_Dataprocessor_BAO_DataProcessor');
if (!$dao->fetch()) {
throw new \Exception('Could not find Data Processor "' . $dataProcessorName.'"');
}
$this->dataProcessor = civicrm_api3('DataProcessor', 'getsingle', array('id' => $dao->data_processor_id));
$this->dataProcessorClass = \CRM_Dataprocessor_BAO_DataProcessor::dataProcessorToClass($this->dataProcessor, true);
$this->dataProcessorId = $dao->data_processor_id;
$this->dataProcessorOutput = civicrm_api3('DataProcessorOutput', 'getsingle', array('id' => $dao->output_id));
$outputClass = $factory->getOutputByName($this->dataProcessorOutput['type']);
if (!$outputClass instanceof \Civi\DataProcessor\Output\DirectDownloadExportOutputInterface) {
throw new \Exception('Invalid output');
}
if (!$outputClass->checkPermission($this->dataProcessorOutput, $this->dataProcessor)) {
CRM_Utils_System::permissionDenied();
CRM_Utils_System::civiExit();
}
}
}
/**
* Add the headers for the columns
*
* @return array
* Array with all possible sort fields.
*
* @throws \Civi\DataProcessor\DataFlow\InvalidFlowException
*/
protected function addColumnHeaders() {
$sortFields = array();
$columnHeaders = array();
$sortColumnNr = 1;
foreach($this->dataProcessorClass->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) {
$field = $outputFieldHandler->getOutputFieldSpecification();
$columnHeaders[$field->alias] = $field->title;
if ($outputFieldHandler instanceof \Civi\DataProcessor\FieldOutputHandler\OutputHandlerSortable) {
$sortFields[$sortColumnNr] = array(
'name' => $field->title,
'sort' => $field->alias,
'direction' => CRM_Utils_Sort::DONTCARE,
);
$sortColumnNr++;
}
}
return $sortFields;
}
}
<?php
/**
* @author Jaap Jansma <jaap.jansma@civicoop.org>
* @license AGPL-3.0
*/
namespace Civi\DataProcessor\Output;
/**
* This interface indicates that the output type is available as a direct download.
*
* @package Civi\DataProcessor\Output
*/
interface DirectDownloadExportOutputInterface extends UrlOutputInterface {
/**
* Download export
*
* @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessorClass
* @param array $dataProcessor
* @param array $outputBAO
* @param array $formValues
* @param string $sortFieldName
* @param string $sortDirection
* @param string $idField
* Set $idField to the name of the field containing the ID of the array $selectedIds
* @param array $selectedIds
* Array with the selectedIds.
* @return string
*/
public function doDirectDownload(\Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessorClass, $dataProcessor, $outputBAO, $sortFieldName = null, $sortDirection = 'ASC', $idField, $selectedIds=array());
}
<?php
/**
* @author Jaap Jansma <jaap.jansma@civicoop.org>
* @license AGPL-3.0
*/
namespace Civi\DataProcessor\Output;
/**
* This interface indicates that the output type is available through a url.
*
* @package Civi\DataProcessor\Output
*/
interface UrlOutputInterface {
/**
* Returns the url for the page/form this output will show to the user
*
* @param array $output
* @param array $dataProcessor
* @return string
*/
public function getUrl($output, $dataProcessor);
/**
* Returns the url for the page/form this output will show to the user
*
* @param array $output
* @param array $dataProcessor
* @return string
*/
public function getTitleForLink($output, $dataProcessor);
/**
* Checks whether the current user has access to this output
*
* @param array $output
* @param array $dataProcessor
* @return bool
*/
public function checkPermission($output, $dataProcessor);
}
......@@ -15,5 +15,16 @@
<div class="content">{$form.escape_char.html}</div>
<div class="clear"></div>
</div>
<div class="crm-section">
<div class="label">{$form.anonymous.label}</div>
<div class="content">{$form.anonymous.html}
<p class="description">
{ts}Tick this box when you want to make the CSV available for non-logged in users. <br>
This could be necessary when another system is importing this csv file on a regular basis. E.g. a website with
a public agenda of the upcoming events.
<br><strong>Caution:</strong> when you check this box the data becomes available without logging so this might lead to a data breach.{/ts}</p>
</div>
<div class="clear"></div>
</div>
{/crmScope}
\ No newline at end of file
{/crmScope}
......@@ -83,8 +83,15 @@
</item>
<item>
<path>civicrm/dataprocessor/form/output/download</path>
<title>Browse Uploaded files</title>
<title>Download</title>
<access_arguments>access uploaded files</access_arguments>
<page_callback>CRM_DataprocessorOutputExport_Page_Download</page_callback>
</item>
<item>
<path>civicrm/dataprocessor/output/export</path>
<title>Export</title>
<page_callback>CRM_DataprocessorOutputExport_Page_Export</page_callback>
<access_callback>1</access_callback>
<is_public>true</is_public>
</item>
</menu>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment