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.core.util.StringUtils;
033import org.ametys.runtime.i18n.I18nizableText;
034import org.ametys.runtime.plugin.component.AbstractLogEnabled;
035
036/**
037 * Utils for Mentions
038 */
039public class MentionUtils extends AbstractLogEnabled implements Component, Serviceable
040{
041    /** Avalon role */
042    public static final String ROLE = MentionUtils.class.getName();
043
044    /** Regex used to extract mentions from a text. A mention is inside a @() */
045    public static final String EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT = "@\\(([^()]+)\\)";
046
047    /** Regex used to extract mentions from a text. A mention is inside a @() */
048    public static final String EXTRACT_MENTIONS_REGEX_RICH_TEXT = "data-ametys-mention-user=\"([^\"]+)\"";
049    
050    /** A prefix to have before full name of a mentioned user */
051    public static final String MENTIONED_USER_PREFIX = "@";
052
053    /** The user manager */
054    protected UserManager _userManager;
055
056    /** The i18n utils. */
057    protected I18nUtils _i18nUtils;
058    
059    public void service(ServiceManager manager) throws ServiceException
060    {
061        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
062        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
063    }
064
065    /**
066     * Extract mentioned users from simple text content
067     * @param content the simple text content
068     * @return the set of mentioned users
069     */
070    public static Set<UserIdentity> extractMentionedUsersFromSimpleText(String content)
071    {
072        Set<UserIdentity> mentionendUsers = new HashSet<>();
073        if (content != null)
074        {
075            Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT);
076            Matcher matcher = pattern.matcher(content);
077            
078            while (matcher.find())
079            {
080                String userIdentityAsString = matcher.group(1);
081                UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
082                mentionendUsers.add(userIdentity);
083            }
084        }
085        return mentionendUsers;
086    }
087    
088    /**
089     * Extract mentioned users from rich text content
090     * @param content the rich text content
091     * @return the set of mentioned users
092     */
093    public Set<UserIdentity> extractMentionedUsersFromRichText(String content)
094    {
095        Set<UserIdentity> mentionedUsers = new HashSet<>();
096        Pattern pattern = Pattern.compile("data-ametys-mention-user=\"([^\"]+)\"");
097        Matcher matcher = pattern.matcher(content);
098
099        while (matcher.find())
100        {
101            String userIdentityAsString = matcher.group(1);
102            UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
103            mentionedUsers.add(userIdentity);
104        }
105        return mentionedUsers;
106    }
107
108    /**
109     * 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
110     * @param syntaxText the syntax text
111     * @param recipient the recipient of the mail, for mail purposes
112     * @return the transformed text with colors according to the recipient
113     */
114    public String transformRichTextToReadableText(String syntaxText, UserIdentity recipient)
115    {
116        String readableText = syntaxText;
117
118        if (syntaxText != null)
119        {
120            Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_RICH_TEXT);
121            Matcher matcher = pattern.matcher(syntaxText);
122            StringBuffer sb = new StringBuffer();
123
124            while (matcher.find())
125            {
126                String mentionBackgroundColor = _getMentionColor(recipient, matcher);
127                
128                StringBuilder replaceBy = new StringBuilder("style=\"background: ").append(mentionBackgroundColor).append("; color: #1264a3\"");
129                
130                matcher.appendReplacement(sb, Matcher.quoteReplacement(replaceBy.toString()));
131            }
132            matcher.appendTail(sb);
133            readableText = sb.toString();
134        }
135        return readableText;
136    }
137    
138    /**
139     * 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
140     * @param syntaxText the syntax text
141     * @param recipient the recipient of the mail, for mail purposes, can be null for any other purposes
142     * @return the transformed text with colors according to the recipient if not null, with full name in plain text otherwise
143     */
144    public String transformTextToReadableText(String syntaxText, UserIdentity recipient)
145    {
146        String readableText = syntaxText;
147        if (org.apache.commons.lang3.StringUtils.isNotBlank(syntaxText))
148        {
149            Pattern pattern = Pattern.compile(EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT);
150            Matcher matcher = pattern.matcher(readableText);
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(StringUtils.escapeHTML(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}