Commit a5780d16 authored by Alexis Ragot's avatar Alexis Ragot
Browse files

Merge branch 'release/2.2' into 'master'

Release/2.2

See merge request maarch/thirdPartyArchiving!32
parents 2e797382 08dbf16d
......@@ -46,7 +46,7 @@ class ArchiveDeliveryRequest extends abstractMessage
$registrationNumber = $this->getCurrentRegistrationNumber();
$queryParts[] = "recipientOrgRegNumber=$registrationNumber";
$queryParts[] = "type='ArchiveDeliveryRequestReply'";
$queryParts[] = "type='ArchiveDeliveryRequest'";
$queryParts[] = "status = 'sent'";
$queryParts[] = "active=true";
......@@ -147,13 +147,6 @@ class ArchiveDeliveryRequest extends abstractMessage
$archiverOrgRegNumber = $archives[0]->archiverOrgRegNumber;
$message = $this->send($messageIdentifier, $archives, $derogation, $comment, $requesterOrgRegNumber, $archiverOrgRegNumber);
$controlAutorityControler = \laabs::newController("medona/ControlAuthority");
if (count($controlAutorityControler->index()) > 0) {
$this->sendAuthorizationRequest((string) $message->messageId);
} else {
$this->accept((string) $message->messageId);
}
$messages[] = $message;
}
......@@ -204,7 +197,7 @@ class ArchiveDeliveryRequest extends abstractMessage
$message->derogation = $derogation;
if ($derogation) {
$message->status = "derogation";
$message->status = "sent";
} else {
$message->status = "accepted";
}
......@@ -254,12 +247,6 @@ class ArchiveDeliveryRequest extends abstractMessage
$operationResult
);
/*if ($message->status == "accepted") {
$replyMessage = $this->process($message);
$message->replyMessage = $replyMessage;
}*/
return $message;
}
......@@ -280,6 +267,35 @@ class ArchiveDeliveryRequest extends abstractMessage
}
}
/**
* Derogation archive delivery request message
* @param string $messageId The message identifier
*/
public function derogation($messageId)
{
$this->changeStatus($messageId, "derogation");
$message = $this->sdoFactory->read('medona/message', array('messageId' => $messageId));
$message->derogation = "true";
$this->sdoFactory->update($message);
$event = $this->lifeCycleJournalController->logEvent(
'medona/authorization',
'medona/message',
$message->messageId,
$message,
true
);
$controlAutorityControler = \laabs::newController("medona/ControlAuthority");
if (count($controlAutorityControler->index()) > 0) {
$this->sendAuthorizationRequest((string) $message->messageId);
} else {
$this->accept((string) $message->messageId);
}
}
/**
* Accept archive delivery request message
* @param string $messageId The message identifier
......@@ -297,10 +313,6 @@ class ArchiveDeliveryRequest extends abstractMessage
$message,
true
);
/*$replyMessage = $this->process((string) $messageId);
$message->replyMessage = $replyMessage;*/
}
/**
......@@ -382,6 +394,9 @@ class ArchiveDeliveryRequest extends abstractMessage
$archives[] = $this->archiveController->communicate($unitIdentifier->objectId);
}
$logMessage = ["message" => "%s archives are communicated", "variables"=> count($archives)];
\laabs::notify(\bundle\audit\AUDIT_ENTRY_OUTPUT, $logMessage);
try {
$archiveDeliveryRequestReplyController = \laabs::newController('medona/ArchiveDeliveryRequestReply');
$archiveDeliveryRequestReplyController->send($message, $archives, $replyCode);
......
......@@ -29,6 +29,31 @@ namespace ext\thirdPartyArchiving\bundle\medona\Controller;
class ArchiveDeliveryRequestReply extends abstractMessage
{
/**
* Get received archive delivery message
*
* @return array Array of medona/message object
*/
public function listReception()
{
$currentOrg = \laabs::getToken('ORGANIZATION');
if (!$currentOrg) {
$this->view->addContentFile("recordsManagement/welcome/noWorkingOrg.html");
return $this->view->saveHtml();
}
$queryParts = array();
$registrationNumber = $this->getCurrentRegistrationNumber();
$queryParts[] = "recipientOrgRegNumber=$registrationNumber";
$queryParts[] = "type='ArchiveDeliveryRequestReply'";
$queryParts[] = "status = 'sent'";
$queryParts[] = "active=true";
return $this->sdoFactory->find('medona/message', implode(' and ', $queryParts), null, false, false, 300);
}
/**
* Get deliveries request reply messages
*
......
......@@ -294,6 +294,9 @@ class ArchiveDestructionRequest extends abstractMessage
try {
$archives = $this->archiveController->destruct($archiveIds);
$logMessage = ["message" => "%s archives are deleted", "variables"=> count($archives)];
\laabs::notify(\bundle\audit\AUDIT_ENTRY_OUTPUT, $logMessage);
$message->status = "processed";
$message->operationDate = \laabs::newDatetime(null, "UTC");
......
......@@ -321,6 +321,15 @@ class ArchiveRestitution extends abstractMessage
$this->changeStatus($messageId, "acknowledge");
$message = $this->sdoFactory->read('medona/message', array('messageId' => $messageId));
$requestMessage = $this->sdoFactory->find('medona/message', "type='ArchiveRestitutionRequest' AND senderOrgRegNumber='".$message->recipientOrgRegNumber."' AND replyReference='".$message->relatedReference."'")[0];
$requestMessage->unitIdentifier = $this->sdoFactory->readChildren('medona/unitIdentifier', $requestMessage);
foreach ($requestMessage->unitIdentifier as $unitIdentifier) {
$this->archiveController->setStatus($unitIdentifier->objectId, 'restituted');
}
$eventInfo = array();
$eventInfo['type'] = "ArchiveRestitution";
$eventInfo['senderOrgRegNumber'] = $message->senderOrgRegNumber;
......@@ -382,14 +391,7 @@ class ArchiveRestitution extends abstractMessage
$this->sdoFactory->update($message, "medona/message");
$requestMessage = $this->sdoFactory->find('medona/message', "type='ArchiveRestitutionRequest' AND senderOrgRegNumber='".$message->recipientOrgRegNumber."' AND replyReference='".$message->relatedReference."'")[0];
$requestMessage->unitIdentifier = $this->sdoFactory->readChildren('medona/unitIdentifier', $requestMessage);
foreach ($requestMessage->unitIdentifier as $unitIdentifier) {
$this->archiveController->setStatus($unitIdentifier->objectId, 'restituted');
}
$this->changeStatus($messageId, "validated");
$uri = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
......
......@@ -370,6 +370,9 @@ class ArchiveRestitutionRequest extends abstractMessage
$archives[] = $archive;
}
$logMessage = ["message" => "%s archives are restituted", "variables"=> count($archives)];
\laabs::notify(\bundle\audit\AUDIT_ENTRY_OUTPUT, $logMessage);
try {
$archiveRestitutionController = \laabs::newController('medona/ArchiveRestitution');
$archiveRestitutionController->send($message, $archives);
......
......@@ -119,12 +119,13 @@ class ArchiveTransfer extends abstractMessage
* Receive message with all contents embedded
* @param string $messageFile The message binary contents OR a filename
* @param array $attachments An array of attachment binary data
* @param string $filename The message file name
*
* @return medona/message
*
* @todo Remove files from sas when error on reception
*/
public function receive($messageFile, $attachments = array())
public function receive($messageFile, $attachments = array(), $filename = false)
{
$messageId = \laabs::newId();
$message = \laabs::newInstance('medona/message');
......@@ -132,6 +133,7 @@ class ArchiveTransfer extends abstractMessage
$message->type = "ArchiveTransfer";
$message->receptionDate = \laabs::newTimestamp();
$messageDir = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
if (!is_dir($messageDir)) {
mkdir($messageDir, 0777, true);
......@@ -153,7 +155,7 @@ class ArchiveTransfer extends abstractMessage
case 'application/zip':
case 'application/octet-stream':
$this->receiveZip($message, $messageFile);
$this->receiveZip($message, $messageFile, $filename);
break;
}
}
......@@ -163,6 +165,20 @@ class ArchiveTransfer extends abstractMessage
if ($message->schema != 'medona') {
$archiveTransferController = \laabs::newController($message->schema.'/ArchiveTransfer');
$archiveTransferController->receive($message);
$errors = $archiveTransferController->checkResources($message);
if ($errors) {
$messageURI = $this->messageDirectory.DIRECTORY_SEPARATOR.$message->messageId;
if (is_dir($messageURI)) {
\laabs\rmdir($messageURI, true);
}
$exception = \laabs::newException('medona/invalidMessageException', "Invalid message", $errors[0]->getCode());
$exception->errors = $errors;
throw $exception;
}
} else {
// Validate xsd
$schemaFile = LAABS_EXTENSION.DIRECTORY_SEPARATOR.'thirdPartyArchiving'.DIRECTORY_SEPARATOR.LAABS_BUNDLE.DIRECTORY_SEPARATOR.'medona'.DIRECTORY_SEPARATOR.LAABS_RESOURCE.DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.'medona_V1.0.xsd';
......@@ -235,6 +251,21 @@ class ArchiveTransfer extends abstractMessage
$message->size += (integer) $size;
}
}
$this->checkResources($message);
if ($this->errors) {
$messageURI = $this->messageDirectory.DIRECTORY_SEPARATOR.$message->messageId;
if (is_dir($messageURI)) {
\laabs\rmdir($messageURI, true);
}
$exception = \laabs::newException('medona/invalidMessageException', "Invalid message", $this->errors[0]->getCode());
$exception->errors = $this->errors;
throw $exception;
}
}
try {
......@@ -348,33 +379,44 @@ class ArchiveTransfer extends abstractMessage
}
}
protected function receiveZip($message, $zipstream)
protected function receiveZip($message, $zipstream, $filename)
{
$messageDir = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
$zipfile = \laabs\tempnam();
file_put_contents($zipfile, $zipstream);
$zip = \laabs::newService('dependency/fileSystem/plugins/zip');
$zip->extract($zipfile, $messageDir);
$zipContents = scandir($messageDir);
if (!isset($zipContents[2])) {
throw \laabs::newException('medona/invalidMessageException', "Invalid message", 400);
}
if (is_dir($messageDir.DIRECTORY_SEPARATOR.$zipContents[2])) {
$zipFolder = $messageDir.DIRECTORY_SEPARATOR.$zipContents[2];
foreach (scandir($zipFolder) as $file) {
if ($file != "." && $file != "..") {
rename($zipFolder.DIRECTORY_SEPARATOR.$file, $messageDir.DIRECTORY_SEPARATOR.$file);
}
}
var_dump($zipContents);
exit;
rmdir($zipFolder);
}
$filename = explode('.', $filename);
array_pop($filename);
$filename = implode('.', $filename);
$messageFile = file_get_contents($messageDir.DIRECTORY_SEPARATOR.$filename.'.xml');
// Load file xml
$this->loadXml($message, $messageFile);
// Save to message directory
$this->save($message);
if (count($attachments)) {
foreach ($attachments as $attachment) {
$attachment->data = base64_decode($attachment->data);
file_put_contents($messageDir.DIRECTORY_SEPARATOR.$attachment->filename, $attachment->data);
}
}
unlink($messageDir.DIRECTORY_SEPARATOR.$filename.'.xml');
}
/**
......@@ -886,20 +928,8 @@ class ArchiveTransfer extends abstractMessage
$archives = $message->object->dataObjectPackage->descriptiveMetadata->archive;
$binaryDataObjects = (array) $message->object->dataObjectPackage->binaryDataObject;
foreach ($archives as $archive) {
foreach ($archive->digitalResources as $digitalResource) {
if (!isset($binaryDataObjects[$digitalResource->resId])) {
$this->sendError("213", "Le document identifié par '$digitalResource->resId' est introuvable.");
}
}
}
$fromdir = dirname($message->xml->uri);
// List received files
$receivedFiles = glob($fromdir.DIRECTORY_SEPARATOR."*.*");
// List actual message files, starting with message xml itself
$messageFiles = array($message->xml->uri);
if (count($binaryDataObjects)) {
foreach ($binaryDataObjects as $dataObjectId => $binaryDataObject) {
......@@ -907,36 +937,15 @@ class ArchiveTransfer extends abstractMessage
if ($attachment->filename) {
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$attachment->filename;
if (!is_file($filepath)) {
$this->sendError("211", "Le document identifié par le nom '$attachment->filename' n'a pas été trouvé.");
continue;
}
$contents = file_get_contents($filepath);
$messageFiles[] = $attachment->filename;
} elseif ($attachment->uri) {
$contents = file_get_contents($attachment->getAttribute('uri'));
if (!$contents) {
$this->sendError("211", "Le document à l'adresse '$attachment->uri' est indisponible.");
continue;
}
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
file_put_contents($filepath, $contents);
} else {
if (strlen($attachmentElement->value) == 0) {
$this->sendError("211", "Le contenu du document n'a pas été transmis.");
continue;
}
$contents = base64_decode($attachment->value);
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
file_put_contents($filepath, $contents);
}
......@@ -953,11 +962,6 @@ class ArchiveTransfer extends abstractMessage
} else {
$puid = $format->puid;
$fileInfo->format = $format;
/*if ($format->puid != $attachment->format) {
$this->sendError("205 Format de document non conforme au format déclaré.");
array_push($this->errors, new \core\Error("Le format du document '".basename($filepath)."' ".$format->puid." ne correspond pas à celui indiqué (".$attachment->format.")."));
}*/
}
}
......@@ -974,12 +978,6 @@ class ArchiveTransfer extends abstractMessage
}
}
// Validate hash
$messageDigest = $binaryDataObject->messageDigest;
if (strtolower($messageDigest->value) != strtolower(hash($messageDigest->algorithm, $contents))) {
$this->sendError("207", "L'empreinte numérique du document '".basename($filepath)."' ne correspond pas à celle transmise.");
}
if (($arr = get_object_vars($fileInfo)) && !empty($arr)) {
file_put_contents(
$this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId.'.info',
......@@ -988,15 +986,6 @@ class ArchiveTransfer extends abstractMessage
}
}
}
// Check all files received are part of the message
foreach ($receivedFiles as $receivedFile) {
if (!in_array(basename($receivedFile), $messageFiles) && basename($receivedFile) != basename($message->xml->uri)) {
$this->sendError("101", "Le fichier '".basename($receivedFile)."' ,'est pas référencé dans le bordereau.");
return;
}
}
}
protected function validateArchiveRelationships($descriptiveMetadata)
......@@ -1018,6 +1007,80 @@ class ArchiveTransfer extends abstractMessage
return;
}
public function checkResources($message) {
$archives = $message->object->dataObjectPackage->descriptiveMetadata->archive;
$binaryDataObjects = (array) $message->object->dataObjectPackage->binaryDataObject;
foreach ($archives as $archive) {
foreach ($archive->digitalResources as $digitalResource) {
if (!isset($binaryDataObjects[$digitalResource->resId])) {
$this->sendError("213", "Le document identifié par '$digitalResource->resId' est introuvable.");
}
}
}
$fromdir = dirname($message->xml->uri);
// List received files
$receivedFiles = glob($fromdir.DIRECTORY_SEPARATOR."*.*");
// List actual message files, starting with message xml itself
$messageFiles = array($message->xml->uri);
if (count($binaryDataObjects)) {
foreach ($binaryDataObjects as $dataObjectId => $binaryDataObject) {
$attachment = $binaryDataObject->attachment;
if ($attachment->filename) {
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$attachment->filename;
if (!is_file($filepath)) {
$this->sendError("211", "Le document identifié par le nom '$attachment->filename' n'a pas été trouvé.");
continue;
}
$contents = file_get_contents($filepath);
$messageFiles[] = $attachment->filename;
} elseif ($attachment->uri) {
$contents = file_get_contents($attachment->getAttribute('uri'));
if (!$contents) {
$this->sendError("211", "Le document à l'adresse '$attachment->uri' est indisponible.");
continue;
}
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
} else {
if (strlen($attachmentElement->value) == 0) {
$this->sendError("211", "Le contenu du document n'a pas été transmis.");
continue;
}
$contents = base64_decode($attachment->value);
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
}
// Validate hash
$messageDigest = $binaryDataObject->messageDigest;
if (strtolower($messageDigest->value) != strtolower(hash($messageDigest->algorithm, $contents))) {
$this->sendError("207", "L'empreinte numérique du document '".basename($filepath)."' ne correspond pas à celle transmise.");
}
}
}
// Check all files received are part of the message
foreach ($receivedFiles as $receivedFile) {
if (!in_array(basename($receivedFile), $messageFiles) && basename($receivedFile) != basename($message->xml->uri)) {
$this->sendError("101", "Le fichier '".basename($receivedFile)."' ,'est pas référencé dans le bordereau.");
return;
}
}
}
/**
* Process the messages
*
......@@ -1039,6 +1102,9 @@ class ArchiveTransfer extends abstractMessage
}
}
$logMessage = ["message" => "%s message(s) processed", "variables"=> count($results)];
\laabs::notify(\bundle\audit\AUDIT_ENTRY_OUTPUT, $logMessage);
return $results;
}
......
......@@ -339,7 +339,7 @@ class ArchiveTransferSending extends abstractMessage
$message->unitIdentifier = $this->sdoFactory->readChildren('medona/unitIdentifier', $message);
foreach ($message->unitIdentifier as $unitIdentifier) {
$this->archiveController->setStatus($unitIdentifier->objectId, 'transfered');
$this->archiveController->outgoingTransfer($unitIdentifier->objectId);
}
$this->changeStatus($messageId, "validated");
......@@ -350,7 +350,7 @@ class ArchiveTransferSending extends abstractMessage
}
$eventInfo = array();
$eventInfo['type'] = "ArchiveRestitution";
$eventInfo['type'] = "ArchiveTransfer";
$eventInfo['senderOrgRegNumber'] = $message->senderOrgRegNumber;
$eventInfo['recipientOrgRegNumber'] = $message->recipientOrgRegNumber;
$eventInfo['reference'] = $message->reference;
......
......@@ -27,12 +27,19 @@ namespace ext\thirdPartyArchiving\bundle\medona;
*/
interface archiveDeliveryInterface extends messageInterface
{
/**
* Get ingoing delivery messages
*
* @action medona/ArchiveDeliveryRequestReply/listReception
*/
public function readRequestReplyList();
/**
* Get ingoing delivery messages
*
* @action medona/ArchiveDeliveryRequest/listReception
*/
public function readIncominglist();
public function readRequestList();
/**
* Count delivery messages
......@@ -65,9 +72,9 @@ interface archiveDeliveryInterface extends messageInterface
/**
* Accept archive delivery request
*
* @action medona/ArchiveDeliveryRequest/accept
* @action medona/ArchiveDeliveryRequest/derogation
*/
public function updateRequestacceptance_messageId_();
public function updateRequestderogation_messageId_();
/**
* Reject archive delivery request
......
......@@ -67,10 +67,11 @@ interface archiveTransferInterface
* Receive message with all contents embedded
* @param string $messageFile The message binary contents OR a filename
* @param array $attachments An array of filenames for attachments
* @param string $filename The message file name
*
* @action medona/ArchiveTransfer/receive
*/
public function create($messageFile, $attachments = array());
public function create($messageFile, $attachments = array(), $filename = null);
/**
* Validate messages against schema and rules
......
......@@ -35,7 +35,7 @@ trait archiveDeliveryTrait
*
* @return string The view
*/
public function deliveryIncomingList($messages)
public function deliveryRequestReplyList($messages)
{
$this->view->addContentFile('medona/archiveDelivery/deliveryIncomingList.html');
$this->prepareMesageList($messages);
......@@ -52,7 +52,7 @@ trait archiveDeliveryTrait
*
* @return string The view
*/
public function deliveryRequestIncomingList($messages)
public function deliveryRequestList($messages)
{
$this->view->addContentFile('medona/archiveDelivery/deliveryIncomingList.html');
$this->prepareMesageList($messages);
......@@ -64,6 +64,24 @@ trait archiveDeliveryTrait
return $this->view->saveHtml();
}
/**
* Show incoming delivery message list
* @param array $messages Array of message object
*
* @return string The view
*/
public function deliveryAuthorizationList($messages)
{
$this->view->addContentFile('medona/archiveDelivery/deliveryIncomingList.html');
$this->prepareMesageList($messages);
$title = $this->translator->getText("Delivery authorization request");