BPMN Import/Export Updates, adding url endpoint GET /project/{prj_uid}/export

This commit is contained in:
Erik Amaru Ortiz
2014-03-28 12:57:55 -04:00
parent 00fd862056
commit 262e29ab9c
4 changed files with 201 additions and 136 deletions

View File

@@ -23,22 +23,36 @@
*/
ini_set( 'max_execution_time', '0' );
$ext = pathinfo($_FILES["PROCESS_FILENAME"]["name"], PATHINFO_EXTENSION);
if ($ext == "pmx") {
$importer = new \ProcessMaker\Importer\XmlImporter();
$importer->setSourceFromGlobals("PROCESS_FILENAME");
$data = array("usr_uid" => $_SESSION['USER_LOGGED']);
$res = $importer->import($data);
$result = array(
"success" => true,
"catchMessage" => "",
"ExistProcessInDatabase" => 0,
"ExistGroupsInDatabase" => 0,
"sNewProUid" => $res[0]["new_uid"],
"project_type" => "bpmn"
);
$importer->setData("usr_uid", $_SESSION['USER_LOGGED']);
try {
$res = $importer->import();
$result = array(
"success" => true,
"catchMessage" => "",
"ExistProcessInDatabase" => 0,
"ExistGroupsInDatabase" => 0,
"sNewProUid" => $res[0]["new_uid"],
"project_type" => "bpmn"
);
} catch (Exception $e) {
$result = array(
"success" => true,
"catchMessage" => "", //$e->getMessage(),
"ExistProcessInDatabase" => 1,
"ExistGroupsInDatabase" => 0,
"groupBeforeAccion" => "uploadFileNewProcess",
"sNewProUid" => "63626727053359dabb8fee8019503780",
"proFileName" => $_FILES['PROCESS_FILENAME']['name'],
"project_type" => "bpmn"
);
}
echo json_encode($result);
exit(0);

View File

@@ -1,8 +1,13 @@
<?php
namespace ProcessMaker\Importer;
use ProcessMaker\Util;
use ProcessMaker\Project\Adapter;
abstract class Importer
{
protected $data = array();
protected $importData = array();
protected $filename = "";
protected $saveDir = "";
@@ -23,19 +28,55 @@ abstract class Importer
*/
const IMPORT_STAT_INVALID_SOURCE_FILE = 102;
public abstract function load();
public function import($option = self::IMPORT_OPTION_CREATE_NEW)
{
$this->prepare();
switch ($option) {
case self::IMPORT_OPTION_CREATE_NEW:
$this->prepare();
$this->createNewProject();
$result = $this->doImport();
break;
case self::IMPORT_OPTION_DISABLE_AND_CREATE_NEW:
break;
case self::IMPORT_OPTION_OVERWRITE:
break;
}
return $result;
}
/**
* Prepare for import, it makes all validations needed
* @return int
* @throws \Exception
*/
public function prepare()
{
if ($this->validateSource() === false) {
throw new \Exception(
"Error, Invalid file type or the file have corrupt data",
self::IMPORT_STAT_INVALID_SOURCE_FILE
);
}
$this->importData = $this->load();
$this->validateImportData();
if ($this->targetExists()) {
throw new \Exception(sprintf(
"Project already exists, you need set an action to continue. " .
"Avaliable actions: [%s|%s|%s].", self::IMPORT_OPTION_CREATE_NEW,
self::IMPORT_OPTION_OVERWRITE, self::IMPORT_OPTION_DISABLE_AND_CREATE_NEW
), self::IMPORT_STAT_TARGET_ALREADY_EXISTS);
}
}
public function setData($key, $value)
{
$this->data[$key] = $value;
}
/**
@@ -47,18 +88,29 @@ abstract class Importer
return true;
}
public function validateImportData()
{
if (! isset($this->importData["tables"]["bpmn"])) {
throw new \Exception("BPMN Definition is missing.");
}
if (! isset($this->importData["tables"]["bpmn"]["project"]) || count($this->importData["tables"]["bpmn"]["project"]) !== 1) {
throw new \Exception("BPMN table: \"Project\", definition is missing or has multiple definition.");
}
return true;
}
/**
* Verify if the project already exists
* @return mixed
*/
public function targetExists()
{
return false;
}
$prjUid = $this->importData["tables"]["bpmn"]["project"][0]["prj_uid"];
public function createNewProject()
{
$bpmnProject = \BpmnProjectPeer::retrieveByPK($prjUid);
return is_object($bpmnProject);
}
public function updateProject()
@@ -109,15 +161,6 @@ abstract class Importer
*/
public function setSourceFromGlobals($varName)
{
/*[PROCESS_FILENAME] => Array
(
[name] => sample29.pm
[type] => application/pm
[tmp_name] => /tmp/phpvHpCVO
[error] => 0
[size] => 1260881
)*/
if (! array_key_exists($varName, $_FILES)) {
throw new \Exception("Couldn't find specified source \"$varName\" in PHP Globals");
}
@@ -136,28 +179,75 @@ abstract class Importer
umask($oldUmask);
}
/**
* Prepare for import, it makes all validations needed
* @return int
* @throws \Exception
*/
public function prepare()
protected function importBpmnTables(array $tables)
{
if ($this->validateSource() === false) {
throw new \Exception(
"Error, Invalid file type or the file have corrupt data",
self::IMPORT_STAT_INVALID_SOURCE_FILE
);
}
// Build BPMN project struct
$project = $tables["project"][0];
$diagram = $tables["diagram"][0];
$diagram["activities"] = $tables["activity"];
$diagram["artifacts"] = array();
$diagram["events"] = $tables["event"];
$diagram["flows"] = $tables["flow"];
$diagram["gateways"] = $tables["gateway"];
$diagram["lanes"] = array();
$diagram["laneset"] = array();
$project["diagrams"] = array($diagram);
$project["prj_author"] = isset($this->data["usr_uid"])? $this->data["usr_uid"]: "00000000000000000000000000000001";
$project["process"] = $tables["process"][0];
if ($this->targetExists()) {
throw new \Exception(sprintf(
"Project already exists, you need set an action to continue. " .
"Avaliable actions: [%s|%s|%s].", self::IMPORT_OPTION_CREATE_NEW,
self::IMPORT_OPTION_OVERWRITE, self::IMPORT_OPTION_DISABLE_AND_CREATE_NEW
), self::IMPORT_STAT_TARGET_ALREADY_EXISTS);
}
return Adapter\BpmnWorkflow::createFromStruct($project);
}
return self::IMPORT_STAT_SUCCESS;
protected function importWfTables(array $tables)
{
$tables = (object) $tables;
$processes = new \Processes();
$processes->createProcessPropertiesFromData($tables);
}
protected function importWfFiles(array $workflowFiles)
{
foreach ($workflowFiles as $target => $files) {
switch ($target) {
case "dynaforms":
$basePath = PATH_DYNAFORM;
break;
case "public":
$basePath = PATH_DATA . "sites" . PATH_SEP . SYS_SYS . PATH_SEP . "public" . PATH_SEP;
break;
case "templates":
$basePath = PATH_DATA . "sites" . PATH_SEP . SYS_SYS . PATH_SEP . "mailTemplates" . PATH_SEP;
break;
default:
$basePath = "";
}
if (empty($basePath)) continue;
foreach ($files as $file) {
$filename = $basePath . $file["file_path"];
$path = dirname($filename);
if (! is_dir($path)) {
Util\Common::mk_dir($path, 0775);
}
file_put_contents($filename, $file["file_content"]);
chmod($filename, 0775);
}
}
}
public function doImport()
{
$tables = $this->importData["tables"];
$files = $this->importData["files"];
$result = $this->importBpmnTables($tables["bpmn"]);
$this->importWfTables($tables["workflow"]);
$this->importWfFiles($files["workflow"]);
return $result;
}
}

View File

@@ -1,9 +1,6 @@
<?php
namespace ProcessMaker\Importer;
use ProcessMaker\Project\Adapter;
use ProcessMaker\Util;
class XmlImporter extends Importer
{
/**
@@ -12,17 +9,22 @@ class XmlImporter extends Importer
protected $dom;
protected $root;
protected $version = "";
protected $metadata;
public function __construct()
{
$this->dom = new \DOMDocument();
}
public function setSourceFile($filename)
{
$this->filename = $filename;
}
/**
* @return array
* Example:
* array(
* "tables" => array("bpmn" => array(), "workflow" => array())
* "files" => array("bpmn" => array(), "workflow" => array())
* )
* @throws \Exception
*/
public function load()
{
$this->dom->load($this->filename);
@@ -36,13 +38,13 @@ class XmlImporter extends Importer
}
// read metadata section
$metadata = $this->root->getElementsByTagName("metadata");
$metadataNode = $this->root->getElementsByTagName("metadata");
if ($metadata->length != 1) {
if ($metadataNode->length != 1) {
throw new \Exception("Invalid Document format, metadata section is missing or has multiple definition.");
}
$metadata = $metadata->item(0);
$this->metadata = $metadataNode->item(0);
// load project definition
/** @var \DOMElement[]|\DomNodeList $definitions */
@@ -57,7 +59,7 @@ class XmlImporter extends Importer
$tables = array();
foreach ($definitions as $definition) {
$defClass = strtoupper($definition->getAttribute("class"));
$defClass = strtolower($definition->getAttribute("class"));
$tables[$defClass] = array();
// getting tables def
@@ -66,7 +68,7 @@ class XmlImporter extends Importer
$tablesNodeList = $definition->getElementsByTagName("table");
foreach ($tablesNodeList as $tableNode) {
$tableName = $tableNode->getAttribute("name"); //strtoupper($tableNode->getAttribute("name"));
$tableName = strtolower($tableNode->getAttribute("name"));
$tables[$defClass][$tableName] = array();
/** @var \DOMElement[] $recordsNodeList */
$recordsNodeList = $tableNode->getElementsByTagName("record");
@@ -80,9 +82,9 @@ class XmlImporter extends Importer
foreach ($recordsNode->childNodes as $columnNode) {
if ($columnNode->nodeName == "#text") continue;
//$columns[strtoupper($columnNode->nodeName)] = self::createTextNode($columnNode);;
$columnName = $defClass == "WORKFLOW" ? strtoupper($columnNode->nodeName) : $columnNode->nodeName;
$columns[$columnName] = self::createTextNode($columnNode);
//$columns[strtoupper($columnNode->nodeName)] = self::getTextNode($columnNode);;
$columnName = $defClass == "workflow" ? strtoupper($columnNode->nodeName) : $columnNode->nodeName;
$columns[$columnName] = self::getTextNode($columnNode);
}
$tables[$defClass][$tableName][] = $columns;
@@ -97,54 +99,28 @@ class XmlImporter extends Importer
$filesNodeList = $wfFilesNodeList->item(0)->getElementsByTagName("file");
foreach ($filesNodeList as $fileNode) {
$target = $fileNode->getAttribute("target");
$target = strtolower($fileNode->getAttribute("target"));
if (! isset($wfFiles[$target])) {
$wfFiles[$target] = array();
}
$fileContent = self::createTextNode($fileNode->getElementsByTagName("file_content")->item(0));
$fileContent = base64_decode($fileContent);
$fileContent = self::getTextNode($fileNode->getElementsByTagName("file_content")->item(0));
$wfFiles[$target][] = array(
"file_name" => self::createTextNode($fileNode->getElementsByTagName("file_name")->item(0)),
"file_path" => self::createTextNode($fileNode->getElementsByTagName("file_path")->item(0)),
"file_content" => $fileContent
"file_name" => self::getTextNode($fileNode->getElementsByTagName("file_name")->item(0)),
"file_path" => self::getTextNode($fileNode->getElementsByTagName("file_path")->item(0)),
"file_content" => base64_decode($fileContent)
);
}
}
//print_r($tables);
//print_r($wfFiles);
return array($tables, $wfFiles);
return array(
"tables" => $tables,
"files" => array("workflow" => $wfFiles, "bpmn" => array())
);
}
public function import($data = array())
{
list($tables, $files) = $this->load();
// Build BPMN project struct
$project = $tables["BPMN"]["PROJECT"][0];
$diagram = $tables["BPMN"]["DIAGRAM"][0];
$diagram["activities"] = $tables["BPMN"]["ACTIVITY"];
$diagram["artifacts"] = array();
$diagram["events"] = $tables["BPMN"]["EVENT"];
$diagram["flows"] = $tables["BPMN"]["FLOW"];
$diagram["gateways"] = $tables["BPMN"]["GATEWAY"];
$diagram["lanes"] = array();
$diagram["laneset"] = array();
$project["diagrams"] = array($diagram);
$project["prj_author"] = isset($data["usr_uid"])? $data["usr_uid"]: "00000000000000000000000000000001";
$project["process"] = $tables["BPMN"]["PROCESS"][0];
$result = Adapter\BpmnWorkflow::createFromStruct($project);
$this->importWfTables($tables["WORKFLOW"]);
$this->importWfFiles($files);
return $result;
}
private static function createTextNode($node)
private static function getTextNode($node)
{
if ($node->nodeType == XML_ELEMENT_NODE) {
return $node->textContent;
@@ -152,42 +128,4 @@ class XmlImporter extends Importer
return (string) simplexml_import_dom($node->parentNode);
}
}
private static function importWfFiles(array $workflowFiles)
{
foreach ($workflowFiles as $target => $files) {
switch ($target) {
case "dynaforms": $basePath = PATH_DYNAFORM; break;
case "public":
$basePath = PATH_DATA . "sites" . PATH_SEP . SYS_SYS . PATH_SEP . "public" . PATH_SEP;
break;
case "templates":
$basePath = PATH_DATA . "sites" . PATH_SEP . SYS_SYS . PATH_SEP . "mailTemplates" . PATH_SEP;
break;
default: $basePath = "";
}
if (empty($basePath)) continue;
foreach ($files as $file) {
$filename = $basePath . $file["file_path"];
$path = dirname($filename);
if (! is_dir($path)) {
Util\Common::mk_dir($path, 0775);
}
file_put_contents($filename, $file["file_content"]);
chmod($filename, 0775);
}
}
}
public function importWfTables($tables)
{
$tables = (object) $tables;
$processes = new \Processes();
$processes->createProcessPropertiesFromData($tables);
}
}

View File

@@ -73,6 +73,29 @@ class Project extends Api
}
}
/**
* @url GET /:prj_uid/export
*
* @param string $prj_uid {@min 32}{@max 32}
*/
public function export($prj_uid)
{
$exporter = new \ProcessMaker\Exporter\XmlExporter($prj_uid);
$outputDir = PATH_DATA . "sites" . PATH_SEP . SYS_SYS . PATH_SEP . "files" . PATH_SEP . "output" . PATH_SEP;
$version = \ProcessMaker\Util\Common::getLastVersion($outputDir . $exporter->getProjectName() . "-*.pmx") + 1;
$outputFilename = $outputDir . sprintf("%s-%s.%s", $exporter->getProjectName(), $version, "pmx");
$exporter->saveExport($outputFilename);
$httpStream = new \ProcessMaker\Util\IO\HttpStream();
$fileExtension = pathinfo($outputFilename, PATHINFO_EXTENSION);
$httpStream->loadFromFile($outputFilename);
$httpStream->setHeader("Content-Type", "application/$fileExtension");
$httpStream->send();
}
/**
* @url GET /:prj_uid/process
*