Commit f5b7ee60 authored by jaapjansma's avatar jaapjansma

Added batch functionality

parent 3ff3d043
Version 1.3
-----------
*Major Changes*
* Added batch processing of actions. Also added the start and finish of a batch to the action provider class.
*Changed actions*
* The create PDF action now supports batching and it also returns the filename and url of the generated PDF.
*New actions*
Version 1.2
===========
-----------
**Renamed actions**
......
......@@ -5,6 +5,8 @@ class CRM_ActionProvider_Page_DownloadFile extends CRM_Core_Page {
public function run() {
$fileName = CRM_Utils_Request::retrieve('filename', 'String', $this, FALSE);
$downloadName = CRM_Utils_Request::retrieve('downloadname', 'String', $this, FALSE);
$subdir = CRM_Utils_Request::retrieve('subdir', 'String', $this, FALSE);
if (empty($fileName)) {
CRM_Core_Error::statusBounce("Cannot access file");
}
......@@ -13,7 +15,7 @@ class CRM_ActionProvider_Page_DownloadFile extends CRM_Core_Page {
CRM_Core_Error::statusBounce("Malformed filename");
}
$basePath = CRM_Core_Config::singleton()->templateCompileDir . 'action_provider';
$basePath = CRM_Core_Config::singleton()->templateCompileDir . $subdir;
$path = $basePath.'/'.$fileName;
$mimeType = mime_content_type($path);
......@@ -27,7 +29,7 @@ class CRM_ActionProvider_Page_DownloadFile extends CRM_Core_Page {
}
CRM_Utils_System::download(
$fileName,
$downloadName,
$mimeType,
$buffer,
NULL,
......
......@@ -53,6 +53,11 @@ abstract class AbstractAction implements \JsonSerializable {
*/
protected $provider;
/**
* @var name of the current batcj
*/
protected $currentBatch;
/**
* @var AbstractCondition
*/
......@@ -135,7 +140,31 @@ abstract class AbstractAction implements \JsonSerializable {
$output = $this->createParameterBag();
$this->doAction($parameters, $output);
return $output;
}
}
/**
* This function initialize a batch.
*
* @param $batchName
*/
public function initializeBatch($batchName) {
$this->currentBatch = $batchName;
}
/**
* This function finishes a batch and is called when a batch with actions is finished.
*
* @param $batchName
* @param bool
* Whether this was the last batch.
*/
public function finishBatch($batchName, $isLastBatch=false) {
// Child classes could override this function
// E.g. merge files in a directory
$this->currentBatch = null;
}
/**
* @return bool
......
......@@ -16,12 +16,19 @@ use CRM_ActionProvider_ExtensionUtil as E;
class CreatePdf extends AbstractAction {
/**
* @var \ZipArchive
*/
protected $zip;
public function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
$domain = \CRM_Core_BAO_Domain::getDomain();
$message = $parameters->getParameter('message');
$contactId = $parameters->getParameter('contact_id');
$filename = $this->configuration->getParameter('filename');
$filename .= '_' . $contactId . '.pdf';
$fileNameWithoutContactId = $filename . '.pdf';
$filenameWithContactId = $filename . '_' . $contactId . '.pdf';
$subdir = $this->createSubDir($this->currentBatch);
$contact = civicrm_api3('Contact', 'getsingle', array('id' => $contactId));
......@@ -44,10 +51,10 @@ class CreatePdf extends AbstractAction {
$message = $smarty->fetch("string:{$message}");
}
$contents = \CRM_Utils_PDF_Utils::html2pdf($message, $filename, TRUE);
$fullFilePath = FileWriter::writeFile($contents, $filename);
$mimeType = mime_content_type($fullFilePath);
$contents = \CRM_Utils_PDF_Utils::html2pdf($message, $filenameWithContactId, TRUE);
if ($this->zip) {
$this->zip->addFromString($filenameWithContactId, $contents);
}
$activityParams = array(
'activity_type_id' => \CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Print PDF Letter'),
......@@ -56,16 +63,77 @@ class CreatePdf extends AbstractAction {
'target_contact_id' => $contactId,
);
$result = civicrm_api3('Activity', 'create', $activityParams);
civicrm_api3('Attachment', 'create', array(
$attachment = civicrm_api3('Attachment', 'create', array(
'entity_table' => 'civicrm_activity',
'entity_id' => $result['id'],
'name' => $filename,
'mime_type' => $mimeType,
'name' => $fileNameWithoutContactId,
'mime_type' => 'application/pdf',
'content' => $contents,
));
$downloadUrl = \CRM_Utils_System::url('civicrm/actionprovider/downloadfile', array('filename' => $filename));
\CRM_Core_Session::setStatus(E::ts('Created document for %1 <a href="%2">Download document<a/>', array(1=>$contact['display_name'], 2=>$downloadUrl)));
$file = reset($attachment['values']);
$output->setParameter('filename', $file['name']);
$output->setParameter('url', $file['url']);
$output->setParameter('path', $file['path']);
}
/**
* This function initialize a batch.
*
* @param $batchName
*/
public function initializeBatch($batchName) {
// Child classes could override this function
// E.g. create a directory
$this->createSubDir($batchName);
$subdir = $this->createSubDir();
$outputName = \CRM_Core_Config::singleton()->templateCompileDir . $subdir.'/'.$batchName.'.zip';
$this->zip = new \ZipArchive();
if ($this->zip->open($outputName, \ZipArchive::CREATE) !== TRUE) {
$this->zip = null;
}
$this->currentBatch = $batchName;
}
/**
* This function finishes a batch and is called when a batch with actions is finished.
*
* @param $batchName
* @param bool
* Whether this was the last batch.
*/
public function finishBatch($batchName, $isLastBatch=false) {
// Child classes could override this function
// E.g. merge files in a directorys
$subdir = $this->createSubDir();
$downloadName = $this->configuration->getParameter('filename').'.zip';
if ($this->zip) {
$this->zip->close();
if ($isLastBatch) {
$downloadUrl = \CRM_Utils_System::url('civicrm/actionprovider/downloadfile', [
'filename' => $batchName . '.zip',
'subdir' => $subdir,
'downloadname' => $downloadName
]);
\CRM_Core_Session::setStatus(E::ts('<a href="%1">Download document(s)<a/>', [1 => $downloadUrl]), E::ts('Created PDF'), 'success');
}
}
}
protected function createSubDir() {
$subDir = 'action_provider';
$basePath = \CRM_Core_Config::singleton()->templateCompileDir . $subDir;
\CRM_Utils_File::createDir($basePath);
\CRM_Utils_File::restrictAccess($basePath.'/');
$subDir .= '/createpdf';
$basePath = \CRM_Core_Config::singleton()->templateCompileDir . $subDir;
\CRM_Utils_File::createDir($basePath);
\CRM_Utils_File::restrictAccess($basePath.'/');
return $subDir;
}
/**
......@@ -86,5 +154,13 @@ class CreatePdf extends AbstractAction {
));
}
public function getOutputSpecification() {
return new SpecificationBag(array(
new Specification('filename', 'String', E::ts('Filename')),
new Specification('url', 'String', E::ts('Download Url')),
new Specification('path', 'String', E::ts('Path in filesystem')),
));
}
}
\ No newline at end of file
......@@ -48,6 +48,12 @@ class Provider {
* Contains all possible conditions.
*/
protected $allConditions = array();
/**
* @var AbstractAction[]
* Contains all instanciated actions.
*/
protected $batchActions = array();
public function __construct() {
$this->addActionWithoutFiltering('SetValue', '\Civi\ActionProvider\Action\Generic\SetValue', E::ts('Set Value'), array(
......@@ -326,6 +332,41 @@ class Provider {
return null;
}
/**
* Returns an action and store the instance to use in batch mode
*
* @return \Civi\ActionProvider\Action\AbstractAction|null when action is not found.
*/
public function getBatchActionByName($name, $configuration, $batchName) {
if (!isset($this->batchActions[$batchName])) {
$this->batchActions[$batchName] = array();
}
if (!isset($this->batchActions[$batchName][$name])) {
$this->batchActions[$batchName][$name] = $this->getActionByName($name);
if (!$this->batchActions[$batchName][$name]) {
return null;
}
$this->batchActions[$batchName][$name]->getConfiguration()->fromArray($configuration);
$this->batchActions[$batchName][$name]->initializeBatch($batchName);
}
return $this->batchActions[$batchName][$name];
}
/**
* Finish a batch
*
* @param $batchName
* @param bool $isLastBatch
*/
public function finishBatch($batchName, $isLastBatch=false) {
if (isset($this->batchActions[$batchName])) {
foreach($this->batchActions[$batchName] as $actionName => $action) {
$action->finishBatch($batchName, $isLastBatch);
unset($this->batchActions[$batchName][$actionName]);
}
}
}
/**
* Returns all available conditins
*/
......
......@@ -14,11 +14,12 @@ class FileWriter {
*
* @param $contents
* @param $filename
* @param $subDir
* @return string
* The full file path.
*/
public static function writeFile($contents, $filename) {
$basePath = \CRM_Core_Config::singleton()->templateCompileDir . 'action_provider';
public static function writeFile($contents, $filename, $subDir) {
$basePath = \CRM_Core_Config::singleton()->templateCompileDir . $subDir;
\CRM_Utils_File::createDir($basePath);
\CRM_Utils_File::restrictAccess($basePath.'/');
$fullFilePath = $basePath.'/'. $filename;
......
# action-provider
**This extension is in an prototype stage**
This extension provides a base class for actions. An action is something other extensions could reuse and which is executable.
At its own this extension does not do something but it might be used by other extensions.
......@@ -25,7 +23,7 @@ install it with the command-line tool [cv](https://github.com/civicrm/cv).
```bash
cd <extension-dir>
cv dl action-provider@https://lab.civicrm.org/jaapjansma/action-provider/repository/master/archive.zip
cv dl action-provider@https://lab.civicrm.org/extensions/action-provider/repository/master/archive.zip
```
## Installation (CLI, Git)
......@@ -34,11 +32,15 @@ Sysadmins and developers may clone the [Git](https://en.wikipedia.org/wiki/Git)
install it with the command-line tool [cv](https://github.com/civicrm/cv).
```bash
git clone https://lab.civicrm.org/jaapjansma/action-provider.git
git clone https://lab.civicrm.org/extensions/action-provider.git
cv en action_provider
```
## Roadmap
## Developer documentation
* [How to create an action](docs/howto_create_an_action.md)
* How to use the action provider in your extension (not yet written)
* How to use the batch functionality in your extension (not yet written)
1. Implement an interface and implement the interface in the form-processor extension.
2. Add a set of action which could be reused to this extension
## Roadmap
......@@ -14,7 +14,7 @@
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2019-01-09</releaseDate>
<version>1.2</version>
<version>1.3</version>
<develStage>stable</develStage>
<compatibility>
<ver>4.7</ver>
......
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