From 425a83e753940eb7863dce45932d273561e4c310 Mon Sep 17 00:00:00 2001 From: Paula Quispe Date: Thu, 4 Jun 2020 10:38:48 -0400 Subject: [PATCH] PMCORE-1542 --- database/factories/DocumentsFactory.php | 54 ++++++++++ gulliver/system/class.g.php | 2 + tests/resources/images/activate.png | Bin 0 -> 750 bytes tests/resources/images/activity.gif | Bin 0 -> 6610 bytes .../ProcessMaker/BusinessModel/CasesTest.php | 59 +++++++++++ .../src/ProcessMaker/Model/DocumentsTest.php | 29 ++++++ .../Util/Helpers/SaveAppDocumentTest.php | 47 +++++++++ workflow/engine/classes/WsBase.php | 19 ++-- workflow/engine/classes/class.pmFunctions.php | 6 +- workflow/engine/classes/model/AppNotes.php | 17 +++- .../model/map/AppDocumentMapBuilder.php | 2 +- workflow/engine/config/schema.xml | 2 +- .../src/ProcessMaker/BusinessModel/Cases.php | 80 +++++++++++++++ .../src/ProcessMaker/Model/Documents.php | 95 ++++++++++++++++++ .../engine/src/ProcessMaker/Util/helpers.php | 36 +++++++ 15 files changed, 434 insertions(+), 14 deletions(-) create mode 100644 database/factories/DocumentsFactory.php create mode 100644 tests/resources/images/activate.png create mode 100644 tests/resources/images/activity.gif create mode 100644 tests/unit/workflow/engine/src/ProcessMaker/Model/DocumentsTest.php create mode 100644 tests/unit/workflow/engine/src/ProcessMaker/Util/Helpers/SaveAppDocumentTest.php create mode 100644 workflow/engine/src/ProcessMaker/Model/Documents.php diff --git a/database/factories/DocumentsFactory.php b/database/factories/DocumentsFactory.php new file mode 100644 index 000000000..acfafb0ce --- /dev/null +++ b/database/factories/DocumentsFactory.php @@ -0,0 +1,54 @@ +define(\ProcessMaker\Model\Documents::class, function (Faker $faker) { + $types = ['INPUT', 'OUTPUT', 'ATTACHED']; + $type = $faker->randomElement($types); + return [ + 'APP_DOC_UID' => G::generateUniqueID(), + 'APP_DOC_FILENAME' => 'image.png', + 'APP_DOC_TITLE' => '', + 'APP_DOC_COMMENT' => '', + 'DOC_VERSION' => 1, + 'APP_UID' => G::generateUniqueID(), + 'DEL_INDEX' => 1, + 'DOC_UID' => G::generateUniqueID(), + 'USR_UID' => G::generateUniqueID(), + 'APP_DOC_TYPE' => $type, + 'APP_DOC_CREATE_DATE' => $faker->date(), + 'APP_DOC_INDEX' => 1, + 'FOLDER_UID' => G::generateUniqueID(), + 'APP_DOC_PLUGIN' => '', + 'APP_DOC_TAGS' => '', + 'APP_DOC_STATUS' => 'ACTIVE', + 'APP_DOC_STATUS_DATE' => $faker->date(), + 'APP_DOC_FIELDNAME' => '', + 'APP_DOC_DRIVE_DOWNLOAD' => '', + ]; +}); + +// Create a dynaform with the foreign keys +$factory->state(\ProcessMaker\Model\Documents::class, 'case_notes', function (Faker $faker) { + return [ + 'APP_DOC_UID' => G::generateUniqueID(), + 'APP_DOC_FILENAME' => 'image.png', + 'APP_DOC_TITLE' => '', + 'APP_DOC_COMMENT' => '', + 'DOC_VERSION' => 1, + 'APP_UID' => G::generateUniqueID(), + 'DEL_INDEX' => 1, + 'DOC_UID' => G::generateUniqueID(), + 'USR_UID' => G::generateUniqueID(), + 'APP_DOC_TYPE' => 'CASE_NOTE', + 'APP_DOC_CREATE_DATE' => $faker->date(), + 'APP_DOC_INDEX' => 1, + 'FOLDER_UID' => G::generateUniqueID(), + 'APP_DOC_PLUGIN' => '', + 'APP_DOC_TAGS' => '', + 'APP_DOC_STATUS' => 'ACTIVE', + 'APP_DOC_STATUS_DATE' => $faker->date(), + 'APP_DOC_FIELDNAME' => '', + 'APP_DOC_DRIVE_DOWNLOAD' => '', + ]; +}); diff --git a/gulliver/system/class.g.php b/gulliver/system/class.g.php index ee129521e..8e9e9af86 100644 --- a/gulliver/system/class.g.php +++ b/gulliver/system/class.g.php @@ -2708,6 +2708,8 @@ class G $nameToSave = $filter->validateInput($nameToSave, "path"); @chmod($path . "/" . $nameToSave, $permission); umask($oldumask); + + return true; } catch (Exception $oException) { throw $oException; } diff --git a/tests/resources/images/activate.png b/tests/resources/images/activate.png new file mode 100644 index 0000000000000000000000000000000000000000..1be605c56c14b9b49d46d78d8f269193f1908316 GIT binary patch literal 750 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igi2 z6&wl0^#N%B00M4FL_t(I%cYXvOOsI?#-Gj2HJN7FQZ^jRJ2ituvx1N=Gy6BXjVQd4 zj3N?@b`kyl2fFE|4C$g9wJfx&rCS4o+RVW=b#uP&dwzaT7tR;Wx`-Y)HwT{2d7kh2 zdW50WIv5R5Tk#CkrjExgQB)7Jnbc08V)3S-I93z1;-aqr>Yc!3pAZFJ1z@gQq|ha?3>3W5YUF*k)E0j@dHn<+#ZBG5+1TmUD=Y-Kmv%7(0U z-ffh-08Dc*?LaccT!5`?!-=6PtB^+SGYXOrdOMM13XWn>wlXe2kO)dr*pM3lu;)ct zt0ScZ34*dD3<$(^5CFUYP?43Ktu2HDVU$G~RawQBv|uS47PlZA4rNJ*vOrVoK`_lB zHe}8P6s_XOY++{gSg2zg;#6R93*6c^$}I)HF3=clM1M;^W`9htvH}~~vqiMy2&Y@mU?wyDZEa!w>e9XRge%okz gol0cHUjhHBUvhNKI-;$=ZvX%Q07*qoM6N<$g00L$VgLXD literal 0 HcmV?d00001 diff --git a/tests/resources/images/activity.gif b/tests/resources/images/activity.gif new file mode 100644 index 0000000000000000000000000000000000000000..94d46c129f6bba02f2f0b230d9f4d2c7a48e1412 GIT binary patch literal 6610 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 AkpKVy literal 0 HcmV?d00001 diff --git a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php index 99778d4f2..0b988bf49 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php @@ -5,6 +5,8 @@ namespace ProcessMaker\BusinessModel; use Exception; use G; use ProcessMaker\Model\Application; +use ProcessMaker\Model\Delegation; +use ProcessMaker\Model\Documents; use RBAC; use Tests\TestCase; @@ -77,4 +79,61 @@ class CasesTest extends TestCase $case = new Cases(); $case->deleteCase($application->APP_UID, $_SESSION['USER_LOGGED']); } + + /** + * Review the upload file related to the case notes, an return an exception when the array is empty + * + * @covers \ProcessMaker\BusinessModel\Cases::uploadFilesInCaseNotes() + * + * @test + * + * @expectedException Exception + */ + public function it_return_exception_in_upload_files_related_case_note() + { + $application = factory(Application::class)->create(); + factory(Delegation::class)->states('foreign_keys')->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'APP_UID' => $application->APP_UID + ]); + // Upload the file + $case = new Cases(); + // Return an exception because the files does not exist + $case->uploadFilesInCaseNotes('00000000000000000000000000000001', $application->APP_UID, $filesReferences = []); + } + + /** + * Review the upload file related to the case notes + * + * @covers \ProcessMaker\BusinessModel\Cases::uploadFilesInCaseNotes() + * + * @test + */ + public function it_should_upload_files_related_case_note() + { + $application = factory(Application::class)->create(); + factory(Delegation::class)->states('foreign_keys')->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'APP_UID' => $application->APP_UID + ]); + // File reference to upload + $filesReferences = [ + 'activityRename.gif' => PATH_TRUNK . 'tests' . PATH_SEP . 'resources' . PATH_SEP . 'images' . PATH_SEP . 'activity.gif', + ]; + // Path of the case + $pathCase = PATH_DB . config('system.workspace') . PATH_SEP . 'files' . PATH_SEP . $application->APP_UID . PATH_SEP; + // Upload the file + $case = new Cases(); + $result = $case->uploadFilesInCaseNotes('00000000000000000000000000000001', $application->APP_UID, $filesReferences); + $result = head($result); + $this->assertNotEmpty($result); + $this->assertArrayHasKey('APP_UID', $result); + $this->assertEquals($application->APP_UID, $result['APP_UID']); + $this->assertArrayHasKey('APP_DOC_TYPE', $result); + $this->assertEquals(Documents::DOC_TYPE_CASE_NOTE, $result['APP_DOC_TYPE']); + $this->assertArrayHasKey('APP_DOC_FILENAME', $result); + $this->assertEquals('activityRename.gif', $result['APP_DOC_FILENAME']); + + G::rm_dir($pathCase); + } } diff --git a/tests/unit/workflow/engine/src/ProcessMaker/Model/DocumentsTest.php b/tests/unit/workflow/engine/src/ProcessMaker/Model/DocumentsTest.php new file mode 100644 index 000000000..bc882b79d --- /dev/null +++ b/tests/unit/workflow/engine/src/ProcessMaker/Model/DocumentsTest.php @@ -0,0 +1,29 @@ +states('case_notes')->create(); + $doc = new Documents(); + $res = $doc->getAppFiles($appDoc->APP_UID, Documents::DOC_TYPE_CASE_NOTE); + $this->assertNotEmpty($res); + } +} \ No newline at end of file diff --git a/tests/unit/workflow/engine/src/ProcessMaker/Util/Helpers/SaveAppDocumentTest.php b/tests/unit/workflow/engine/src/ProcessMaker/Util/Helpers/SaveAppDocumentTest.php new file mode 100644 index 000000000..4f1079a08 --- /dev/null +++ b/tests/unit/workflow/engine/src/ProcessMaker/Util/Helpers/SaveAppDocumentTest.php @@ -0,0 +1,47 @@ + PATH_TRUNK . 'tests' . PATH_SEP . 'resources' . PATH_SEP . 'images' . PATH_SEP . 'activate.png', + 'tmp_name' => PATH_TRUNK . 'tests' . PATH_SEP . 'resources' . PATH_SEP . 'images' . PATH_SEP . 'activate.png', + ]; + $appUid = G::generateUniqueID(); + $appDocUid = G::generateUniqueID(); + $pathCase = PATH_DB . config('system.workspace') . PATH_SEP . 'files' . PATH_SEP . G::getPathFromUID($appUid) . PATH_SEP; + saveAppDocument($files, $appUid, $appDocUid, 1, false); + $this->assertFileExists($pathCase . $appDocUid . '_1.png'); + G::rm_dir($pathCase); + } + + /** + * It test if the file reference was uploaded + * + * @test + */ + public function it_should_copy_file_different_name() + { + $files = [ + 'name' => 'activityRename.gif', + 'tmp_name' => PATH_TRUNK . 'tests' . PATH_SEP . 'resources' . PATH_SEP . 'images' . PATH_SEP . 'activity.gif', + ]; + $appUid = G::generateUniqueID(); + $appDocUid = G::generateUniqueID(); + $pathCase = PATH_DB . config('system.workspace') . PATH_SEP . 'files' . PATH_SEP . G::getPathFromUID($appUid) . PATH_SEP; + saveAppDocument($files, $appUid, $appDocUid, 1, false); + $this->assertFileExists($pathCase . $appDocUid . '_1.gif'); + G::rm_dir($pathCase); + } +} \ No newline at end of file diff --git a/workflow/engine/classes/WsBase.php b/workflow/engine/classes/WsBase.php index 898b2af56..268c9293a 100644 --- a/workflow/engine/classes/WsBase.php +++ b/workflow/engine/classes/WsBase.php @@ -3420,16 +3420,17 @@ class WsBase /** * Add case note * - * @param string caseUid : ID of the case. - * @param string processUid : ID of the process. - * @param string taskUid : ID of the task. - * @param string userUid : The unique ID of the user who will add note case. - * @param string note : Note of the case. - * @param int sendMail : Optional parameter. If set to 1, will send an email to all participants in the case. + * @param string $caseUid, ID of the case. + * @param string $processUid, ID of the process. + * @param string $taskUid, ID of the task. + * @param string $userUid, The unique ID of the user who will add note case. + * @param string $note, Note of the case. + * @param int $sendMail, Optional parameter. If set to 1, will send an email to all participants in the case. + * @param array $files, Optional parameter. This is an array of files. * - * @return $result will return an object + * @return object */ - public function addCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail = 1) + public function addCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail = 1, $files = []) { try { if (empty($caseUid)) { @@ -3475,7 +3476,7 @@ class WsBase //Add note case $appNote = new AppNotes(); - $response = $appNote->addCaseNote($caseUid, $userUid, $note, $sendMail); + $response = $appNote->addCaseNote($caseUid, $userUid, $note, $sendMail, $files); //Response $result = new WsResponse(0, G::LoadTranslation("ID_COMMAND_EXECUTED_SUCCESSFULLY")); diff --git a/workflow/engine/classes/class.pmFunctions.php b/workflow/engine/classes/class.pmFunctions.php index e99854804..5193afb66 100644 --- a/workflow/engine/classes/class.pmFunctions.php +++ b/workflow/engine/classes/class.pmFunctions.php @@ -2887,13 +2887,15 @@ function PMFUnpauseCase ($caseUid, $delIndex, $userUid) * @param string(32) | $userUid | ID user | The unique ID of the user who will add note case. * @param string | $note | Note of the case | Note of the case. * @param int | $sendMail = 1 | Send mail | Optional parameter. If set to 1, will send an email to all participants in the case. + * @param array | $files | Array of files | An array of files (full paths) to be attached to the case notes. + * * @return int | $result | Result of the add a case note | Returns 1 if the note has been added to the case.; otherwise, returns 0 if an error occurred. * */ -function PMFAddCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail = 1) +function PMFAddCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail = 1, $files = []) { $ws = new WsBase(); - $result = $ws->addCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail); + $result = $ws->addCaseNote($caseUid, $processUid, $taskUid, $userUid, $note, $sendMail, $files); if ($result->status_code == 0) { return 1; diff --git a/workflow/engine/classes/model/AppNotes.php b/workflow/engine/classes/model/AppNotes.php index 6e99dc408..3081d519c 100644 --- a/workflow/engine/classes/model/AppNotes.php +++ b/workflow/engine/classes/model/AppNotes.php @@ -260,10 +260,25 @@ class AppNotes extends BaseAppNotes } } - public function addCaseNote($applicationUid, $userUid, $note, $sendMail) + /** + * Add a note in the case and send an email + * + * @param string $applicationUid + * @param string $userUid + * @param string $note + * @param bool $sendMail + * @param array $files + * + * @return array + */ + public function addCaseNote($applicationUid, $userUid, $note, $sendMail, $files) { $response = $this->postNewNote($applicationUid, $userUid, $note, false); + // Check the files to upload + $case = new Cases(); + $res = $case->uploadFilesInCaseNotes($userUid, $applicationUid, $files, null); + if ($sendMail == 1) { $case = new Cases(); diff --git a/workflow/engine/classes/model/map/AppDocumentMapBuilder.php b/workflow/engine/classes/model/map/AppDocumentMapBuilder.php index c0a6495d2..f8171cacb 100644 --- a/workflow/engine/classes/model/map/AppDocumentMapBuilder.php +++ b/workflow/engine/classes/model/map/AppDocumentMapBuilder.php @@ -127,7 +127,7 @@ class AppDocumentMapBuilder $tMap->addValidator('USR_UID', 'required', 'propel.validator.RequiredValidator', '', 'User UID is required.'); - $tMap->addValidator('APP_DOC_TYPE', 'validValues', 'propel.validator.ValidValuesValidator', 'INPUT|OUTPUT|ATTACHED', 'Please select a valid document type.'); + $tMap->addValidator('APP_DOC_TYPE', 'validValues', 'propel.validator.ValidValuesValidator', 'INPUT|OUTPUT|ATTACHED|CASE_NOTE', 'Please select a valid document type.'); $tMap->addValidator('APP_DOC_TYPE', 'required', 'propel.validator.RequiredValidator', '', 'Application Document Type is required.'); diff --git a/workflow/engine/config/schema.xml b/workflow/engine/config/schema.xml index 24e4d7490..4d945b5dd 100644 --- a/workflow/engine/config/schema.xml +++ b/workflow/engine/config/schema.xml @@ -284,7 +284,7 @@ - + diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php index c8e078d8a..d99b4c597 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php @@ -42,6 +42,7 @@ use ProcessMaker\Core\System; use ProcessMaker\Exception\UploadException; use ProcessMaker\Model\Application as ModelApplication; use ProcessMaker\Model\Delegation; +use ProcessMaker\Model\Documents; use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Services\OAuth2\Server; use ProcessMaker\Util\DateTime as UtilDateTime; @@ -3843,6 +3844,85 @@ class Cases return $response; } + /** + * Upload file related to the case notes + * + * @param string $userUid + * @param string $appUid + * @param array $filesReferences + * @param string $appDocUid + * + * @return array + * @throws Exception + */ + public function uploadFilesInCaseNotes($userUid, $appUid, $filesReferences = [], $appDocUid = null) + { + if (!empty($_FILES["form"]["name"])) { + $upload = true; + // Array from post upload + foreach ($_FILES["form"]["name"] as $fileIndex => $fileName) { + if (!is_array($fileName)) { + $files[] = [ + 'name' => $_FILES["form"]["name"][$fileIndex], + 'tmp_name' => $_FILES["form"]["tmp_name"][$fileIndex], + 'error' => $_FILES["form"]["error"][$fileIndex] + ]; + } + } + } elseif (!empty($filesReferences)) { + $upload = false; + // Array with path references + foreach ($filesReferences as $fileIndex => $fileName) { + $nameFile = !is_numeric($fileIndex) ? basename($fileIndex) : basename($fileName); + $files[] = [ + 'name' => $nameFile, + 'tmp_name' => $fileName, + 'error' => UPLOAD_ERR_OK + ]; + } + } + + // Get the delIndex related to the case + $cases = new ClassesCases(); + $delIndex = $cases->getCurrentDelegation($appUid); + + // We will to register the files in the database + $response = []; + if (!empty($files)) { + $i = 0; + foreach ($files as $fileIndex => $fileName) { + // There is no error, the file uploaded with success + if ($fileName["error"] === UPLOAD_ERR_OK) { + $appDocUid = G::generateUniqueID(); + $attributes = [ + "APP_DOC_UID" => $appDocUid, + "DOC_VERSION" => 1, + "APP_UID" => $appUid, + "DEL_INDEX" => $delIndex, + "USR_UID" => $userUid, + "DOC_UID" => -1, + "APP_DOC_TYPE" => 'CASE_NOTE', + "APP_DOC_CREATE_DATE" => date("Y-m-d H:i:s"), + "APP_DOC_FILENAME" => $fileName["name"] + ]; + Documents::create($attributes); + + // Upload or move the file + $isUploaded = saveAppDocument($fileName, $appUid, $appDocUid, 1, $upload); + + // List of files uploaded or copy + $response[$i++] = $attributes; + } else { + throw new UploadException($fileName['error']); + } + } + } else { + throw new Exception(G::LoadTranslation('ID_ERROR_UPLOAD_FILE_CONTACT_ADMINISTRATOR')); + } + + return $response; + } + /** * Run the validations related to an Input Document * diff --git a/workflow/engine/src/ProcessMaker/Model/Documents.php b/workflow/engine/src/ProcessMaker/Model/Documents.php new file mode 100644 index 000000000..5e915cc69 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Model/Documents.php @@ -0,0 +1,95 @@ + '', + 'APP_DOC_COMMENT' => '', + 'DOC_UID' => '-1', + 'FOLDER_UID' => '', + 'APP_DOC_PLUGIN' => '', + 'APP_DOC_TAGS' => '', + 'APP_DOC_FIELDNAME' => '', + 'APP_DOC_DRIVE_DOWNLOAD' => 'a:0:{}', + 'SYNC_WITH_DRIVE' => 'UNSYNCHRONIZED', + 'SYNC_PERMISSIONS' => '', + 'APP_DOC_STATUS_DATE' => '', + ]; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'APP_DOC_UID', + 'DOC_VERSION', + 'APP_DOC_FILENAME', + 'APP_UID', + 'DEL_INDEX', + 'DOC_UID', + 'USR_UID', + 'APP_DOC_TYPE', + 'APP_DOC_CREATE_DATE', + 'APP_DOC_INDEX', + 'FOLDER_UID', + 'APP_DOC_STATUS', + ]; + + /** + * Scope a query to filter an specific case + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $proUid + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeAppUid($query, string $appUid) + { + return $query->where('APP_UID', $appUid); + } + + /** + * Return the documents related to the case + * + * @param int $proId + * @param string $type + * + * @return array + */ + public static function getAppFiles(string $appUid, $type = 'CASE_NOTES') + { + $query = Documents::query()->select(); + $query->appUid($appUid); + $query->where('APP_DOC_TYPE', $type); + $results = $query->get(); + $documentList = []; + $results->each(function ($item, $key) use (&$documentList) { + $documentList[] = $item->toArray(); + }); + + return $documentList; + } +} diff --git a/workflow/engine/src/ProcessMaker/Util/helpers.php b/workflow/engine/src/ProcessMaker/Util/helpers.php index 22272a78e..a844b2eaa 100644 --- a/workflow/engine/src/ProcessMaker/Util/helpers.php +++ b/workflow/engine/src/ProcessMaker/Util/helpers.php @@ -601,3 +601,39 @@ function getMysqlVersion() return $mysqlVersion; } + +/** + * Move the uploaded file to the documents folder + * + * @param array $file + * @param string $appUid + * @param string $appDocUid + * @param int $version + * + * @return string + */ +function saveAppDocument($file, $appUid, $appDocUid, $version = 1, $upload = true) +{ + try { + $info = pathinfo($file["name"]); + $extension = ((isset($info["extension"])) ? $info["extension"] : ""); + //$pathCase = G::getPathFromUID($appUid); + $fileName = $appDocUid . "_" . $version . "." . $extension; + + $pathCase = PATH_DATA_SITE . 'files' . PATH_SEP . G::getPathFromUID($appUid) . PATH_SEP; + + $response = false; + if ($upload) { + $response = G::uploadFile( + $file["tmp_name"], + $pathCase, + $fileName + ); + } else { + G::verifyPath($pathCase, true); + $response = copy($file["tmp_name"], $pathCase . $fileName); + } + } catch (Exception $e) { + throw $e; + } +}