Merged in bugfix/PMCORE-545 (pull request #7231)

PMCORE-545 Public files in a process cannot be deleted (in Windows Server) when the process is imported

Approved-by: Julio Cesar Laura Avendaño <contact@julio-laura.com>
This commit is contained in:
Roly
2020-02-05 13:17:12 +00:00
committed by Julio Cesar Laura Avendaño
12 changed files with 386 additions and 36 deletions

View File

@@ -0,0 +1,14 @@
<?php
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\BpmnDiagram::class, function(Faker $faker) {
return [
'DIA_UID' => $faker->regexify("/[a-zA-Z]{32}/"),
'PRJ_UID' => function() {
return factory(\ProcessMaker\Model\BpmnProject::class)->create()->PRJ_UID;
},
'DIA_NAME' => $faker->name,
'DIA_IS_CLOSABLE' => 0,
];
});

View File

@@ -0,0 +1,32 @@
<?php
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\BpmnEvent::class, function(Faker $faker) {
$bpmnProcess = factory(\ProcessMaker\Model\BpmnProcess::class)->create();
return [
'EVN_UID' => $faker->regexify("/[a-zA-Z]{32}/"),
'PRJ_UID' => $bpmnProcess->PRJ_UID,
'PRO_UID' => $bpmnProcess->PRO_UID,
'EVN_NAME' => $faker->name,
'EVN_TYPE' => 'START',
'EVN_MARKER' => 'EMPTY',
'EVN_IS_INTERRUPTING' => 1,
'EVN_ATTACHED_TO' => '',
'EVN_CANCEL_ACTIVITY' => 0,
'EVN_ACTIVITY_REF' => null,
'EVN_WAIT_FOR_COMPLETION' => 0,
'EVN_ERROR_NAME' => null,
'EVN_ERROR_CODE' => null,
'EVN_ESCALATION_NAME' => null,
'EVN_ESCALATION_CODE' => null,
'EVN_CONDITION' => null,
'EVN_MESSAGE' => '',
'EVN_OPERATION_NAME' => null,
'EVN_OPERATION_IMPLEMENTATION_REF' => null,
'EVN_TIME_DATE' => null,
'EVN_TIME_CYCLE' => null,
'EVN_TIME_DURATION' => null,
'EVN_BEHAVIOR' => 'THROW',
];
});

View File

@@ -0,0 +1,20 @@
<?php
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\BpmnProcess::class, function(Faker $faker) {
return [
'PRO_UID' => $faker->regexify("/[a-zA-Z]{32}/"),
'PRJ_UID' => function() {
return factory(\ProcessMaker\Model\BpmnProject::class)->create()->PRJ_UID;
},
'DIA_UID' => function() {
return factory(\ProcessMaker\Model\BpmnDiagram::class)->create()->DIA_UID;
},
'PRO_NAME' => $faker->title,
'PRO_TYPE' => 'NONE',
'PRO_IS_EXECUTABLE' => 0,
'PRO_IS_CLOSED' => 0,
'PRO_IS_SUBPROCESS' => 0,
];
});

View File

@@ -0,0 +1,21 @@
<?php
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\EmailEvent::class, function(Faker $faker) {
$bpmnEvent = factory(\ProcessMaker\Model\BpmnEvent::class)->create();
return [
'EMAIL_EVENT_UID' => $faker->regexify("/[a-zA-Z]{32}/"),
'PRJ_UID' => $bpmnEvent->PRJ_UID,
'EVN_UID' => $bpmnEvent->EVN_UID,
'EMAIL_EVENT_FROM' => $faker->email,
'EMAIL_EVENT_TO' => $faker->email,
'EMAIL_EVENT_SUBJECT' => $faker->title,
'PRF_UID' => function() {
return factory(\ProcessMaker\Model\ProcessFiles::class)->create()->PRF_UID;
},
'EMAIL_SERVER_UID' => function() {
return factory(\ProcessMaker\Model\EmailServerModel::class)->create()->MESS_UID;
},
];
});

View File

