diff --git a/gulliver/system/class.g.php b/gulliver/system/class.g.php index 8e9e9af86..ee129521e 100644 --- a/gulliver/system/class.g.php +++ b/gulliver/system/class.g.php @@ -2708,8 +2708,6 @@ class G $nameToSave = $filter->validateInput($nameToSave, "path"); @chmod($path . "/" . $nameToSave, $permission); umask($oldumask); - - return true; } catch (Exception $oException) { throw $oException; } diff --git a/tests/unit/workflow/engine/classes/model/AppNotesTest.php b/tests/unit/workflow/engine/classes/model/AppNotesTest.php index 4d8b3feda..b86714211 100644 --- a/tests/unit/workflow/engine/classes/model/AppNotesTest.php +++ b/tests/unit/workflow/engine/classes/model/AppNotesTest.php @@ -219,7 +219,7 @@ class AppNotesTest extends TestCase $appUid = $appDocument->APP_UID; $appNotes = new ModelAppNotes(); - $result = $appNotes->getAttachedFilesFromTheCaseNote($appUid); + $result = $appNotes->getAttachedFilesFromTheCaseNote($appNote->NOTE_ID); $this->assertNotEmpty($result); } diff --git a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php index 3c7da31c5..aa55a5548 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/CasesTest.php @@ -124,7 +124,8 @@ class CasesTest extends TestCase // Upload the file $case = new Cases(); $result = $case->uploadFilesInCaseNotes('00000000000000000000000000000001', $application->APP_UID, $filesReferences); - $result = head($result); + $this->assertNotEmpty($result['attachments']); + $result = head($result['attachments']); $this->assertNotEmpty($result); $this->assertArrayHasKey('APP_UID', $result); $this->assertEquals($application->APP_UID, $result['APP_UID']); diff --git a/workflow/engine/classes/model/AppNotes.php b/workflow/engine/classes/model/AppNotes.php index 17c885359..e659bab4f 100644 --- a/workflow/engine/classes/model/AppNotes.php +++ b/workflow/engine/classes/model/AppNotes.php @@ -181,6 +181,7 @@ class AppNotes extends BaseAppNotes * @param string $noteRecipients * @param string $from * @param integer $delIndex + * @param integer $noteId * @return void * @throws Exception * @@ -188,7 +189,15 @@ class AppNotes extends BaseAppNotes * @see AppNotes->postNewNote() * @see workflow/engine/src/ProcessMaker/Util/helpers.php::postNote() */ - public function sendNoteNotification($appUid, $usrUid, $noteContent, $noteRecipients, $from = '', $delIndex = 0) + public function sendNoteNotification( + $appUid, + $usrUid, + $noteContent, + $noteRecipients, + $from = '', + $delIndex = 0, + $noteId = 0 + ) { try { $configuration = System::getEmailConfiguration(); @@ -216,9 +225,13 @@ class AppNotes extends BaseAppNotes $configNoteNotification['body'] = $this->getBodyCaseNote($authorName, $noteContent); $body = nl2br(G::replaceDataField($configNoteNotification['body'], $fieldCase, 'mysql', false)); - $attachFileLinks = $this->getAttachedFilesFromTheCaseNote($appUid); + // Get the files related to the specific case note + if ($noteId !== 0) { + $attachFileLinks = $this->getAttachedFilesFromTheCaseNote($noteId); + } + if (!empty($attachFileLinks)) { - $body = $body . "
" . G::LoadTranslation('ID_ATTACHED_FILES') . ": " . implode("
", $attachFileLinks) . "."; + $body = $body . "
" . G::LoadTranslation('ID_ATTACHED_FILES') . ": 
" . implode("
", $attachFileLinks); } $users = new Users(); $recipientsArray = explode(",", $noteRecipients); @@ -267,19 +280,20 @@ class AppNotes extends BaseAppNotes } /** - * Get attached files from the case note, this require appUid. - * @param string $appUid + * Get attached files from a specific case note + * @param int $docId * @return array */ - public function getAttachedFilesFromTheCaseNote(string $appUid): array + public function getAttachedFilesFromTheCaseNote(int $docId): array { $attachFileLinks = []; $url = System::getServerMainPath(); - $result = Documents::getAttachedFilesFromTheCaseNote($appUid); - $result->each(function($item) use($url, &$attachFileLinks) { - $href = $url . "/cases/casesShowCaseNotes?a={$item->APP_DOC_UID}=&v={$item->DOC_VERSION}"; - $attachFileLinks[] = "{$item->APP_DOC_FILENAME}"; - }); + $result = Documents::getFiles($docId); + foreach ($result as $item) { + $href = $url . "/cases/casesShowCaseNotes?a={$item['APP_DOC_UID']}=&v={$item['DOC_VERSION']}"; + $attachFileLinks[] = "{$item['APP_DOC_FILENAME']}"; + } + return $attachFileLinks; } diff --git a/workflow/engine/controllers/appProxy.php b/workflow/engine/controllers/appProxy.php index 3d9f519f4..ab30a6028 100644 --- a/workflow/engine/controllers/appProxy.php +++ b/workflow/engine/controllers/appProxy.php @@ -1,4 +1,17 @@ tas; } + + // Get user logged $usrUid = $_SESSION['USER_LOGGED']; + // Review if the user has the permissions $respView = $case->getAllObjectsFrom($proUid, $appUid, $tasUid, $usrUid, "VIEW", $delIndex); $respBlock = $case->getAllObjectsFrom($proUid, $appUid, $tasUid, $usrUid, "BLOCK", $delIndex); - if ($respView['CASES_NOTES'] == 0 && $respBlock['CASES_NOTES'] == 0) { return [ 'totalCount' => 0, @@ -99,27 +114,30 @@ class AppProxy extends HttpProxyController ]; } - $usrUid = isset($_SESSION['USER_LOGGED']) ? $_SESSION['USER_LOGGED'] : ""; - $appNotes = new AppNotes(); - $response = $appNotes->getNotesList($appUid, '', $httpData->start, $httpData->limit); + // Get the notes + $appNote = new Notes(); + $response = $appNote->getNotes($appUid, $httpData->start, $httpData->limit); $response = AppNotes::applyHtmlentitiesInNotes($response); + // Prepare the response + $documents = new Documents(); $iterator = 0; - foreach ($response['array']['notes'] as $value) { - $response ['array']['notes'][$iterator]['NOTE_DATE'] = DateTime::convertUtcToTimeZone($value['NOTE_DATE']); + foreach ($response['notes'] as $value) { + $response['notes'][$iterator]['NOTE_DATE'] = DateTime::convertUtcToTimeZone($value['NOTE_DATE']); + $response['notes'][$iterator]['attachments'] = $documents->getFiles($value['NOTE_ID']); $iterator++; } require_once("classes/model/Application.php"); - $oApplication = new Application(); - $aApplication = $oApplication->Load($appUid); - $response['array']['appTitle'] = $aApplication['APP_TITLE']; + $application = new Application(); + $appInfo = $application->Load($appUid); + $response['appTitle'] = $appInfo['APP_TITLE']; - return $response['array']; + return $response; } /** - * post Note Action + * Post a note * * @param string $httpData->appUid (optional, if it is not passed try use $_SESSION['APPLICATION']) * @return array containg the case notes @@ -143,9 +161,10 @@ class AppProxy extends HttpProxyController $this->setSendResponse(false); //Add note case - $appNote = new AppNotes(); + $cases = new BmCases(); try { - $response = $appNote->addCaseNote($appUid, $usrUid, $noteContent, intval($httpData->swSendMail)); + $sendMail = intval($httpData->swSendMail); + $response = $cases->addNote($appUid, $usrUid, $noteContent, $sendMail); } catch (Exception $error) { $response = new stdclass(); $response->success = 'success'; diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php index 15727a9c9..571ab3b66 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php @@ -14,6 +14,7 @@ use AppHistoryPeer; use Application; use ApplicationPeer; use Applications; +use AppNotes; use AppNotesPeer; use AppSolr; use BasePeer; @@ -41,7 +42,7 @@ use ProcessMaker\BusinessModel\User as BmUser; use ProcessMaker\Core\System; use ProcessMaker\Exception\UploadException; use ProcessMaker\Model\Application as ModelApplication; -use ProcessMaker\Model\AppNotes; +use ProcessMaker\Model\AppNotes as Notes; use ProcessMaker\Model\Delegation; use ProcessMaker\Model\Documents; use ProcessMaker\Plugins\PluginRegistry; @@ -3869,16 +3870,25 @@ class Cases "NOTE_AVAILABILITY" => "PUBLIC", "NOTE_RECIPIENTS" => "" ]; - $response = AppNotes::create($attributes); + $newNote = Notes::create($attributes); // Get the FK - $noteId = $response->NOTE_ID; + $noteId = $newNote->NOTE_ID; + $attachments = []; // Register the files related to the note - $this->uploadFilesInCaseNotes($userUid, $appUid, $files, $noteId); + if (!empty($files) || !empty($_FILES["filesToUpload"])) { + $filesResponse = $this->uploadFilesInCaseNotes($userUid, $appUid, $files, $noteId); + foreach ($filesResponse['attachments'] as $key => $value) { + $attachments[$key] = []; + $attachments[$key]['APP_DOC_FILENAME'] = $value['APP_DOC_FILENAME']; + $attachments[$key]['LINK'] = "../cases/cases_ShowDocument?a=" . $value["APP_DOC_UID"] . "&v=" . $value["DOC_VERSION"]; + } + + } // Send the email if ($sendMail) { - // @todo refactor this section the files attached need to send in the email + // Get the recipients $case = new ClassesCases(); $p = $case->getUsersParticipatedInCase($appUid, 'ACTIVE'); $noteRecipientsList = []; @@ -3892,9 +3902,19 @@ class Cases $noteRecipients = implode(",", $noteRecipientsList); $note = stripslashes($note); - $note = new \AppNotes(); - $note->sendNoteNotification($appUid, $userUid, $note, $noteRecipients); + // Send the notification + $appNote = new AppNotes(); + $appNote->sendNoteNotification($appUid, $userUid, $note, $noteRecipients, '', 0, $noteId); } + + // Prepare the response + $result = []; + $result['success'] = 'success'; + $result['message'] = ''; + $result['attachments'] = $attachments; + $result['attachment_errors'] = []; + + return $result; } /** @@ -3910,15 +3930,20 @@ class Cases */ public function uploadFilesInCaseNotes($userUid, $appUid, $filesReferences = [], $noteId = 0) { - if (!empty($_FILES["form"]["name"])) { + $files = []; + if (!empty($_FILES["filesToUpload"])) { $upload = true; - // Array from post upload - foreach ($_FILES["form"]["name"] as $fileIndex => $fileName) { - if (!is_array($fileName)) { + // This format is from ext-js multipart + $filesName = !empty($_FILES["filesToUpload"]["name"]) ? $_FILES["filesToUpload"]["name"] : []; + $filesTmpName = !empty($_FILES["filesToUpload"]["tmp_name"]) ? $_FILES["filesToUpload"]["tmp_name"] : []; + $filesError = !empty($_FILES["filesToUpload"]["error"]) ? $_FILES["filesToUpload"]["error"] : []; + + foreach ($filesName as $index => $value) { + if (!empty($value)) { $files[] = [ - 'name' => $_FILES["form"]["name"][$fileIndex], - 'tmp_name' => $_FILES["form"]["tmp_name"][$fileIndex], - 'error' => $_FILES["form"]["error"][$fileIndex] + 'name' => $filesName[$index], + 'tmp_name' => $filesTmpName[$index], + 'error' => $filesError[$index] ]; } } @@ -3941,31 +3966,43 @@ class Cases // We will to register the files in the database $response = []; + $response['attachments'] = []; + $response['attachment_errors'] = []; if (!empty($files)) { $i = 0; + $j = 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 = [ - "DOC_ID" => $noteId, - "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; + // If the file was uploaded correctly we will to register in the DB + if ($isUploaded) { + $attributes = [ + "DOC_ID" => $noteId, + "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); + + // List of files uploaded or copy + $response['attachments'][$i++] = $attributes; + } else { + $response['attachment_errors'][$j++] = [ + 'error' => 'error', + 'file' => $fileName["name"] + ]; + } } else { throw new UploadException($fileName['error']); } diff --git a/workflow/engine/src/ProcessMaker/Model/AppNotes.php b/workflow/engine/src/ProcessMaker/Model/AppNotes.php index 402662991..66c00b43b 100644 --- a/workflow/engine/src/ProcessMaker/Model/AppNotes.php +++ b/workflow/engine/src/ProcessMaker/Model/AppNotes.php @@ -44,4 +44,63 @@ class AppNotes extends Model 'NOTE_AFFECTED_OBJ2', 'NOTE_RECIPIENTS' ]; + + /** + * Scope a query to filter an specific case + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $appUid + * @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 string $appUid + * @param int $start + * @param int $limit + * @param string $dir + * + * @return array + */ + public static function getNotes(string $appUid, $start = 0, $limit = 25, $dir = 'DESC') + { + $query = AppNotes::query()->select([ + 'NOTE_ID', + 'APP_UID', + 'NOTE_DATE', + 'NOTE_CONTENT', + 'NOTE_TYPE', + 'NOTE_AVAILABILITY', + 'USERS.USR_UID', + 'USERS.USR_USERNAME', + 'USERS.USR_FIRSTNAME', + 'USERS.USR_LASTNAME' + ]); + $query->leftJoin('USERS', function ($join) { + $join->on('USERS.USR_UID', '=', 'APP_NOTES.USR_UID'); + }); + $query->appUid($appUid); + $query->orderBy('NOTE_DATE', $dir); + // Add pagination to the query + $query->offset($start)->limit($limit); + + $results = $query->get(); + $notes = []; + $notes['notes'] = []; + $results->each(function ($item, $key) use (&$notes) { + $row = $item->toArray(); + $row['NOTE_CONTENT'] = stripslashes($row['NOTE_CONTENT']); + $notes['notes'][] = $row; + }); + + // Add the total of rows to return + $notes['totalCount'] = $limit; + + return $notes; + } } diff --git a/workflow/engine/src/ProcessMaker/Model/Documents.php b/workflow/engine/src/ProcessMaker/Model/Documents.php index 85939198d..ec9b45d59 100644 --- a/workflow/engine/src/ProcessMaker/Model/Documents.php +++ b/workflow/engine/src/ProcessMaker/Model/Documents.php @@ -64,7 +64,7 @@ class Documents extends Model * Scope a query to filter an specific case * * @param \Illuminate\Database\Eloquent\Builder $query - * @param string $proUid + * @param string $appUid * @return \Illuminate\Database\Eloquent\Builder */ public function scopeAppUid($query, string $appUid) @@ -72,10 +72,22 @@ class Documents extends Model return $query->where('APP_UID', $appUid); } + /** + * Scope a query to filter an specific reference file + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param int $docId + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeDocId($query, int $docId) + { + return $query->where('DOC_ID', $docId); + } + /** * Return the documents related to the case * - * @param int $proId + * @param string $appUid * @param string $type * * @return array @@ -96,7 +108,9 @@ class Documents extends Model /** * Get attached files from the case note. + * * @param string $appUid + * * @return object */ public static function getAttachedFilesFromTheCaseNote(string $appUid) @@ -109,4 +123,26 @@ class Documents extends Model ->get(); return $result; } + + /** + * Return the documents related to the specific DOC_ID + * + * @param int $docId + * + * @return array + */ + public static function getFiles(int $docId) + { + $query = Documents::query()->select(['APP_DOC_UID', 'APP_DOC_FILENAME', 'DOC_VERSION']); + $query->docId($docId); + $results = $query->get(); + $documentList = []; + $results->each(function ($item, $key) use (&$documentList) { + $row = $item->toArray(); + $row['LINK'] = "../cases/cases_ShowDocument?a=" . $row["APP_DOC_UID"] . "&v=" . $row["DOC_VERSION"]; + $documentList[] = $row; + }); + + return $documentList; + } } diff --git a/workflow/engine/src/ProcessMaker/Util/helpers.php b/workflow/engine/src/ProcessMaker/Util/helpers.php index a844b2eaa..e63d20a30 100644 --- a/workflow/engine/src/ProcessMaker/Util/helpers.php +++ b/workflow/engine/src/ProcessMaker/Util/helpers.php @@ -617,22 +617,24 @@ function saveAppDocument($file, $appUid, $appDocUid, $version = 1, $upload = tru 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( + G::uploadFile( $file["tmp_name"], $pathCase, $fileName ); + $response = true; } else { G::verifyPath($pathCase, true); $response = copy($file["tmp_name"], $pathCase . $fileName); } + + return $response; } catch (Exception $e) { throw $e; }