diff --git a/CRM/Certificate/Entity/AbstractEntity.php b/CRM/Certificate/Entity/AbstractEntity.php index 0388642..4660045 100644 --- a/CRM/Certificate/Entity/AbstractEntity.php +++ b/CRM/Certificate/Entity/AbstractEntity.php @@ -101,21 +101,28 @@ public function getCertificateConfigurationById($certificateId) { * Id of the entity to get a configured certificate for * @param int $contactId * Id of the contact the entity belongs to + * @param bool $multiple + * If multiple certificate should be returned * - * @return \CRM_Certificate_BAO_CompuCertificate|bool + * @return \CRM_Certificate_BAO_CompuCertificate|array|bool */ - public function getCertificateConfiguration($entityId, $contactId) { + public function getCertificateConfiguration($entityId, $contactId, $multiple = FALSE) { try { $certificateBAO = new CRM_Certificate_BAO_CompuCertificate(); $this->addEntityConditionals($certificateBAO, $entityId, $contactId); $certificateBAO->whereDateIsValid(); $certificateBAO->orderBy(CRM_Certificate_DAO_CompuCertificate::$_tableName . '.id Desc'); $certificateBAO->selectAdd(CRM_Certificate_DAO_CompuCertificate::$_tableName . '.id'); - $certificateBAO->find(TRUE); + $certificateBAO->find(); - if (!empty($certificateBAO->id) && $this->isCertificateValidForAnEntity($certificateBAO, $contactId)) { - return $certificateBAO; + $results = []; + while ($certificateBAO->fetch()) { + if (!empty($certificateBAO->id) && $this->isCertificateValidForAnEntity($certificateBAO, $contactId)) { + $results[] = clone $certificateBAO; + } } + + return $multiple ? $results : ($results[0] ?? FALSE); } catch (\Exception $e) { } diff --git a/CRM/Certificate/Entity/Membership.php b/CRM/Certificate/Entity/Membership.php index 97093ff..4a3ad73 100644 --- a/CRM/Certificate/Entity/Membership.php +++ b/CRM/Certificate/Entity/Membership.php @@ -169,6 +169,7 @@ public function formatConfiguredCertificatesForContact(array $configuredCertific 'start_date' => $configuredCertificate['start_date'], 'linked_to' => $membership['membership_name'], 'download_link' => $this->getCertificateDownloadUrl($membership['id'], $contactId, TRUE), + 'configuration_id' => $configuredCertificate['certificate_id'], ]; array_push($certificates, $certificate); }); diff --git a/CRM/Certificate/Hook/PageRun/EventPageTab.php b/CRM/Certificate/Hook/PageRun/EventPageTab.php index b680464..d7f5175 100644 --- a/CRM/Certificate/Hook/PageRun/EventPageTab.php +++ b/CRM/Certificate/Hook/PageRun/EventPageTab.php @@ -32,7 +32,7 @@ public function addDownloadButton() { $downloadUrl = htmlspecialchars_decode(CRM_Utils_System::url('civicrm/certificates/event', $query)); CRM_Core_Resources::singleton() ->addScriptFile("uk.co.compucorp.certificate", "./js/eventDownloadButton.js"); - Civi::resources()->addVars(E::SHORT_NAME, ['download_url' => $downloadUrl]); + Civi::resources()->addVars(E::SHORT_NAME, ['download_url' => [$downloadUrl]]); } } diff --git a/CRM/Certificate/Hook/PageRun/MemberPageTab.php b/CRM/Certificate/Hook/PageRun/MemberPageTab.php index 95555a4..b52d1b2 100644 --- a/CRM/Certificate/Hook/PageRun/MemberPageTab.php +++ b/CRM/Certificate/Hook/PageRun/MemberPageTab.php @@ -21,12 +21,14 @@ public function addDownloadButton() { $certificateType = CRM_Certificate_Enum_CertificateType::MEMBERSHIPS; $entity = CRM_Certificate_Entity_EntityFactory::create($certificateType); - $configuredCertificate = $entity->getCertificateConfiguration($id, $contactId); + $configuredCertificates = $entity->getCertificateConfiguration($id, $contactId, TRUE); - if ($configuredCertificate) { - $downloadUrl = $entity->getCertificateDownloadUrl($id, $contactId); + if (!empty($configuredCertificates)) { + foreach ($configuredCertificates as $certificate) { + $downloadUrls[] = sprintf("%s&ccid=%s", $entity->getCertificateDownloadUrl($id, $contactId), $certificate->id); + } - Civi::resources()->addVars(E::SHORT_NAME, ['download_url' => $downloadUrl]); + Civi::resources()->addVars(E::SHORT_NAME, ['download_url' => $downloadUrls]); Civi::resources()->addScriptFile(E::LONG_NAME, "/js/compucertificate.js", 0); Civi::resources()->addScriptFile(E::LONG_NAME, "./js/memberDownloadButton.js", 1); } diff --git a/CRM/Certificate/Page/CertificateDownload.php b/CRM/Certificate/Page/CertificateDownload.php index 303712d..51ac349 100755 --- a/CRM/Certificate/Page/CertificateDownload.php +++ b/CRM/Certificate/Page/CertificateDownload.php @@ -44,7 +44,8 @@ public static function downloadMembershipCertificate() { */ private static function downloadCertificate($contactId, $entityId, $certificateType) { try { - $certificate = self::checkIfCertificateAvailable($contactId, $entityId, $certificateType); + $configurationId = CRM_Utils_Request::retrieve('ccid', 'Positive'); + $certificate = self::checkIfCertificateAvailable($contactId, $entityId, $certificateType, $configurationId); } catch (CRM_Core_Exception $e) { CRM_Core_Session::setStatus($e->getMessage(), 'Error', 'error'); @@ -67,22 +68,34 @@ private static function downloadCertificate($contactId, $entityId, $certificateT * @param int $contactId * @param int $entityId * @param int $certificateType + * @param int|bool $certificateId * * @return \CRM_Certificate_BAO_CompuCertificate * * @throws \CRM_Core_exception */ - public static function checkIfCertificateAvailable($contactId, $entityId, $certificateType) { + public static function checkIfCertificateAvailable($contactId, $entityId, $certificateType, $certificateId = NULL) { if (empty($contactId) || empty($entityId)) { throw new CRM_Core_Exception('You do not have permission to access this contact.', 403); } - $certificate = self::validateCertificate($contactId, $entityId, $certificateType); - $accessChecker = new CRM_Certificate_Service_CertificateAccessChecker($contactId, $certificate); - $hasAccess = $accessChecker->check(); + $certificates = self::validateCertificate($contactId, $entityId, $certificateType); + $certificateWithAccess = []; + foreach ($certificates as $certificate) { + if (!empty($certificateId) && $certificate->id != $certificateId) { + continue; + } - if ($hasAccess) { - return $certificate; + $accessChecker = new CRM_Certificate_Service_CertificateAccessChecker($contactId, $certificate); + $hasAccess = $accessChecker->check(); + + if ($hasAccess) { + $certificateWithAccess[$certificate->id] = $certificate; + } + } + + if (!empty($certificateWithAccess)) { + return end($certificateWithAccess); } throw new CRM_Core_Exception('You do not have permission to access this contact.', 403); @@ -96,19 +109,19 @@ public static function checkIfCertificateAvailable($contactId, $entityId, $certi * @param $entityId * @param int $certificateType * - * @return \CRM_Certificate_BAO_CompuCertificate + * @return \CRM_Certificate_BAO_CompuCertificate[] * * @throws CRM_Core_Exception; */ private static function validateCertificate(int $contactId, int $entityId, int $certificateType) { $entity = CRM_Certificate_Entity_EntityFactory::create($certificateType); - $configuredCertificate = $entity->getCertificateConfiguration($entityId, $contactId); + $configuredCertificates = $entity->getCertificateConfiguration($entityId, $contactId, TRUE); - if (!$configuredCertificate) { + if (empty($configuredCertificates)) { throw new CRM_Core_Exception(ts('Certificate not available for contact')); } - return $configuredCertificate; + return $configuredCertificates; } } diff --git a/CRM/Certificate/Service/Certificate.php b/CRM/Certificate/Service/Certificate.php index 928479b..ec1554e 100644 --- a/CRM/Certificate/Service/Certificate.php +++ b/CRM/Certificate/Service/Certificate.php @@ -17,7 +17,8 @@ class CRM_Certificate_Service_Certificate { public function store($values) { $result = NULL; - if ($this->configurationExist($values)) { + $duplicateSupportEntity = [CRM_Certificate_Enum_CertificateType::MEMBERSHIPS]; + if (!in_array($values['type'], $duplicateSupportEntity) && $this->configurationExist($values)) { throw new CRM_Certificate_Exception_ConfigurationExistException(); } diff --git a/js/compucertificate.js b/js/compucertificate.js index 34c451d..0377612 100644 --- a/js/compucertificate.js +++ b/js/compucertificate.js @@ -15,8 +15,15 @@ window.downloadLink = function () { ` Print Certificate` ); + + let url = ''; + let count = 0; + CRM.vars.certificate.download_url.forEach(downloadUrl => { + url += " setTimeout(function(){ window.open('" + downloadUrl + "'); }, " + (500 * count++) + "); "; + }); + btn.setAttribute('type', 'button'); - btn.setAttribute('onclick', "window.open('" + CRM.vars.certificate.download_url + "')"); + btn.setAttribute('onclick', url); btn.setAttribute('target', '_blank'); btn.classList.add('ui-button', 'ui-corner-all', 'ui-widget'); btn.style.marginRight = '5px'; diff --git a/tests/phpunit/CRM/Certificate/Service/CertificateMembershipTest.php b/tests/phpunit/CRM/Certificate/Service/CertificateMembershipTest.php index 41e5006..64e4434 100644 --- a/tests/phpunit/CRM/Certificate/Service/CertificateMembershipTest.php +++ b/tests/phpunit/CRM/Certificate/Service/CertificateMembershipTest.php @@ -58,8 +58,7 @@ public function testCreateEventCertificateConfigurationForEmptyStatusAndType() { * Test that duplicate certifiacte configuration * cannot be created for the same entity. */ - public function testExceptionThrownForDuplicateCertificateMembershipConfiguration() { - $this->expectException(CRM_Certificate_Exception_ConfigurationExistException::class); + public function testExceptionNotThrownForDuplicateCertificateMembershipConfiguration() { $statuses = CRM_Certificate_Test_Fabricator_MembershipStatus::fabricate()['id']; $types = CRM_Certificate_Test_Fabricator_MembershipType::fabricate()['id']; @@ -72,8 +71,11 @@ public function testExceptionThrownForDuplicateCertificateMembershipConfiguratio 'end_date' => date('Y-m-d'), ]; - $this->createCertificate($values); - $this->createCertificate($values); + $cert1 = $this->createCertificate($values); + $cert2 = $this->createCertificate($values); + + $this->assertNotEmpty($cert1); + $this->assertNotEmpty($cert2); } /**