@@ -0,0 +1,208 @@
<?php
namespace ProcessMaker\BusinessModel;
use Exception;
use Faker\Factory;
use G;
use ProcessMaker\BusinessModel\FilesManager;
use ProcessMaker\Model\EmailEvent as EmailEventModel;
use ProcessMaker\Model\Process as ProcessModel;
use ProcessMaker\Model\ProcessFiles as ProcessFilesModel;
use ProcessMaker\Model\User as UserModel;
use Tests\TestCase;
class FilesManagerTest extends TestCase
{
private $faker;
private $directories;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->directories = [];
}
/**
* Tear down method.
*/
public function tearDown()
{
parent::tearDown();
$this->directories = array_reverse($this->directories);
foreach ($this->directories as $value) {
rmdir($value);
}
}
/**
* This test verifies if a file is missing.
* @test
* @covers \ProcessMaker\BusinessModel\FilesManager::deleteProcessFilesManager()
*/
public function it_should_deleted_public_files_when_not_exist()
{
$proUid = G::generateUniqueID();
$prfUid = G::generateUniqueID();
$filesManager = new FilesManager();
$this->expectException(Exception::class);
$filesManager->deleteProcessFilesManager($proUid, $prfUid);
}
/**
* This represents the windows and linux separators.
*/
public function directorySeparator()
{
return [
["linux", "/"],
["windows", "\\"]
];
}
/**
* This test verifies the deletion of a template.
* @test
* @covers \ProcessMaker\BusinessModel\FilesManager::deleteProcessFilesManager()
* @dataProvider directorySeparator
*/
public function it_should_deleted_a_template_file($type, $separator)
{
$user = factory(UserModel::class)->create([
'USR_UID' => G::generateUniqueID()
]);
$process = factory(ProcessModel::class)->create([
'PRO_UID' => G::generateUniqueID()
]);
//create a template file
$directory = PATH_DATA_SITE;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$directory = PATH_DATA_PUBLIC;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$directory = PATH_DATA_PUBLIC . $process->PRO_UID;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$fileName = "template1.html";
$path = $directory . "/" . $fileName;
file_put_contents($path, $this->faker->randomHtml());
$processFiles = factory(ProcessFilesModel::class)->create([
'PRF_UID' => G::generateUniqueID(),
'PRO_UID' => $process->PRO_UID,
'USR_UID' => $user->USR_UID,
'PRF_PATH' => $separator . $fileName
]);
$filesManager = new FilesManager();
$filesManager->deleteProcessFilesManager($process->PRO_UID, $processFiles->PRF_UID);
//assert empty registry
$expectedEmptyObject = ProcessFilesModel::where('PRF_UID', '=', $processFiles->PRF_UID)->first();
$this->assertTrue(empty($expectedEmptyObject));
//assert empty file
$this->assertTrue(!file_exists($path));
}
/**
* This test verifies the deletion of a public file.
* @test
* @covers \ProcessMaker\BusinessModel\FilesManager::deleteProcessFilesManager()
* @dataProvider directorySeparator
*/
public function it_should_deleted_a_public_file($type, $separator)
{
$user = factory(UserModel::class)->create([
'USR_UID' => G::generateUniqueID()
]);
$process = factory(ProcessModel::class)->create([
'PRO_UID' => G::generateUniqueID()
]);
//create a temporal file
$directory = PATH_DATA_SITE;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$directory = PATH_DATA_MAILTEMPLATES;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$directory = PATH_DATA_MAILTEMPLATES . $process->PRO_UID;
if (!is_dir($directory)) {
mkdir($directory);
$this->directories[] = $directory;
}
$fileName = "temporal.html";
$path = $directory . "/" . $fileName;
file_put_contents($path, $this->faker->randomHtml());
$processFiles = factory(ProcessFilesModel::class)->create([
'PRF_UID' => G::generateUniqueID(),
'PRO_UID' => $process->PRO_UID,
'USR_UID' => $user->USR_UID,
'PRF_PATH' => $separator . $fileName
]);
$filesManager = new FilesManager();
$filesManager->deleteProcessFilesManager($process->PRO_UID, $processFiles->PRF_UID);
//assert empty registry
$expectedEmptyObject = ProcessFilesModel::where('PRF_UID', '=', $processFiles->PRF_UID)->first();
$this->assertTrue(empty($expectedEmptyObject));
//assert empty file
$this->assertTrue(!file_exists($path));
}
/**
* This test verifies the removal of a template that is being used by an
* intermediate email event.
* @test
* @covers \ProcessMaker\BusinessModel\FilesManager::deleteProcessFilesManager()
*/
public function it_should_deleted_public_files_with_event_relation()
{
$user = factory(UserModel::class)->create([
'USR_UID' => G::generateUniqueID()
]);
$process = factory(ProcessModel::class)->create([
'PRO_UID' => G::generateUniqueID()
]);
$processFiles = factory(ProcessFilesModel::class)->create([
'PRF_UID' => G::generateUniqueID(),
'PRO_UID' => $process->PRO_UID,
'USR_UID' => $user->USR_UID,
'PRF_PATH' => '/'
]);
$emailEvent = factory(EmailEventModel::class)->create([
'PRF_UID' => $processFiles->PRF_UID
]);
$filesManager = new FilesManager();
$this->expectException(Exception::class);
$filesManager->deleteProcessFilesManager($process->PRO_UID, $processFiles->PRF_UID);
}
}

View File

