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.odfweb.actions; 017 018import java.util.Map; 019import java.util.Optional; 020 021import org.apache.avalon.framework.parameters.Parameters; 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.ResourceNotFoundException; 025import org.apache.cocoon.acting.ServiceableAction; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Redirector; 028import org.apache.cocoon.environment.Request; 029import org.apache.cocoon.environment.SourceResolver; 030import org.apache.commons.lang3.StringUtils; 031 032import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 033import org.ametys.cms.repository.ContentQueryHelper; 034import org.ametys.cms.repository.ContentTypeExpression; 035import org.ametys.cms.repository.LanguageExpression; 036import org.ametys.cms.transformation.xslt.ResolveURIComponent; 037import org.ametys.odf.ProgramItem; 038import org.ametys.odf.catalog.CatalogsManager; 039import org.ametys.odf.course.Course; 040import org.ametys.odf.course.CourseFactory; 041import org.ametys.odf.program.AbstractProgram; 042import org.ametys.plugins.odfweb.repository.CoursePage; 043import org.ametys.plugins.odfweb.repository.OdfPageResolver; 044import org.ametys.plugins.repository.AmetysObjectIterable; 045import org.ametys.plugins.repository.AmetysObjectResolver; 046import org.ametys.plugins.repository.query.expression.AndExpression; 047import org.ametys.plugins.repository.query.expression.Expression.Operator; 048import org.ametys.plugins.repository.query.expression.StringExpression; 049import org.ametys.runtime.config.Config; 050import org.ametys.web.WebHelper; 051 052/** 053 * Get a course page from its code. Needed for IPWeb. 054 */ 055public class GetCourseForIPWebAction extends ServiceableAction 056{ 057 private CatalogsManager _catalogsManager; 058 private OdfPageResolver _odfPageResolver; 059 private ContentTypeExtensionPoint _contentTypeEP; 060 private AmetysObjectResolver _resolver; 061 062 @Override 063 public void service(ServiceManager smanager) throws ServiceException 064 { 065 super.service(smanager); 066 _catalogsManager = (CatalogsManager) smanager.lookup(CatalogsManager.ROLE); 067 _odfPageResolver = (OdfPageResolver) smanager.lookup(OdfPageResolver.ROLE); 068 _contentTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE); 069 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 070 } 071 072 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 073 { 074 // Check if IPWeb is activated in the configuration 075 if (!Config.getInstance().getValue("odf.ipweb.activate", true, false)) 076 { 077 throw new UnsupportedOperationException("The IPWeb URL resolution is not configured."); 078 } 079 080 String field = getField(); 081 String lang = getLanguage(); 082 String catalog = getCatalog(); 083 084 Request request = ObjectModelHelper.getRequest(objectModel); 085 086 // Get course from code 087 String courseCode = request.getParameter("CodElp"); 088 Course course = searchCourse(catalog, lang, courseCode, field); 089 090 // Get the page 091 String url = resolvePage(request, course, field); 092 redirector.redirect(false, url); 093 094 return EMPTY_MAP; 095 } 096 097 private String getField() throws ResourceNotFoundException 098 { 099 String field = Config.getInstance().getValue("odf.ipweb.field"); 100 101 // Check if the configured field is valid 102 if (!_contentTypeEP.getExtension(CourseFactory.COURSE_CONTENT_TYPE).hasModelItem(field)) 103 { 104 throw new ResourceNotFoundException(String.format("The field '%s' is not defined on course type.", field)); 105 } 106 107 return field; 108 } 109 110 private String getLanguage() 111 { 112 return Optional.of("odf.ipweb.lang") 113 .map(Config.getInstance()::<String>getValue) 114 .filter(StringUtils::isNotEmpty) 115 .orElseGet(() -> Config.getInstance().getValue("odf.programs.lang")); 116 } 117 118 private String getCatalog() throws ResourceNotFoundException 119 { 120 String catalog = Optional.of("odf.ipweb.catalog") 121 .map(Config.getInstance()::<String>getValue) 122 .filter(StringUtils::isNotEmpty) 123 .orElseGet(_catalogsManager::getDefaultCatalogName); 124 125 // Check if the catalog is valid 126 if (_catalogsManager.getCatalog(catalog) == null) 127 { 128 throw new ResourceNotFoundException(String.format("The catalog '%s' does not exist", catalog)); 129 } 130 131 return catalog; 132 } 133 134 private Course searchCourse(String catalog, String lang, String code, String fieldCode) throws ResourceNotFoundException 135 { 136 AndExpression expression = new AndExpression(); 137 expression.add(new ContentTypeExpression(Operator.EQ, CourseFactory.COURSE_CONTENT_TYPE)); 138 expression.add(new StringExpression(ProgramItem.CATALOG, Operator.EQ, catalog)); 139 expression.add(new LanguageExpression(Operator.EQ, lang)); 140 expression.add(new StringExpression(fieldCode, Operator.EQ, code)); 141 142 String xpathQuery = ContentQueryHelper.getContentXPathQuery(expression); 143 AmetysObjectIterable<Course> courses = _resolver.query(xpathQuery); 144 145 if (courses.getSize() > 1) 146 { 147 throw new ResourceNotFoundException(String.format("There are several courses with %s '%s' in catalog '%s' with language '%s'", fieldCode, code, catalog, lang)); 148 } 149 150 Course course = courses.stream().findFirst().orElse(null); 151 if (course == null) 152 { 153 throw new ResourceNotFoundException(String.format("There is no course with %s '%s' in catalog '%s' with language '%s'", fieldCode, code, catalog, lang)); 154 } 155 156 return course; 157 } 158 159 private String resolvePage(Request request, Course course, String field) throws ResourceNotFoundException 160 { 161 String siteName = WebHelper.getSiteName(request); 162 163 // Get the page 164 CoursePage page = _odfPageResolver.getCoursePage(course, (AbstractProgram) null, siteName); 165 if (page == null) 166 { 167 throw new ResourceNotFoundException(String.format("There is no page for course with code '%s' in catalog '%s' with language '%s' on site '%s'", course.<String>getValue(field), course.getCatalog(), course.getLanguage(), siteName)); 168 } 169 170 return ResolveURIComponent.resolve("page", page.getId(), false, true, false); 171 } 172}