diff --git a/CRM/Certificate/Entity/AbstractEntity.php b/CRM/Certificate/Entity/AbstractEntity.php index 1c0548a..0388642 100644 --- a/CRM/Certificate/Entity/AbstractEntity.php +++ b/CRM/Certificate/Entity/AbstractEntity.php @@ -113,7 +113,7 @@ public function getCertificateConfiguration($entityId, $contactId) { $certificateBAO->selectAdd(CRM_Certificate_DAO_CompuCertificate::$_tableName . '.id'); $certificateBAO->find(TRUE); - if (!empty($certificateBAO->id)) { + if (!empty($certificateBAO->id) && $this->isCertificateValidForAnEntity($certificateBAO, $contactId)) { return $certificateBAO; } } @@ -164,6 +164,20 @@ abstract protected function addEntityConditionals($certificateBAO, $entityId, $c */ protected function addEntityExtraField($certificateBAO, &$certificate) {} + /** + * Validate a certificate against entity specific checks. + * + * @param \CRM_Certificate_BAO_CompuCertificate $certificate + * Certificate. + * @param int $contactId + * Contact id. + * + * @return bool + */ + protected function isCertificateValidForAnEntity(\CRM_Certificate_BAO_CompuCertificate $certificate, int $contactId) { + return TRUE; + } + /** * Gets all entity certificates vailable for a contact. * diff --git a/CRM/Certificate/Entity/Membership.php b/CRM/Certificate/Entity/Membership.php index 3c21ab0..97093ff 100644 --- a/CRM/Certificate/Entity/Membership.php +++ b/CRM/Certificate/Entity/Membership.php @@ -195,4 +195,14 @@ public function getEntity() { return CertificateType::MEMBERSHIPS; } + /** + * @inheritDoc + */ + protected function isCertificateValidForAnEntity(\CRM_Certificate_BAO_CompuCertificate $certificate, int $contactId) { + $membershipDates = (new CRM_Certificate_Service_CertificateMembership())->getMembershipDates($certificate->id, $contactId); + + return ($membershipDates['startDate'] === NULL || $certificate->max_valid_through_date === NULL || $membershipDates['startDate'] <= $certificate->max_valid_through_date) + && ($membershipDates['endDate'] === NULL || $certificate->min_valid_from_date === NULL || $membershipDates['endDate'] >= $certificate->min_valid_from_date); + } + } diff --git a/CRM/Certificate/Service/Certificate.php b/CRM/Certificate/Service/Certificate.php index 1984f5a..928479b 100644 --- a/CRM/Certificate/Service/Certificate.php +++ b/CRM/Certificate/Service/Certificate.php @@ -25,12 +25,13 @@ public function store($values) { if (!empty($values['id'])) { $params['id'] = $values['id']; } + $isMembershipCertificate = (int) $values['type'] === CRM_Certificate_Enum_CertificateType::MEMBERSHIPS; $params['name'] = $values['name']; $params['entity'] = $values['type']; $params['end_date'] = $values['end_date']; $params['start_date'] = $values['start_date']; - $params['min_valid_from_date'] = $values['min_valid_from_date'] ?? NULL; - $params['max_valid_through_date'] = $values['max_valid_through_date'] ?? NULL; + $params['min_valid_from_date'] = isset($values['min_valid_from_date']) && $isMembershipCertificate ? $values['min_valid_from_date'] : NULL; + $params['max_valid_through_date'] = isset($values['max_valid_through_date']) && $isMembershipCertificate ? $values['max_valid_through_date'] : NULL; $params['template_id'] = $values['message_template_id']; $params['download_type'] = $values['download_type'] ?? DownloadType::TEMPLATE; $params['download_format'] = $values['download_format'] ?? DownloadFormat::PDF; diff --git a/CRM/Certificate/Service/CertificateAccessChecker.php b/CRM/Certificate/Service/CertificateAccessChecker.php index e2d0596..b73c99c 100644 --- a/CRM/Certificate/Service/CertificateAccessChecker.php +++ b/CRM/Certificate/Service/CertificateAccessChecker.php @@ -1,7 +1,6 @@ checkMembershipDates() && ($this->hasViewPermission() || $this->hasViewPermissionByRelationship()); + return $this->hasViewPermission() || $this->hasViewPermissionByRelationship(); } /** @@ -81,36 +80,4 @@ private function hasViewPermissionByRelationship() { return FALSE; } - private function checkMembershipDates(): bool { - $membershipDates = $this->getMembershipDates(); - $membershipStartDate = $membershipDates['start_date']; - $membershipEndDate = $membershipDates['end_date']; - $certificateStartDate = $this->certificate->min_valid_from_date ?? $membershipEndDate; - $certificateEndDate = $this->certificate->max_valid_through_date ?? $membershipStartDate; - - return !empty($membershipStartDate) && !empty($membershipEndDate) && strtotime($membershipStartDate) <= strtotime($certificateEndDate) && - strtotime($membershipEndDate) >= strtotime($certificateStartDate); - } - - private function getMembershipDates(): array { - $startDate = NULL; - $endDate = NULL; - - $memberships = Membership::get(FALSE) - ->addSelect('start_date', 'end_date') - ->addWhere('contact_id', '=', $this->contactId) - ->addWhere('status_id', '=', 2) - ->execute() - ->getArrayCopy(); - - foreach ($memberships as $membership) { - $startDate = $startDate === NULL || strtotime($membership['start_date']) < strtotime($startDate) ? - $membership['start_date'] : $startDate; - $endDate = $endDate === NULL || strtotime($membership['end_date']) > strtotime($endDate) ? - $membership['end_date'] : $endDate; - } - - return ['start_date' => $startDate, 'end_date' => $endDate]; - } - } diff --git a/CRM/Certificate/Service/CertificateMembership.php b/CRM/Certificate/Service/CertificateMembership.php index 7ea27f1..4f3e303 100644 --- a/CRM/Certificate/Service/CertificateMembership.php +++ b/CRM/Certificate/Service/CertificateMembership.php @@ -1,4 +1,45 @@ select(['GROUP_CONCAT(DISTINCT cet.entity_type_id) as entityTypes', 'GROUP_CONCAT(DISTINCT cs.status_id) as statuses']) + ->join('cet', 'LEFT JOIN `' . CRM_Certificate_DAO_CompuCertificateEntityType::getTableName() . '` cet ON (cet.certificate_id = ccc.id)') + ->join('cs', 'LEFT JOIN `' . CRM_Certificate_DAO_CompuCertificateStatus::getTableName() . '` cs ON (cs.certificate_id = ccc.id)') + ->where('ccc.id = @certificateId', ['certificateId' => $certificateId]) + ->groupBy('ccc.id'); + + $certificates = $query->execute()->fetchAll(); + + $query = Membership::get(FALSE) + ->addSelect('start_date', 'end_date') + ->addWhere('contact_id', '=', $contactId) + ->addClause('OR', ['start_date', 'IS NULL'], ['start_date', '<=', 'now']) + ->addClause('OR', ['end_date', 'IS NULL'], ['end_date', '>', 'now']); + + if (!empty($certificates[0]['entityTypes'])) { + $query->addWhere('membership_type_id', 'IN', explode(',', $certificates[0]['entityTypes'])); + } + if (!empty($certificates[0]['statuses'])) { + $query->addWhere('status_id', 'IN', explode(',', $certificates[0]['statuses'])); + } + + $memberships = $query->execute()->getArrayCopy(); + + foreach ($memberships as $membership) { + $startDate = $startDate === NULL || strtotime($membership['start_date']) < strtotime($startDate) ? + $membership['start_date'] : $startDate; + $endDate = $endDate === NULL || strtotime($membership['end_date']) > strtotime($endDate) ? + $membership['end_date'] : $endDate; + } + + return ['startDate' => $startDate, 'endDate' => $endDate]; + } + } diff --git a/CRM/Certificate/Token/Certificate.php b/CRM/Certificate/Token/Certificate.php index bf4b641..3d44686 100644 --- a/CRM/Certificate/Token/Certificate.php +++ b/CRM/Certificate/Token/Certificate.php @@ -1,7 +1,6 @@ resolveFields($certificate, $this->getMembershipDates($e), $resolvedTokens); + $this->resolveFields($certificate, $resolvedTokens, $e); } } catch (Exception $e) { @@ -71,64 +70,46 @@ public function prefetch(TokenValueEvent $e) { return $resolvedTokens; } - private function getMembershipDates(TokenValueEvent $e): array { - $startDate = NULL; - $endDate = NULL; - - $contactIds = $e->getTokenProcessor()->getContextValues('contactId'); - $contactId = (is_array($contactIds) && !empty($contactIds[0])) ? $contactIds[0] : 0; - - // get all memberships for given contact to get min start_date and max end_date of all memberships - $memberships = Membership::get(FALSE) - ->addSelect('start_date', 'end_date') - ->addWhere('contact_id', '=', $contactId) - ->addWhere('status_id', '=', self::MEMBERSHIP_STATUS_CURRENT) - ->execute() - ->getArrayCopy(); - - foreach ($memberships as $membership) { - $startDate = $startDate === NULL || strtotime($membership['start_date']) < strtotime($startDate) ? - $membership['start_date'] : $startDate; - $endDate = $endDate === NULL || strtotime($membership['end_date']) > strtotime($endDate) ? - $membership['end_date'] : $endDate; - } - - return ['start_date' => $startDate, 'end_date' => $endDate]; - } - /** * Resolve the value of ceritificate configuration token fields. * * @param CRM_Certificate_DAO_CompuCertificate $certificate - * @param array $membershipDates * @param array &$resolvedTokens + * @param Civi\Token\Event\TokenValueEvent $e */ - private function resolveFields($certificate, array $membershipDates, &$resolvedTokens) { - $membershipStartTimestamp = !empty($membershipDates['start_date']) ? strtotime($membershipDates['start_date']) : ''; - $membershipEndTimestamp = !empty($membershipDates['end_date']) ? strtotime($membershipDates['end_date']) : ''; - $certificateValidityStartTimestamp = !empty($certificate->min_valid_from_date) ? strtotime($certificate->min_valid_from_date) : ''; - $certificateValidityEndTimestamp = !empty($certificate->max_valid_through_date) ? strtotime($certificate->max_valid_through_date) : ''; + private function resolveFields($certificate, &$resolvedTokens, $e) { $resolvedTokens['rolling_start_or_renewal_date'] = ''; - - if ($membershipStartTimestamp && $membershipEndTimestamp) { - $renewalTimestamp = strtotime($membershipDates['end_date'] . " -1 year 1 day"); - $resolvedTokens['rolling_start_or_renewal_date'] = $renewalTimestamp > $membershipStartTimestamp - ? CRM_Utils_Date::customFormat(date('Y-m-d', $renewalTimestamp), '%e/%b/%Y') - : CRM_Utils_Date::customFormat($membershipDates['start_date'], '%e/%b/%Y'); + $resolvedTokens['valid_from'] = ''; + $resolvedTokens['valid_to'] = ''; + + if ((int) $certificate->entity === CRM_Certificate_Enum_CertificateType::MEMBERSHIPS) { + $contactIds = $e->getTokenProcessor()->getContextValues('contactId'); + $contactId = (is_array($contactIds) && !empty($contactIds[0])) ? $contactIds[0] : 0; + $membershipDates = (new CRM_Certificate_Service_CertificateMembership())->getMembershipDates($certificate->id, $contactId); + $membershipStartTimestamp = !empty($membershipDates['startDate']) ? strtotime($membershipDates['startDate']) : ''; + $membershipEndTimestamp = !empty($membershipDates['endDate']) ? strtotime($membershipDates['endDate']) : ''; + $certificateValidityStartTimestamp = !empty($certificate->min_valid_from_date) ? strtotime($certificate->min_valid_from_date) : ''; + $certificateValidityEndTimestamp = !empty($certificate->max_valid_through_date) ? strtotime($certificate->max_valid_through_date) : ''; + + if ($membershipStartTimestamp && $membershipEndTimestamp) { + $renewalTimestamp = strtotime($membershipDates['endDate'] . " -1 year 1 day"); + $resolvedTokens['rolling_start_or_renewal_date'] = $renewalTimestamp > $membershipStartTimestamp + ? CRM_Utils_Date::customFormat(date('Y-m-d', $renewalTimestamp), '%e/%b/%Y') + : CRM_Utils_Date::customFormat($membershipDates['startDate'], '%e/%b/%Y'); + } + $validityStartDate = empty($certificateValidityStartTimestamp) || $membershipStartTimestamp > $certificateValidityStartTimestamp ? + $membershipDates['startDate'] : (string) $certificate->min_valid_from_date; + $validityEndDate = empty($certificateValidityEndTimestamp) || (!empty($membershipEndTimestamp) && $certificateValidityEndTimestamp > $membershipEndTimestamp) ? + $membershipDates['endDate'] : (string) $certificate->max_valid_through_date; + $resolvedTokens['valid_from'] = !empty($validityStartDate) + ? CRM_Utils_Date::customFormat($validityStartDate, '%e/%b/%Y') : ''; + $resolvedTokens['valid_to'] = !empty($validityEndDate) + ? CRM_Utils_Date::customFormat($validityEndDate, '%e/%b/%Y') : ''; } - $validityStartDate = empty($certificateValidityStartTimestamp) || $membershipStartTimestamp > $certificateValidityStartTimestamp ? - $membershipDates['start_date'] : (string) $certificate->min_valid_from_date; - $validityEndDate = empty($certificateValidityEndTimestamp) || (!empty($membershipEndTimestamp) && $certificateValidityEndTimestamp > $membershipEndTimestamp) ? - $membershipDates['end_date'] : (string) $certificate->max_valid_through_date; - $resolvedTokens['name'] = $certificate->name; $resolvedTokens['start_date'] = CRM_Utils_Date::customFormat($certificate->start_date, '%e/%b/%Y'); $resolvedTokens['end_date'] = CRM_Utils_Date::customFormat($certificate->end_date, '%e/%b/%Y'); - $resolvedTokens['valid_from'] = !empty($validityStartDate) - ? CRM_Utils_Date::customFormat($validityStartDate, '%e/%b/%Y') : ''; - $resolvedTokens['valid_to'] = !empty($validityEndDate) - ? CRM_Utils_Date::customFormat($validityEndDate, '%e/%b/%Y') : ''; } } diff --git a/templates/CRM/Certificate/Form/CertificateConfigure.hlp b/templates/CRM/Certificate/Form/CertificateConfigure.hlp index aff6fdc..da43d01 100644 --- a/templates/CRM/Certificate/Form/CertificateConfigure.hlp +++ b/templates/CRM/Certificate/Form/CertificateConfigure.hlp @@ -17,11 +17,11 @@
{ts}Tokens: They will create tokens that can be used on certificates as follows:{/ts}
{ts}'Min Valid From Date' (certificate.valid_from){/ts}
+{ts}"Min Valid From Date" (certificate.valid_from){/ts}
{ts}The latter of 1. Min Valid From Date and 2. The users membership start date.{/ts}
{ts}'Max Valid Through Date' (certificate.valid_to){/ts}
+{ts}"Max Valid Through Date" (certificate.valid_to){/ts}
{ts}The earlier of 1. The date entered in this field and 2. The users membership end date.{/ts}
{ts}Tokens: They will create tokens that can be used on certificates as follows:{/ts}
{ts}'Min Valid From Date' (certificate.valid_from){/ts}
+{ts}"Min Valid From Date" (certificate.valid_from){/ts}
{ts}The latter of 1. Min Valid From Date and 2. The users membership start date.{/ts}
{ts}'Max Valid Through Date' (certificate.valid_to){/ts}
+{ts}"Max Valid Through Date" (certificate.valid_to){/ts}
{ts}The earlier of 1. The date entered in this field and 2. The users membership end date.{/ts}