@@ -1,12 +1,14 @@
<?php
namespace ProcessMaker\BusinessModel;
use EmailEventPeer;
use Exception;
use G;
use Criteria;
use ProcessFiles;
use ProcessFilesPeer;
use ProcessPeer;
use ResultSet;
use TaskPeer;
class FilesManager
@@ -671,62 +673,60 @@ class FilesManager
}
/**
*
* @param string $sProcessUID {@min 32} {@max 32}
* Deletes the physical file and its corresponding record in the database.
* @param string $proUid {@min 32} {@max 32}
* @param string $prfUid {@min 32} {@max 32}
*
*
* @param bool $verifyingRelationship
* @access public
* @throws Exception
*/
public function deleteProcessFilesManager($sProcessUID, $prfUid, $verifyingRelationship = false)
public function deleteProcessFilesManager($proUid, $prfUid, $verifyingRelationship = false)
{
try {
$path = '';
$criteriaPf = new \Criteria("workflow");
$criteriaPf->addSelectColumn(\ProcessFilesPeer::PRF_PATH);
$criteriaPf->add(\ProcessFilesPeer::PRF_UID, $prfUid, \Criteria::EQUAL);
$rsCriteria = \ProcessFilesPeer::doSelectRS($criteriaPf);
$rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC);
$rsCriteria->next();
while ($aRow = $rsCriteria->getRow()) {
$path = $aRow['PRF_PATH'];
$rsCriteria->next();
$criteriaProcessFiles = new Criteria("workflow");
$criteriaProcessFiles->addSelectColumn(ProcessFilesPeer::PRF_PATH);
$criteriaProcessFiles->add(ProcessFilesPeer::PRF_UID, $prfUid, Criteria::EQUAL);
$resultSet1 = ProcessFilesPeer::doSelectRS($criteriaProcessFiles);
$resultSet1->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$resultSet1->next();
while ($row = $resultSet1->getRow()) {
$path = $row['PRF_PATH'];
$resultSet1->next();
}
if ($path == '') {
throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('prf_uid')));
throw new Exception(G::LoadTranslation("ID_INVALID_VALUE_FOR", array('prf_uid')));
}
$relationshipEmailEvent = false;
$criteria = new \Criteria("workflow");
$criteria->addSelectColumn(\EmailEventPeer::PRF_UID);
$criteria->add(\EmailEventPeer::PRF_UID, $prfUid, \Criteria::EQUAL);
$rsCriteria = \EmailEventPeer::doSelectRS($criteria);
$rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC);
$rsCriteria->next();
while ($aRow = $rsCriteria->getRow()) {
$criteria = new Criteria("workflow");
$criteria->addSelectColumn(EmailEventPeer::PRF_UID);
$criteria->add(EmailEventPeer::PRF_UID, $prfUid, Criteria::EQUAL);
$resultSet2 = EmailEventPeer::doSelectRS($criteria);
$resultSet2->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$resultSet2->next();
while ($row = $resultSet2->getRow()) {
$relationshipEmailEvent = true;
$rsCriteria->next();
$resultSet2->next();
}
$explodePath = explode(DIRECTORY_SEPARATOR,$path);
$path = str_replace("\\", "/", $path);
$fileName = basename($path);
if ($relationshipEmailEvent && !$verifyingRelationship) {
throw new \Exception(\G::LoadTranslation(G::LoadTranslation('ID_CANNOT_REMOVE_TEMPLATE_EMAIL_EVENT',
[end($explodePath)])));
throw new Exception(G::LoadTranslation(G::LoadTranslation('ID_CANNOT_REMOVE_TEMPLATE_EMAIL_EVENT', [$fileName])));
}
$sFile = end($explodePath);
$path = PATH_DATA_MAILTEMPLATES.$sProcessUID.DIRECTORY_SEPARATOR.$sFile;
$path = PATH_DATA_MAILTEMPLATES . $proUid . "/" . $fileName;
if (file_exists($path) && !is_dir($path)) {
unlink($path);
} else {
$path = PATH_DATA_PUBLIC.$sProcessUID.DIRECTORY_SEPARATOR.$sFile;
if (file_exists($path) && !is_dir($path)) {
unlink($path);
}
$path = PATH_DATA_PUBLIC . $proUid . "/" . $fileName;
if (file_exists($path) && !is_dir($path)) {
unlink($path);
}
}
$rs = \ProcessFilesPeer::doDelete($criteriaPf);
ProcessFilesPeer::doDelete($criteriaProcessFiles);
} catch (Exception $e) {
throw $e;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class BpmnDiagram extends Model
{
protected $table = 'BPMN_DIAGRAM';
public $timestamps = false;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class BpmnEvent extends Model
{
protected $table = 'BPMN_EVENT';
public $timestamps = false;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class BpmnProcess extends Model
{
protected $table = 'BPMN_PROCESS';
public $timestamps = false;
}

View File

@@ -9,6 +9,8 @@ class BpmnProject extends Model
// Set our table name
protected $table = 'BPMN_PROJECT';
protected $primaryKey = 'PRJ_UID';
public $incrementing = false;
// We do not have create/update timestamps for this table
public $timestamps = false;
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class EmailEvent extends Model
{
protected $table = 'EMAIL_EVENT';
public $timestamps = false;
}

View File

@@ -8,6 +8,7 @@ class ProcessFiles extends Model
{
protected $table = 'PROCESS_FILES';
protected $primaryKey = 'PRF_UID';
public $incrementing = false;
public $timestamps = false;
}