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' ); ini_set( 'max_execution_time', '0' );
$ext = pathinfo($_FILES["PROCESS_FILENAME"]["name"], PATHINFO_EXTENSION); $ext = pathinfo($_FILES["PROCESS_FILENAME"]["name"], PATHINFO_EXTENSION);
if ($ext == "pmx") { if ($ext == "pmx") {
$importer = new \ProcessMaker\Importer\XmlImporter(); $importer = new \ProcessMaker\Importer\XmlImporter();
$importer->setSourceFromGlobals("PROCESS_FILENAME"); $importer->setSourceFromGlobals("PROCESS_FILENAME");
$data = array("usr_uid" => $_SESSION['USER_LOGGED']); $importer->setData("usr_uid", $_SESSION['USER_LOGGED']);
$res = $importer->import($data);
$result = array( try {
"success" => true, $res = $importer->import();
"catchMessage" => "",
"ExistProcessInDatabase" => 0, $result = array(
"ExistGroupsInDatabase" => 0, "success" => true,
"sNewProUid" => $res[0]["new_uid"], "catchMessage" => "",
"project_type" => "bpmn" "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); echo json_encode($result);
exit(0); exit(0);

View File

@@ -1,8 +1,13 @@
<?php <?php
namespace ProcessMaker\Importer; namespace ProcessMaker\Importer;
use ProcessMaker\Util;
use ProcessMaker\Project\Adapter;
abstract class Importer abstract class Importer
{ {
protected $data = array();
protected $importData = array();
protected $filename = ""; protected $filename = "";
protected $saveDir = ""; protected $saveDir = "";
@@ -23,19 +28,55 @@ abstract class Importer
*/ */
const IMPORT_STAT_INVALID_SOURCE_FILE = 102; const IMPORT_STAT_INVALID_SOURCE_FILE = 102;
public abstract function load();
public function import($option = self::IMPORT_OPTION_CREATE_NEW) public function import($option = self::IMPORT_OPTION_CREATE_NEW)
{ {
$this->prepare();
switch ($option) { switch ($option) {
case self::IMPORT_OPTION_CREATE_NEW: case self::IMPORT_OPTION_CREATE_NEW:
$this->prepare(); $result = $this->doImport();
$this->createNewProject();
break; break;
case self::IMPORT_OPTION_DISABLE_AND_CREATE_NEW: case self::IMPORT_OPTION_DISABLE_AND_CREATE_NEW:
break; break;
case self::IMPORT_OPTION_OVERWRITE: case self::IMPORT_OPTION_OVERWRITE:
break; 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; 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 * Verify if the project already exists
* @return mixed * @return mixed
*/ */
public function targetExists() 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() public function updateProject()
@@ -109,15 +161,6 @@ abstract class Importer
*/ */
public function setSourceFromGlobals($varName) 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)) { if (! array_key_exists($varName, $_FILES)) {
throw new \Exception("Couldn't find specified source \"$varName\" in PHP Globals"); throw new \Exception("Couldn't find specified source \"$varName\" in PHP Globals");
} }
@@ -136,28 +179,75 @@ abstract class Importer
umask($oldUmask); umask($oldUmask);
} }
/** protected function importBpmnTables(array $tables)
* Prepare for import, it makes all validations needed
* @return int
* @throws \Exception
*/
public function prepare()
{ {
if ($this->validateSource() === false) { // Build BPMN project struct
throw new \Exception( $project = $tables["project"][0];
"Error, Invalid file type or the file have corrupt data", $diagram = $tables["diagram"][0];
self::IMPORT_STAT_INVALID_SOURCE_FILE $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()) { return Adapter\BpmnWorkflow::createFromStruct($project);
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 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 <?php
namespace ProcessMaker\Importer; namespace ProcessMaker\Importer;
use ProcessMaker\Project\Adapter;
use ProcessMaker\Util;
class XmlImporter extends Importer class XmlImporter extends Importer
{ {
/** /**
@@ -12,17 +9,22 @@ class XmlImporter extends Importer
protected $dom; protected $dom;
protected $root; protected $root;
protected $version = ""; protected $version = "";
protected $metadata;
public function __construct() public function __construct()
{ {
$this->dom = new \DOMDocument(); $this->dom = new \DOMDocument();
} }
public function setSourceFile($filename) /**
{ * @return array
$this->filename = $filename; * Example:
} * array(
* "tables" => array("bpmn" => array(), "workflow" => array())
* "files" => array("bpmn" => array(), "workflow" => array())
* )
* @throws \Exception
*/
public function load() public function load()
{ {
$this->dom->load($this->filename); $this->dom->load($this->filename);
@@ -36,13 +38,13 @@ class XmlImporter extends Importer
} }
// read metadata section // 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."); 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 // load project definition
/** @var \DOMElement[]|\DomNodeList $definitions */ /** @var \DOMElement[]|\DomNodeList $definitions */
@@ -57,7 +59,7 @@ class XmlImporter extends Importer
$tables = array(); $tables = array();
foreach ($definitions as $definition) { foreach ($definitions as $definition) {
$defClass = strtoupper($definition->getAttribute("class")); $defClass = strtolower($definition->getAttribute("class"));
$tables[$defClass] = array(); $tables[$defClass] = array();
// getting tables def // getting tables def
@@ -66,7 +68,7 @@ class XmlImporter extends Importer
$tablesNodeList = $definition->getElementsByTagName("table"); $tablesNodeList = $definition->getElementsByTagName("table");
foreach ($tablesNodeList as $tableNode) { foreach ($tablesNodeList as $tableNode) {
$tableName = $tableNode->getAttribute("name"); //strtoupper($tableNode->getAttribute("name")); $tableName = strtolower($tableNode->getAttribute("name"));
$tables[$defClass][$tableName] = array(); $tables[$defClass][$tableName] = array();
/** @var \DOMElement[] $recordsNodeList */ /** @var \DOMElement[] $recordsNodeList */
$recordsNodeList = $tableNode->getElementsByTagName("record"); $recordsNodeList = $tableNode->getElementsByTagName("record");
@@ -80,9 +82,9 @@ class XmlImporter extends Importer
foreach ($recordsNode->childNodes as $columnNode) { foreach ($recordsNode->childNodes as $columnNode) {
if ($columnNode->nodeName == "#text") continue; if ($columnNode->nodeName == "#text") continue;
//$columns[strtoupper($columnNode->nodeName)] = self::createTextNode($columnNode);; //$columns[strtoupper($columnNode->nodeName)] = self::getTextNode($columnNode);;
$columnName = $defClass == "WORKFLOW" ? strtoupper($columnNode->nodeName) : $columnNode->nodeName; $columnName = $defClass == "workflow" ? strtoupper($columnNode->nodeName) : $columnNode->nodeName;
$columns[$columnName] = self::createTextNode($columnNode); $columns[$columnName] = self::getTextNode($columnNode);
} }
$tables[$defClass][$tableName][] = $columns; $tables[$defClass][$tableName][] = $columns;
@@ -97,54 +99,28 @@ class XmlImporter extends Importer
$filesNodeList = $wfFilesNodeList->item(0)->getElementsByTagName("file"); $filesNodeList = $wfFilesNodeList->item(0)->getElementsByTagName("file");
foreach ($filesNodeList as $fileNode) { foreach ($filesNodeList as $fileNode) {
$target = $fileNode->getAttribute("target"); $target = strtolower($fileNode->getAttribute("target"));
if (! isset($wfFiles[$target])) { if (! isset($wfFiles[$target])) {
$wfFiles[$target] = array(); $wfFiles[$target] = array();
} }
$fileContent = self::createTextNode($fileNode->getElementsByTagName("file_content")->item(0)); $fileContent = self::getTextNode($fileNode->getElementsByTagName("file_content")->item(0));
$fileContent = base64_decode($fileContent);
$wfFiles[$target][] = array( $wfFiles[$target][] = array(
"file_name" => self::createTextNode($fileNode->getElementsByTagName("file_name")->item(0)), "file_name" => self::getTextNode($fileNode->getElementsByTagName("file_name")->item(0)),
"file_path" => self::createTextNode($fileNode->getElementsByTagName("file_path")->item(0)), "file_path" => self::getTextNode($fileNode->getElementsByTagName("file_path")->item(0)),
"file_content" => $fileContent "file_content" => base64_decode($fileContent)
); );
} }
} }
//print_r($tables); return array(
//print_r($wfFiles); "tables" => $tables,
return array($tables, $wfFiles); "files" => array("workflow" => $wfFiles, "bpmn" => array())
);
} }
public function import($data = array()) private static function getTextNode($node)
{
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)
{ {
if ($node->nodeType == XML_ELEMENT_NODE) { if ($node->nodeType == XML_ELEMENT_NODE) {
return $node->textContent; return $node->textContent;
@@ -152,42 +128,4 @@ class XmlImporter extends Importer
return (string) simplexml_import_dom($node->parentNode); 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 * @url GET /:prj_uid/process
* *