001/* 002 * Copyright 2024 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.repository.mentions; 017 018import java.util.HashSet; 019import java.util.Set; 020import java.util.regex.Matcher; 021import java.util.regex.Pattern; 022 023import org.apache.avalon.framework.component.Component; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027 028import org.ametys.core.user.User; 029import org.ametys.core.user.UserIdentity; 030import org.ametys.core.user.UserManager; 031import org.ametys.core.util.I18nUtils; 032import org.ametys.runtime.i18n.I18nizableText; 033import org.ametys.runtime.plugin.component.AbstractLogEnabled; 034 035/** 036 * Utils for Mentions 037 */ 038public class MentionUtils extends AbstractLogEnabled implements Component, Serviceable 039{ 040 /** Avalon role */ 041 public static final String ROLE = MentionUtils.class.getName(); 042 043 /** Regex used to extract mentions from a text. A mention is inside a @() */ 044 public static final String EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT = "@\\(([^()]+)\\)"; 045 046 /** Regex used to extract mentions from a text. A mention is inside a @() */ 047 public static final String EXTRACT_MENTIONS_REGEX_RICH_TEXT = "data-ametys-mention-user=\"([^\"]+)\""; 048 049 /** A prefix to have before full name of a mentioned user */ 050 public static final String MENTIONED_USER_PREFIX = "@"; 051 052 /** The user manager */ 053 protected UserManager _userManager; 054 055 /** The i18n utils. */ 056 protected I18nUtils _i18nUtils; 057 058 public void service(ServiceManager manager) throws ServiceException 059 { 060 _userManager = (UserManager) manager.lookup(UserManager.ROLE); 061 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 062 } 063 064 /** 065 * Extract mentioned users from simple text content 066 * @param content the simple text content 067 * @return the set of mentioned users 068 */ 069 public static Set<UserIdentity> extractMentionedUsersFromSimpleText(String content) 070 { 071 Set<UserIdentity> mentionendUsers = new HashSet<>(); 072 if (content != null) 073 { 074 Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT); 075 Matcher matcher = pattern.matcher(content); 076 077 while (matcher.find()) 078 { 079 String userIdentityAsString = matcher.group(1); 080 UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString); 081 mentionendUsers.add(userIdentity); 082 } 083 } 084 return mentionendUsers; 085 } 086 087 /** 088 * Extract mentioned users from rich text content 089 * @param content the rich text content 090 * @return the set of mentioned users 091 */ 092 public Set<UserIdentity> extractMentionedUsersFromRichText(String content) 093 { 094 Set<UserIdentity> mentionedUsers = new HashSet<>(); 095 Pattern pattern = Pattern.compile("data-ametys-mention-user=\"([^\"]+)\""); 096 Matcher matcher = pattern.matcher(content); 097 098 while (matcher.find()) 099 { 100 String userIdentityAsString = matcher.group(1); 101 UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString); 102 mentionedUsers.add(userIdentity); 103 } 104 return mentionedUsers; 105 } 106 107 /** 108 * Transform syntax text of a rich text to display text using a regex to find the parts to transform and a function to transform them 109 * @param syntaxText the syntax text 110 * @param recipient the recipient of the mail, for mail purposes 111 * @return the transformed text with colors according to the recipient 112 */ 113 public String transformRichTextToReadableText(String syntaxText, UserIdentity recipient) 114 { 115 String readableText = syntaxText; 116 117 if (syntaxText != null) 118 { 119 Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_RICH_TEXT); 120 Matcher matcher = pattern.matcher(syntaxText); 121 StringBuffer sb = new StringBuffer(); 122 123 while (matcher.find()) 124 { 125 String mentionBackgroundColor = _getMentionColor(recipient, matcher); 126 127 StringBuilder replaceBy = new StringBuilder("style=\"background: ").append(mentionBackgroundColor).append("; color: #1264a3\""); 128 129 matcher.appendReplacement(sb, Matcher.quoteReplacement(replaceBy.toString())); 130 } 131 matcher.appendTail(sb); 132 readableText = sb.toString(); 133 } 134 return readableText; 135 } 136 137 /** 138 * Transform syntax text of a simple text to display text using a regex to find the parts to transform and a function to transform them 139 * @param syntaxText the syntax text 140 * @param recipient the recipient of the mail, for mail purposes, can be null for any other purposes 141 * @return the transformed text with colors according to the recipient if not null, with full name in plain text otherwise 142 */ 143 public String transformTextToReadableText(String syntaxText, UserIdentity recipient) 144 { 145 String readableText = syntaxText; 146 147 if (syntaxText != null) 148 { 149 Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT); 150 Matcher matcher = pattern.matcher(syntaxText); 151 StringBuffer sb = new StringBuffer(); 152 153 while (matcher.find()) 154 { 155 String userIdentityAsString = matcher.group(1); 156 UserIdentity mentionedUserIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString); 157 User mentionedUser = _userManager.getUser(mentionedUserIdentity); 158 String mentionedUserName = mentionedUser != null ? (MENTIONED_USER_PREFIX + mentionedUser.getFullName()) : _i18nUtils.translate(new I18nizableText("plugin.core", "PLUGINS_CORE_USERS_UNKNOWN_USER")); 159 160 StringBuilder replaceBy = new StringBuilder(mentionedUserName); 161 if (recipient != null) 162 { 163 String mentionBackgroundColor = _getMentionColor(recipient, matcher); 164 165 replaceBy = new StringBuilder("<span style=\"background: ").append(mentionBackgroundColor).append("; color: #1264a3\">") 166 .append(mentionedUserName) 167 .append("</span>"); 168 } 169 170 matcher.appendReplacement(sb, Matcher.quoteReplacement(replaceBy.toString())); 171 } 172 matcher.appendTail(sb); 173 readableText = sb.toString(); 174 } 175 return readableText; 176 } 177 178 private String _getMentionColor(UserIdentity recipient, Matcher matcher) 179 { 180 String userIdentityAsString = matcher.group(1); 181 UserIdentity mentionedUserIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString); 182 183 String mentionBackgroundColor = "rgba(29, 155, 209, 0.1)"; 184 if (mentionedUserIdentity.equals(recipient)) 185 { 186 mentionBackgroundColor = "rgba(255, 198, 0, 0.18)"; 187 } 188 return mentionBackgroundColor; 189 } 190 191}