diff --git a/.hgtags b/.hgtags index ffea6a03ad7c21ae4e7fada7bcc96baa046d76f6..c6c9e6aaca1144a55438bbdd669479ea38de2af7 100644 --- a/.hgtags +++ b/.hgtags @@ -217,3 +217,4 @@ de92931b87a20ec26edb2c65e3496c471bce6481 OpenOLAT 12.3.2 a83d9c176d6c269b4ec124d7700f961e15b2a508 OpenOLAT 12.3.3 e4c7003b290148810092848bc73bcec4e61da7be OpenOLAT 12.4.0 f55676080d2436df8078a8a0f1f6fb1afbdbe58c OpenOLAT 12.4.1 +0810e24414f8cbb68dd6914297d883faf9527469 OpenOLAT 12.4.2 diff --git a/src/main/java/org/olat/core/util/Formatter.java b/src/main/java/org/olat/core/util/Formatter.java index 3b172294d014173a5c2ecb472901c304b73a41ef..a4356f856ae82b665312ec876973eaab32a45142 100644 --- a/src/main/java/org/olat/core/util/Formatter.java +++ b/src/main/java/org/olat/core/util/Formatter.java @@ -663,11 +663,25 @@ public class Formatter { sb.append("<").append(elem).append(" id=\"").append(domid).append("\">"); sb.append(htmlFragment); sb.append("</").append(elem).append(">"); - sb.append("\n<script type='text/javascript'>\n/* <![CDATA[ */\n setTimeout(function() { BFormatter.formatLatexFormulas('").append(domid).append("');}, 100);\n/* ]]> */\n</script>"); + sb.append(elementLatexFormattingScript(domid)); return sb.toString(); } return htmlFragment; } + + /** + * Html code script to render the latex formulas of a given element id + * @param domid Id of the DOM node containing the elements to render. + */ + public static String elementLatexFormattingScript(String domid) { + return String.format("%n" + + "<script type='text/javascript'>%n" + + "/* <![CDATA[ */%n" + + " jQuery(function() {setTimeout(function() { BFormatter.formatLatexFormulas('%s');}, 100); }); %n" + + "/* ]]> */%n" + + "</script>", + domid); + } // Pattern to find URL's in text diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java index 45b5077e794459f2d56382e6c87798be7c7b0484..e65baceb53d8e2a80124f954f5d26eb41b7bc7d8 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java @@ -766,8 +766,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD // 1) Delete all group properties CollaborationTools ct = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(group); ct.deleteTools(group);// deletes everything concerning properties&collabTools - // 1.c)delete user in security groups - //removeFromRepositoryEntrySecurityGroup(group); // 2) Delete the group areas areaManager.deleteBGtoAreaRelations(group); // 3) Delete the relations @@ -783,8 +781,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD infoMessageManager.removeInfoMessagesAndSubscriptionContext(group); // 7) the group businessGroupDAO.delete(group); - // 8) delete the associated security groups - //TODO group dbInstance.commit(); diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java index b4a38444a428ea6756e1279e762f0827b812e34a..d56f17be9db0aa7b57e5db10247cf2f657b0b695 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java @@ -83,6 +83,7 @@ import org.olat.core.helpers.Settings; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.CodeHelper; +import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.ims.qti21.QTI21Constants; @@ -97,6 +98,7 @@ import uk.ac.ed.ph.jqtiplus.attribute.Attribute; import uk.ac.ed.ph.jqtiplus.attribute.AttributeList; import uk.ac.ed.ph.jqtiplus.attribute.ForeignAttribute; import uk.ac.ed.ph.jqtiplus.attribute.value.IntegerAttribute; +import uk.ac.ed.ph.jqtiplus.attribute.value.StringAttribute; import uk.ac.ed.ph.jqtiplus.attribute.value.StringMultipleAttribute; import uk.ac.ed.ph.jqtiplus.node.ForeignElement; import uk.ac.ed.ph.jqtiplus.node.QtiNode; @@ -470,15 +472,29 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent } case RubricBlock.QTI_CLASS_NAME: break; //never rendered automatically case Math.QTI_CLASS_NAME: { + String domid = "mw_" + CodeHelper.getRAMUniqueID(); + sb.append("<div id=\"").append(domid).append("\">"); renderMath(renderer, sb, component, resolvedAssessmentItem, itemSessionState, (Math)block); + sb.append("</div>") + .append(Formatter.elementLatexFormattingScript(domid)); break; } - case Div.QTI_CLASS_NAME: + case Div.QTI_CLASS_NAME: { + String domid = null; + if (containsClass(block, "math")) { + domid = "mw_" + CodeHelper.getRAMUniqueID(); + sb.append("<div id=\"").append(domid).append("\">"); + } renderStartHtmlTag(sb, component, resolvedAssessmentItem, block, null); ((Div)block).getFlows().forEach((flow) -> renderFlow(renderer, sb, component, resolvedAssessmentItem, itemSessionState, flow, ubu, translator)); renderEndTag(sb, block); + if (domid != null) { + sb.append("</div>") + .append(Formatter.elementLatexFormattingScript(domid)); + } break; + } case Ul.QTI_CLASS_NAME: renderStartHtmlTag(sb, component, resolvedAssessmentItem, block, null); ((Ul)block).getLis().forEach((li) @@ -672,7 +688,11 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent break; } case Math.QTI_CLASS_NAME: { + String domid = "mw_" + CodeHelper.getRAMUniqueID(); + sb.append("<span id=\"").append(domid).append("\">"); renderMath(renderer, sb, component, resolvedAssessmentItem, itemSessionState, (Math)inline); + sb.append("</span>") + .append(Formatter.elementLatexFormattingScript(domid)); break; } case Img.QTI_CLASS_NAME: { @@ -709,9 +729,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent protected final void renderSpan(AssessmentRenderer renderer, StringOutput sb, Span span, AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem, ItemSessionState itemSessionState, URLBuilder ubu, Translator translator) { - StringMultipleAttribute attrClass = span.getAttributes().getStringMultipleAttribute("class"); - - if (attrClass != null && attrClass.getValue() != null && attrClass.getValue().contains("math")) { + if (containsClass(span,"math")) { String domid = "mw_" + CodeHelper.getRAMUniqueID(); sb.append("<span id=\"").append(domid).append("\">"); @@ -721,7 +739,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent renderEndTag(sb, span); sb.append("</span>") - .append("\n<script type='text/javascript'>\n/* <![CDATA[ */\n jQuery(function() {setTimeout(function() { BFormatter.formatLatexFormulas('").append(domid).append("');}, 100); }); \n/* ]]> */\n</script>"); + .append(Formatter.elementLatexFormattingScript(domid)); } else { renderStartHtmlTag(sb, component, resolvedAssessmentItem, span, null); span.getInlines().forEach((child) @@ -1391,10 +1409,15 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent renderer.setMathXsltDisabled(true); try(StringOutput mathOutput = StringOutputPool.allocStringBuilder(2048)) { - mathOutput.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"); + if (!math.getAttributes().contains("xmlns")) { + StringAttribute xmlnsAttribute = new StringAttribute(math, "xmlns", false); + xmlnsAttribute.setValue("http://www.w3.org/1998/Math/MathML"); + math.getAttributes().add(xmlnsAttribute); + } + renderStartHtmlTag(mathOutput, component, resolvedAssessmentItem, math, null); math.getContent().forEach((foreignElement) -> renderMath(renderer, mathOutput, component, resolvedAssessmentItem, itemSessionState, foreignElement)); - mathOutput.append("</math>"); + renderEndTag(mathOutput, math); String enrichedMathML = StringOutputPool.freePop(mathOutput); renderer.setMathXsltDisabled(false); transformMathmlAsString(sb, enrichedMathML); @@ -1449,7 +1472,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent renderEndTag(out, fElement); } } else if(mathElement instanceof TextRun) { - out.append(((TextRun)mathElement).getTextContent()); + out.append(StringEscapeUtils.escapeXml(((TextRun)mathElement).getTextContent())); } } @@ -1588,7 +1611,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent sb.append("<span class='o_error'>ERROR MATHML</span>"); } } - + protected boolean containsClass(QtiNode element, String marker) { AttributeList attributes = element.getAttributes(); for(int i=attributes.size(); i-->0; ) { diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java index d883dcd785e58af4534becf44922ff6311e69209..af2273133dd3efcdc73b4baf1db5fa9dc2b1917a 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java @@ -593,6 +593,8 @@ public class AssessmentRenderFunctions { case "class": case "contextmenu": case "dir": + case "display": + case "download": case "hidden": case "name": case "id": @@ -603,6 +605,7 @@ public class AssessmentRenderFunctions { case "style": case "width": case "height": + case "xmlns": value = getDomAttributeValue(attribute); break; case "href": diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java index de5500e0b027af5605c14ea1ad591e262f7a9a9c..ded1bd8c82a3a1812fa48b6d602e8b56227a6242 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java +++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java @@ -37,6 +37,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.olat.basesecurity.Group; import org.olat.basesecurity.IdentityRef; import org.olat.basesecurity.manager.GroupDAO; +import org.olat.collaboration.CollaborationTools; import org.olat.core.commons.modules.bc.vfs.OlatRootFileImpl; import org.olat.core.commons.persistence.DB; import org.olat.core.gui.translator.Translator; @@ -60,6 +61,8 @@ import org.olat.course.run.scoring.AssessmentEvaluation; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.fileresource.FileResourceManager; +import org.olat.group.BusinessGroup; +import org.olat.group.DeletableGroupData; import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.assessment.AssessmentService; import org.olat.modules.assessment.Role; @@ -112,6 +115,8 @@ import org.olat.modules.portfolio.model.SectionImpl; import org.olat.modules.portfolio.model.SectionKeyRef; import org.olat.modules.portfolio.model.SynchedBinder; import org.olat.modules.portfolio.ui.PortfolioHomeController; +import org.olat.properties.NarrowedPropertyManager; +import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryService; @@ -130,7 +135,7 @@ import com.thoughtworks.xstream.XStream; * */ @Service -public class PortfolioServiceImpl implements PortfolioService { +public class PortfolioServiceImpl implements PortfolioService, DeletableGroupData { private static final OLog log = Tracing.createLoggerFor(PortfolioServiceImpl.class); @@ -262,6 +267,24 @@ public class PortfolioServiceImpl implements PortfolioService { return binder; } + @Override + public boolean deleteGroupDataFor(BusinessGroup group) { + NarrowedPropertyManager npm = NarrowedPropertyManager.getInstance(group); + Property mapKeyProperty = npm.findProperty(null, null, CollaborationTools.PROP_CAT_BG_COLLABTOOLS, CollaborationTools.KEY_PORTFOLIO); + if (mapKeyProperty != null) { + Long mapKey = mapKeyProperty.getLongValue(); + String version = mapKeyProperty.getStringValue(); + if("2".equals(version)) { + Binder binder = binderDao.loadByKey(mapKey); + if(binder != null) { + deleteBinder(binder); + } + } + return true; + } + return false; + } + @Override public boolean detachCourseFromBinders(RepositoryEntry entry) { int deletedRows = binderDao.detachBinderFromRepositoryEntry(entry); diff --git a/src/main/java/org/olat/modules/wiki/Wiki.java b/src/main/java/org/olat/modules/wiki/Wiki.java index ed4d92c1c1fb4a42a49dd1bd339692294cd9965e..399b4d44432803919ed54cf3b5428063a5119733 100644 --- a/src/main/java/org/olat/modules/wiki/Wiki.java +++ b/src/main/java/org/olat/modules/wiki/Wiki.java @@ -152,8 +152,14 @@ public class Wiki implements WikiContainer, Serializable { return page; } if (loadContent) { - VFSLeaf leaf = (VFSLeaf) pageContainer.resolve(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX); - page.setContent(FileUtils.load(leaf.getInputStream(), "utf-8")); + VFSItem item = pageContainer.resolve(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX); + if(item instanceof VFSLeaf) { + try(InputStream in = ((VFSLeaf)item).getInputStream()) { + page.setContent(FileUtils.load(in, "utf-8")); + } catch(Exception e) { + log.error("Cannot load wiki page: " + item, e); + } + } } return page; } diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 0d10dca0f45831dddfa443a9f97411fa2f006bca..ab6e4e7be6b2b8a893be212cadebf90e99289ba1 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -1130,8 +1130,8 @@ ldap.learningResourceManagerRoleValue= # Build properties ##### application.name=OpenOLAT -build.version=12.4.1 -build.identifier=openolat1241-dev +build.version=12.4.2 +build.identifier=openolat1242-dev build.repo.revision=local-devel ##### diff --git a/src/test/java/org/olat/core/util/FormatterTest.java b/src/test/java/org/olat/core/util/FormatterTest.java index 60073f1557c7ec2b6a156e688fbd7a0d6b82ac7a..54db23da304b7717546b2c5174c20340bc2cad97 100644 --- a/src/test/java/org/olat/core/util/FormatterTest.java +++ b/src/test/java/org/olat/core/util/FormatterTest.java @@ -22,6 +22,7 @@ package org.olat.core.util; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; +import java.util.UUID; import org.apache.commons.lang.StringEscapeUtils; import org.junit.Assert; @@ -132,4 +133,12 @@ public class FormatterTest { Assert.assertEquals("32:23:45", Formatter.formatTimecode(116625000l)); Assert.assertEquals("532:23:45", Formatter.formatTimecode(1916625000l)); } + + @Test + public void elementLatexFormattingScript() { + String domId = UUID.randomUUID().toString(); + String latextFormatterJs = Formatter.elementLatexFormattingScript(domId); + Assert.assertNotNull(latextFormatterJs); + Assert.assertTrue(latextFormatterJs.contains(domId)); + } }