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.plugins.userdirectory.userdataprovider; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.Comparator; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.activity.Initializable; 029import org.apache.avalon.framework.context.Context; 030import org.apache.avalon.framework.context.ContextException; 031import org.apache.avalon.framework.context.Contextualizable; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.avalon.framework.service.Serviceable; 035import org.apache.cocoon.components.ContextHelper; 036import org.apache.cocoon.environment.Request; 037 038import org.ametys.cms.contenttype.ContentTypesHelper; 039import org.ametys.cms.data.File; 040import org.ametys.cms.repository.Content; 041import org.ametys.core.user.User; 042import org.ametys.core.user.dataprovider.UserDataProvider; 043import org.ametys.plugins.userdirectory.UserDirectoryHelper; 044import org.ametys.runtime.model.ModelItem; 045import org.ametys.runtime.plugin.component.AbstractLogEnabled; 046import org.ametys.web.WebHelper; 047 048/** 049 * A {@link UserDataProvider} that finds data from the ContentUser associated to the User or UserIdentity given 050 */ 051public class ContentUserDataProvider extends AbstractLogEnabled implements UserDataProvider, Serviceable, Initializable, Contextualizable 052{ 053 /** Attribute path for user's image */ 054 public static final String USER_CONTENT_IMAGE_PATH = "illustration/image"; 055 private static final Comparator<Content> __COMPARATOR = Comparator.comparing(Content::getName); 056 private Set<String> _supportedData; 057 private UserDirectoryHelper _userDirectoryHelper; 058 private ContentTypesHelper _contentTypesHelper; 059 private Context _context; 060 061 public void service(ServiceManager manager) throws ServiceException 062 { 063 _userDirectoryHelper = (UserDirectoryHelper) manager.lookup(UserDirectoryHelper.ROLE); 064 _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 065 } 066 067 public void contextualize(Context context) throws ContextException 068 { 069 _context = context; 070 } 071 072 public int getPriority() 073 { 074 return 10000; 075 } 076 077 public void initialize() throws Exception 078 { 079 _supportedData = new HashSet<>(); 080 081 // Get the content types of a ud user 082 Map<String, Object> contentTypesList = _contentTypesHelper.getContentTypesList(Collections.singletonList("org.ametys.plugins.userdirectory.Content.user"), 083 true /* inherited */, 084 false /* checkRights */, 085 true /* includePrivate */, 086 false /* includeMixins */, 087 false /* includeAbstract*/); 088 089 @SuppressWarnings("unchecked") 090 List<Map<String, Object>> contentTypes = (List<Map<String, Object>>) contentTypesList.get("contentTypes"); 091 092 // Get the model items names of all the model items that can be in a ud user 093 for (Map<String, Object> contentType : contentTypes) 094 { 095 Collection< ? extends ModelItem> modelItems = _contentTypesHelper.getModelItems(List.of(contentType.get("id")) 096 .toArray(String[]::new)); 097 098 _supportedData.addAll(modelItems.stream() 099 .map(ModelItem::getName) 100 .collect(Collectors.toSet())); 101 } 102 } 103 104 public boolean supports(String element) 105 { 106 // Check if the element requested can be supported. Can return true but not have a value for a specific user. 107 return User.IMAGE_DATA_ID.equals(element) || _supportedData.contains(element); 108 } 109 110 @Override 111 public boolean hasValue(User user, String dataId) 112 { 113 // Sort users by name in order to always retrieve the same value by dataId 114 List<Content> contentUsers = _getSortedContentUsers(user); 115 116 String dataIdToCheck = User.IMAGE_DATA_ID.equals(dataId) ? USER_CONTENT_IMAGE_PATH : dataId; 117 118 // Get the ud users and check if it has a value for the data requested 119 for (Content contentUser : contentUsers) 120 { 121 if (hasValue(contentUser, dataIdToCheck)) 122 { 123 return true; 124 } 125 } 126 127 return false; 128 } 129 130 private boolean hasValue(Content contentUser , String dataId) 131 { 132 return contentUser != null && contentUser.hasValue(dataId); 133 } 134 135 public Object getValue(User user, String dataId) 136 { 137 // Sort users by name in order to always retrieve the same value by dataId 138 List<Content> contentUsers = _getSortedContentUsers(user); 139 140 String dataIdToCheck = User.IMAGE_DATA_ID.equals(dataId) ? USER_CONTENT_IMAGE_PATH : dataId; 141 142 // Get the ud users and retrieve the value wanted if it exists 143 for (Content contentUser : contentUsers) 144 { 145 if (hasValue(contentUser, dataIdToCheck)) 146 { 147 Object value = contentUser.getValue(dataIdToCheck); 148 149 if (USER_CONTENT_IMAGE_PATH.equals(dataIdToCheck) && value != null && value instanceof File file) 150 { 151 return new UserDirectoryImageAccessor(file, getLogger()); 152 } 153 else 154 { 155 return value; 156 } 157 } 158 } 159 160 return null; 161 } 162 163 private List<Content> _getSortedContentUsers(User user) 164 { 165 Request request = ContextHelper.getRequest(_context); 166 String lang = WebHelper.findLanguage(request); 167 168 List<Content> userContents = new ArrayList<>(_userDirectoryHelper.getUserContents(user.getIdentity(), lang)); 169 userContents.sort(__COMPARATOR); 170 return userContents; 171 } 172}