sender->space ?? null; if ($space === null || !$space->moduleManager->isEnabled('donations')) { return; } $event->sender->addItem([ 'label' => Yii::t('DonationsModule.base', 'My Donations'), 'group' => 'modules', 'url' => $space->createUrl('/donations/donations/index'), 'icon' => '', 'sortOrder' => 120, 'isActive' => ( Yii::$app->controller && Yii::$app->controller->module && Yii::$app->controller->module->id === 'donations' && Yii::$app->controller->id === 'donations' ), ]); } public static function onRescueSettingsMenuInit($event): void { $space = $event->sender->space ?? null; if ($space === null || !$space->moduleManager->isEnabled('donations')) { return; } $event->sender->addItem([ 'label' => Yii::t('DonationsModule.base', 'Donations'), 'url' => $space->createUrl('/donations/settings'), 'sortOrder' => 400, 'isActive' => ( Yii::$app->controller && Yii::$app->controller->module && Yii::$app->controller->module->id === 'donations' && Yii::$app->controller->id === 'settings' ), ]); } public static function onSpaceAdminMenuInitFallback($event): void { $space = $event->sender->space ?? null; if ($space === null || !$space->moduleManager->isEnabled('donations')) { return; } if ($space->moduleManager->isEnabled('rescue_foundation') || !$space->isAdmin()) { return; } $event->sender->addItem([ 'label' => Yii::t('DonationsModule.base', 'Donations'), 'group' => 'admin', 'url' => $space->createUrl('/donations/settings'), 'icon' => '', 'sortOrder' => 620, 'isActive' => ( Yii::$app->controller && Yii::$app->controller->module && Yii::$app->controller->module->id === 'donations' && Yii::$app->controller->id === 'settings' ), ]); } public static function onDonationTransactionSucceeded($event): void { if (!$event instanceof DonationSettlementEvent) { return; } $payload = is_array($event->payload) ? $event->payload : []; $animalIntegration = new DonationAnimalIntegrationService(); $payload = $animalIntegration->applySucceededIntegration($event->transaction, $event->goal, $payload); $notificationIntegration = new DonationNotificationService(); $payload = $notificationIntegration->applySucceededNotifications($event->transaction, $event->goal, $payload); $event->payload = $payload; } public static function onDonationTransactionRefunded($event): void { if (!$event instanceof DonationSettlementEvent) { return; } $payload = is_array($event->payload) ? $event->payload : []; $animalIntegration = new DonationAnimalIntegrationService(); $payload = $animalIntegration->applyRefundedIntegration($event->transaction, $event->goal, $payload); $notificationIntegration = new DonationNotificationService(); $payload = $notificationIntegration->applyRefundedNotifications($event->transaction, $event->goal, $payload); $event->payload = $payload; } public static function onAnimalTileOverlayRender($event): void { $hookClass = 'humhub\\modules\\animal_management\\events\\AnimalTileRenderEvent'; if (!class_exists($hookClass) || !$event instanceof $hookClass) { return; } $space = $event->contentContainer ?? null; if (!$space instanceof Space || !$space->moduleManager->isEnabled('donations')) { return; } if (Yii::$app->db->schema->getTableSchema(DonationGoal::tableName(), true) === null) { return; } $goal = $event->existingDonationGoal ?? null; if (!$goal instanceof DonationGoal) { $goal = DonationGoal::find() ->where([ 'contentcontainer_id' => (int)$space->contentcontainer_id, 'goal_type' => DonationGoal::TYPE_ANIMAL, 'target_animal_id' => (int)($event->animal->id ?? 0), ]) ->orderBy(['is_active' => SORT_DESC, 'id' => SORT_DESC]) ->one(); } if (!$goal instanceof DonationGoal) { return; } $target = (float)$goal->target_amount; $current = max(0.0, (float)$goal->current_amount); $isFunded = $target > 0 && $current >= $target; $percent = $target > 0 ? min(100.0, round(($current / $target) * 100, 1)) : 0.0; $percentLabel = rtrim(rtrim(number_format($percent, 1, '.', ''), '0'), '.') . '%'; $targetLabel = '$' . number_format(round(max(0.0, $target)), 0); $currentLabel = '$' . number_format(round($current), 0); $statusColor = $isFunded ? '#4ce083' : '#ff6666'; $goalToggleInputId = 'donation-goal-toggle-' . (int)($event->animal->id ?? 0); $quickDonateToggleInputId = 'donation-goal-quick-toggle-' . (int)($event->animal->id ?? 0); $goalCardId = 'donation-goal-card-' . (int)($event->animal->id ?? 0); $donorPanelId = 'donation-goal-donors-panel-' . (int)($event->animal->id ?? 0); $quickDonatePanelId = 'donation-goal-quick-panel-' . (int)($event->animal->id ?? 0); $donorPagerWrapId = 'donation-goal-donors-pager-' . (int)($event->animal->id ?? 0); $donorPagerName = 'donation-goal-donors-page-' . (int)($event->animal->id ?? 0); $donorRows = []; if (Yii::$app->db->schema->getTableSchema(DonationTransaction::tableName(), true) !== null) { $transactions = DonationTransaction::find() ->where([ 'contentcontainer_id' => (int)$space->contentcontainer_id, 'goal_id' => (int)$goal->id, 'status' => DonationTransaction::STATUS_SUCCEEDED, ]) ->orderBy(['id' => SORT_DESC]) ->limit(200) ->all(); $totalsByUser = []; $anonymousTotal = 0.0; foreach ($transactions as $transaction) { $amount = max(0.0, (float)$transaction->amount); if ($amount <= 0) { continue; } if ((int)$transaction->is_anonymous === 1 || (int)$transaction->donor_user_id <= 0) { $anonymousTotal += $amount; continue; } $userId = (int)$transaction->donor_user_id; $totalsByUser[$userId] = ($totalsByUser[$userId] ?? 0.0) + $amount; } if (!empty($totalsByUser)) { arsort($totalsByUser); $users = User::find() ->where(['id' => array_keys($totalsByUser)]) ->indexBy('id') ->all(); foreach ($totalsByUser as $userId => $totalAmount) { $user = $users[$userId] ?? null; if (!$user instanceof User) { continue; } $avatarUrl = (string)$user->getProfileImage()->getUrl(); $profileUrl = (string)$user->getUrl(); $displayName = (string)$user->getDisplayName(); $amountText = '$' . number_format(round($totalAmount), 0); $donorRows[] = '' . '' . '' . Html::encode($displayName) . '' . '' . Html::encode($amountText) . '' . ''; } } if ($anonymousTotal > 0) { $donorRows[] = '
' . '' . '' . '' . '' . Html::encode(Yii::t('DonationsModule.base', 'Anonymous')) . '' . '$' . Html::encode(number_format(round($anonymousTotal), 0)) . '' . '
'; } } $donorPageRows = empty($donorRows) ? ['
' . Html::encode(Yii::t('DonationsModule.base', 'No donations yet.')) . '
'] : $donorRows; $donorPageSize = 25; $donorPages = array_chunk($donorPageRows, $donorPageSize); $donorTotalPages = max(1, count($donorPages)); $donorPagesHtml = ''; foreach ($donorPages as $pageIndex => $pageRows) { $pageNumber = $pageIndex + 1; $donorPagesHtml .= '
' . implode('', $pageRows) . '
'; } $donorPagerCss = '#'. Html::encode($donorPagerWrapId) . ' [data-donor-page],#' . Html::encode($donorPagerWrapId) . ' [data-donor-controls-page]{display:none;}'; $donorPagerRadioInputsHtml = ''; $donorPagerTopControlsHtml = ''; $donorPagerBottomControlsHtml = ''; foreach ($donorPages as $pageIndex => $pageRows) { $pageNumber = $pageIndex + 1; $radioId = $donorPagerName . '-' . (int)$pageNumber; $prevRadioId = $donorPagerName . '-' . (int)max(1, $pageNumber - 1); $nextRadioId = $donorPagerName . '-' . (int)min($donorTotalPages, $pageNumber + 1); $donorPagerRadioInputsHtml .= ''; $prevControl = $pageNumber > 1 ? '' : '' . Html::encode(Yii::t('DonationsModule.base', 'Previous')) . ''; $nextControl = $pageNumber < $donorTotalPages ? '' : '' . Html::encode(Yii::t('DonationsModule.base', 'Next')) . ''; $pageLabel = Html::encode('Page ' . $pageNumber . ' / ' . $donorTotalPages); $controlsHtml = '
' . $prevControl . '' . $pageLabel . '' . $nextControl . '
'; $donorPagerTopControlsHtml .= $controlsHtml; $donorPagerBottomControlsHtml .= $controlsHtml; $donorPagerCss .= '#' . Html::encode($radioId) . ':checked ~ [data-donor-top-controls] [data-donor-controls-page="' . (int)$pageNumber . '"]{display:flex;}'; $donorPagerCss .= '#' . Html::encode($radioId) . ':checked ~ [data-donor-pages] [data-donor-page="' . (int)$pageNumber . '"]{display:block;}'; $donorPagerCss .= '#' . Html::encode($radioId) . ':checked ~ [data-donor-bottom-controls] [data-donor-controls-page="' . (int)$pageNumber . '"]{display:flex;}'; } $goalToggleCss = ''; $quickDonateHeaderTemplate = (string)Yii::$app->getModule('donations')->settings->contentContainer($space) ->get('animal_donation_form_header', Yii::t('DonationsModule.base', 'Your Donation directly supports [animal-name]')); $quickDonateHeaderTemplate = trim($quickDonateHeaderTemplate); if ($quickDonateHeaderTemplate === '') { $quickDonateHeaderTemplate = Yii::t('DonationsModule.base', 'Your Donation directly supports [animal-name]'); } $quickDonateHeaderText = str_replace('[animal-name]', (string)$event->animal->getDisplayName(), $quickDonateHeaderTemplate); $quickDonateActionUrl = $space->createUrl('/donations/donations/donate'); $quickDonatePanelHtml = ''; $donorPanelHtml = $goalToggleCss . '' . '' . ''; $goalLabelHtml = ''; $percentColor = $percent >= 100.0 ? '#4ce083' : '#ffffff'; $currentAmountHtml = '' . Html::encode($currentLabel) . ''; $targetAmountNumberLabel = ltrim($targetLabel, '$'); if ($targetAmountNumberLabel === '') { $targetAmountNumberLabel = $targetLabel; } $targetAmountInnerHtml = '' . '$' . '' . Html::encode($targetAmountNumberLabel) . '' . ''; $donateCtaHtml = '' . Html::encode(Yii::t('DonationsModule.base', 'Donate')) . ''; $targetAmountHtml = '' . $targetAmountInnerHtml . ''; if (!empty($event->showDonationSettingsButton) && !empty($event->donationToggleInputId)) { $toggleInputId = (string)$event->donationToggleInputId; $inlineFormId = (string)($event->donationInlineFormId ?? ''); $targetOnClick = ''; if ($inlineFormId !== '') { $targetOnClick = ' onclick="var c=document.getElementById(\'' . Html::encode($toggleInputId) . '\');var f=document.getElementById(\'' . Html::encode($inlineFormId) . '\');if(c&&f){window.setTimeout(function(){f.style.display=c.checked?\'block\':\'none\';},0);}"'; } $targetAmountHtml = ''; } $event->addHtml( '
' . '
' . '' . '
' . $goalLabelHtml . $targetAmountHtml . '
' . '
' . '' . '
' . '
' . $currentAmountHtml . $donateCtaHtml . '' . Html::encode($percentLabel) . '' . '
' . '
' . $donorPanelHtml . $quickDonatePanelHtml . '
' ); } public static function onAnimalTileSizeResolve($event): void { $hookClass = 'humhub\\modules\\animal_management\\events\\AnimalTileSizeEvent'; if (!class_exists($hookClass) || !$event instanceof $hookClass) { return; } $space = $event->contentContainer ?? null; if (!$space instanceof Space || !$space->moduleManager->isEnabled('donations')) { return; } $settings = Yii::$app->getModule('donations')->settings->contentContainer($space); $extraHeight = max(0, (int)$settings->get('animal_tile_extra_height_px', 0)); if ($extraHeight <= 0) { return; } $event->addAdditionalHeightPx($extraHeight); } }