Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SAK-51055 Samigo cc+ import issues with embedded image in CKEditor #13423

Merged
merged 6 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,7 @@ protected String fixLtiLaunchUrls(String text, String fromContext, String toCont

// If we cannot find the content item and tool on in this server, get skeleton data
// from the basiclti.xml import
if ( content == null && mcx.ltiContentItems != null ) {
if ( content == null && mcx != null && mcx.ltiContentItems != null ) {
log.debug("Could not find content item {} / {} in site {}, checking ltiContentItems", linkContentId, contentKey, linkSiteId);
content = mcx.ltiContentItems.get(contentKey);
tool = null; // force creation of a new tool in findOrCreateToolForContentItem
Expand Down
1 change: 1 addition & 0 deletions samigo/samigo-pack/src/webapp/WEB-INF/components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@
<property name="publishedAssessmentFacadeQueries" ref="PublishedAssessmentFacadeQueries" />
<property name="qtiService" ref="QTIService"/>
<property name="linkMigrationHelper" ref="org.sakaiproject.util.api.LinkMigrationHelper"/>
<property name="ltiService" ref="org.sakaiproject.lti.api.LTIService"/>
</bean>


Expand Down
4 changes: 4 additions & 0 deletions samigo/samigo-services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@
<groupId>org.sakaiproject.scheduler</groupId>
<artifactId>scheduler-api</artifactId>
</dependency>
<dependency>
<groupId>org.sakaiproject.lti</groupId>
<artifactId>lti-api</artifactId>
</dependency>
<dependency>
<groupId>org.mariuszgromada.math</groupId>
<artifactId>MathParser.org-mXparser</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.stream.Collectors;

import javax.xml.parsers.DocumentBuilder;
Expand Down Expand Up @@ -63,6 +64,7 @@
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.samigo.api.SamigoReferenceReckoner;
import org.sakaiproject.samigo.util.SamigoConstants;
import org.sakaiproject.lti.api.LTIService;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.site.api.ToolConfiguration;
Expand All @@ -71,6 +73,7 @@
import org.sakaiproject.tool.assessment.data.ifc.assessment.AnswerIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentMetaDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemFeedbackIfc;
import org.sakaiproject.tool.assessment.data.ifc.questionpool.QuestionPoolDataIfc;
import org.sakaiproject.tool.assessment.data.dao.assessment.*;
import org.sakaiproject.tool.assessment.data.dao.questionpool.QuestionPoolItemData;
Expand All @@ -81,6 +84,7 @@
import org.sakaiproject.tool.assessment.facade.SectionFacade;
import org.sakaiproject.tool.assessment.shared.api.questionpool.QuestionPoolServiceAPI;
import org.sakaiproject.util.api.LinkMigrationHelper;
import org.sakaiproject.util.MergeConfig;
import org.sakaiproject.tool.assessment.shared.api.qti.QTIServiceAPI;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
Expand Down Expand Up @@ -109,6 +113,7 @@ public class AssessmentEntityProducer implements EntityTransferrer, EntityProduc
@Getter @Setter protected UserDirectoryService userDirectoryService;
@Getter @Setter protected PublishedAssessmentFacadeQueriesAPI publishedAssessmentFacadeQueries;
@Setter protected LinkMigrationHelper linkMigrationHelper;
@Setter protected LTIService ltiService;

public void init() {
log.info("init()");
Expand Down Expand Up @@ -325,9 +330,9 @@ public String getLabel() {
return "samigo";
}

public String merge(String siteId, Element root, String archivePath,
String fromSiteId, Map attachmentNames, Map userIdTrans,
Set userListAllowImport) {
@Override
public String merge(String siteId, Element root, String archivePath, String fromSiteId, MergeConfig mcx) {

if (log.isDebugEnabled()) log.debug("merging " + getLabel());
StringBuilder results = new StringBuilder();
String qtiPath = (new File(archivePath)).getParent()
Expand Down Expand Up @@ -356,8 +361,12 @@ public String merge(String siteId, Element root, String archivePath,
+ id + ": " + t.getMessage() + "\n");
}
}

// Update the RTE text areas
Map<String, String> transversalMap = new HashMap<> ();
updateEntityReferencesInternal(siteId, transversalMap, mcx);
return results.toString();
}
}

public boolean parseEntityReference(String reference, Reference ref) {
if (StringUtils.startsWith(reference, REFERENCE_ROOT)) {
Expand Down Expand Up @@ -397,7 +406,13 @@ public Map<String, String> transferCopyEntities(String fromContext, String toCon

@Override
public void updateEntityReferences(String toContext, Map<String, String> transversalMap){
if (transversalMap != null && !transversalMap.isEmpty()) {
MergeConfig mcx = null;
updateEntityReferencesInternal(toContext, transversalMap, mcx);
}

// Internal, usable in either transferCopyEntities or merge()
public void updateEntityReferencesInternal(String toContext, Map<String, String> transversalMap, MergeConfig mcx){
if (mcx != null || (transversalMap != null && !transversalMap.isEmpty()) ) {
Set<Entry<String, String>> entrySet = transversalMap.entrySet();

AssessmentService service = new AssessmentService();
Expand All @@ -421,7 +436,9 @@ public void updateEntityReferences(String toContext, Map<String, String> transve

String assessmentDesc = assessmentFacade.getDescription();
if(StringUtils.isNotBlank(assessmentDesc)){
log.debug("before migrate assessmentDesc: {}", assessmentDesc);
assessmentDesc = org.sakaiproject.util.cover.LinkMigrationHelper.migrateAllLinks(entrySet, assessmentDesc);
log.debug("after migrate assessmentDesc: {}", assessmentDesc);
if(!assessmentDesc.equals(assessmentFacade.getDescription())){
//need to save since a ref has been updated:
needToUpdate = true;
Expand All @@ -434,7 +451,9 @@ public void updateEntityReferences(String toContext, Map<String, String> transve
SectionFacade section = (SectionFacade) sectionList.get(i);
String sectionDesc = section.getDescription();
if(StringUtils.isNotBlank(sectionDesc)){
log.debug("before migrate sectionDesc: {}", sectionDesc);
sectionDesc = org.sakaiproject.util.cover.LinkMigrationHelper.migrateAllLinks(entrySet, sectionDesc);
log.debug("after migrate sectionDesc: {}", sectionDesc);
if(!sectionDesc.equals(section.getDescription())){
//need to save since a ref has been updated:
needToUpdate = true;
Expand All @@ -453,25 +472,28 @@ public void updateEntityReferences(String toContext, Map<String, String> transve
continue;
}

// TODO: why are these copyAttachments = false?
boolean instructionChanged = migrateText(service, toContext, item, itemHash, hasCaches, hasDuplicates, false,
"inst", itemContentCache, entrySet, ItemData::getInstruction, ItemData::setInstruction);
"inst", itemContentCache, entrySet, transversalMap, mcx, ItemData::getInstruction, ItemData::setInstruction);

boolean descriptionChanged = migrateText(service, toContext, item, itemHash, hasCaches, hasDuplicates, false,
"desc", itemContentCache, entrySet, ItemData::getDescription, ItemData::setDescription);
"desc", itemContentCache, entrySet, transversalMap, mcx, ItemData::getDescription, ItemData::setDescription);

boolean itemTextsChanged = false;
List<ItemTextIfc> itemTexts = item.getItemTextArray();
if (itemTexts != null) {
for (ItemTextIfc itemText : itemTexts) {
boolean itemTextChanged = migrateText(service, toContext, itemText, itemHash, hasCaches, hasDuplicates, true,
"it-" + itemText.getSequence(), itemContentCache, entrySet, ItemTextIfc::getText, ItemTextIfc::setText);
"it-" + itemText.getSequence(), itemContentCache, entrySet, transversalMap,
mcx, ItemTextIfc::getText, ItemTextIfc::setText);

boolean answersChanged = false;
List<AnswerIfc> answers = itemText.getAnswerArray();
if (answers != null) {
for (AnswerIfc answer : answers) {
boolean answerChanged = migrateText(service, toContext, answer, itemHash, hasCaches, hasDuplicates, true,
"at-" + itemText.getSequence() + "-"+ answer.getSequence() , itemContentCache, entrySet, AnswerIfc::getText, AnswerIfc::setText);
"at-" + itemText.getSequence() + "-"+ answer.getSequence() , itemContentCache, entrySet, transversalMap,
mcx, AnswerIfc::getText, AnswerIfc::setText);

answersChanged = answersChanged || answerChanged;
}
Expand All @@ -481,9 +503,21 @@ public void updateEntityReferences(String toContext, Map<String, String> transve
}
}

boolean itemFeedbacksChanged = false;
if ( item.getItemFeedbackSet() != null && !item.getItemFeedbackSet().isEmpty() ) {
for (ItemFeedbackIfc itemFeedback : item.getItemFeedbackSet()) {
boolean itemFeedbackCHanged = migrateText(service, toContext, itemFeedback, itemHash, hasCaches, hasDuplicates, true,
"feedback" + itemFeedback.getTypeId(), itemContentCache, entrySet, transversalMap,
mcx, ItemFeedbackIfc::getText, ItemFeedbackIfc::setText);

itemFeedbacksChanged = itemFeedbacksChanged || itemFeedbackCHanged;
}
}

boolean needToUpdateItem = instructionChanged
|| descriptionChanged
|| itemTextsChanged;
|| itemTextsChanged
|| itemFeedbacksChanged;
needToUpdateCache.put(itemHash, needToUpdateItem);

needToUpdate = needToUpdate || needToUpdateItem;
Expand Down Expand Up @@ -776,34 +810,41 @@ private List<String> getAttachmentResourceIds(NodeList list) {

private <T> boolean migrateText(AssessmentService assessmentService, String toContext, T item, String itemHash,
boolean hasCaches,boolean hasDuplicates, boolean copyAttachments, String cacheCode, Map<String, String> textCache,
Set<Entry<String, String>> entrySet, Function<T, String> getter, BiConsumer<T, String> setter) {
Set<Entry<String, String>> entrySet, Map<String, String> transversalMap, MergeConfig mcx,
Function<T, String> getter, BiConsumer<T, String> setter) {

log.debug("migrateText: {} {}", itemHash, copyAttachments);
String cacheKey = itemHash + "-" + cacheCode;

if (hasCaches && textCache.containsKey(cacheKey)) {
// Item instruction has been cashed, lets get it form the cache
// Item instruction has been cached, lets get it from the cache
setter.accept(item, textCache.get(cacheKey));
return true;
} else {
// Item instruction has not been cached, lets try migrating
String itemText = StringUtils.trimToEmpty(getter.apply(item));
String migratedText;
if (copyAttachments) {
migratedText = assessmentService.copyContentHostingAttachments(itemText, toContext);
log.debug("itemText before {}", itemText);
if ( mcx != null ) {
migratedText = ltiService.fixLtiLaunchUrls(itemText, toContext, mcx);
migratedText = linkMigrationHelper.migrateLinksInMergedRTE(toContext, mcx, migratedText);
} else {
migratedText = itemText;
if (copyAttachments) {
migratedText = assessmentService.copyContentHostingAttachments(itemText, toContext);
} else {
migratedText = itemText;
}
migratedText = linkMigrationHelper.migrateAllLinks(entrySet, migratedText);
migratedText = ltiService.fixLtiLaunchUrls(migratedText, null, toContext, transversalMap);
}

migratedText = linkMigrationHelper.migrateAllLinks(entrySet, migratedText);
log.debug("migratedText after {}", migratedText);

// Check if there has been a change
if (!StringUtils.equals(itemText, migratedText)) {
setter.accept(item, migratedText);

if (hasDuplicates) {
textCache.put(cacheKey, migratedText);
}

return true;
}
}
Expand Down
Loading