digestMode = $digestMode; } /** * @param EchoEventPresentationModel[] $models * @return string[] Array of the following format: * [ 'body' => formatted email body, * 'subject' => formatted email subject ] */ protected function formatModels( array $models ) { // echo-email-batch-body-intro-daily // echo-email-batch-body-intro-weekly $intro = $this->msg( 'echo-email-batch-body-intro-' . $this->digestMode ) ->params( $this->user->getName() ) ->parse(); $intro = nl2br( $intro ); $eventsByCategory = $this->groupByCategory( $models ); ksort( $eventsByCategory ); $digestList = $this->renderDigestList( $eventsByCategory ); $htmlFormatter = new EchoHtmlEmailFormatter( $this->user, $this->language ); $body = $this->renderBody( $this->language, $intro, $digestList, $this->renderAction(), $htmlFormatter->getFooter() ); // echo-email-batch-subject-daily // echo-email-batch-subject-weekly $subject = $this->msg( 'echo-email-batch-subject-' . $this->digestMode ) ->numParams( count( $models ), count( $models ) ) ->text(); return [ 'subject' => $subject, 'body' => $body, ]; } private function renderBody( Language $language, $intro, $digestList, $action, $footer ) { $alignStart = $language->alignStart(); $langCode = $language->getHtmlCode(); $langDir = $language->getDir(); // phpcs:disable Generic.Files.LineLength return <<< EOF


       
    $intro  
$digestList


    $action  
       
   
$footer

 
 


EOF; // phpcs:enable Generic.Files.LineLength } /** * @param string $type Notification type * @param int $count Number of notifications in this type's section * @return string Formatted category section title */ private function getCategoryTitle( $type, $count ) { return $this->msg( "echo-category-title-$type" ) ->numParams( $count ) ->parse(); } /** * @param EchoEventPresentationModel[] $models * @return array [ 'category name' => EchoEventPresentationModel[] ] */ private function groupByCategory( array $models ): array { $eventsByCategory = []; foreach ( $models as $model ) { $eventsByCategory[$model->getCategory()][] = $model; } return $eventsByCategory; } /** * Apply style to notification category header * @param string $category Can contain HTML. Is included as-is in HTML template, is not escaped. * @return string */ protected function applyStyleToCategory( $category ) { return <<< EOF $category

EOF; } /** * Apply style to individual notification event * @param EchoEventPresentationModel $model * @return string */ protected function applyStyleToEvent( EchoEventPresentationModel $model ) { $iconUrl = wfExpandUrl( EchoIcon::getRasterizedUrl( $model->getIconType(), $this->language->getCode() ), PROTO_CANONICAL ); $imgSrc = Sanitizer::encodeAttribute( $iconUrl ); // notification text $text = $model->getHeaderMessage()->parse(); return <<< EOF $text EOF; } private function renderDigestList( $eventsByCategory ) { $result = []; // build the html section for each category foreach ( $eventsByCategory as $category => $models ) { $output = $this->applyStyleToCategory( $this->getCategoryTitle( $category, count( $models ) ) ); foreach ( $models as $model ) { $output .= "\n" . $this->applyStyleToEvent( $model ); } $result[] = '' . $output . '
'; } return trim( implode( "\n", $result ) ); } private function renderAction() { return Html::element( 'a', [ 'href' => SpecialPage::getTitleFor( 'Notifications' ) ->getFullURL( '', false, PROTO_CANONICAL ), 'style' => EchoHtmlEmailFormatter::PRIMARY_LINK_STYLE, ], $this->msg( 'echo-email-batch-link-text-view-all-notifications' )->text() ); } }