|
44 | 44 | import java.io.InputStream; |
45 | 45 | import java.io.Serializable; |
46 | 46 | import java.io.UnsupportedEncodingException; |
47 | | -import java.lang.reflect.Method; |
48 | 47 | import java.net.InetAddress; |
49 | | -import java.net.URI; |
50 | | -import java.net.URISyntaxException; |
51 | 48 | import java.net.URLDecoder; |
52 | 49 | import java.text.DateFormat; |
53 | 50 | import java.text.SimpleDateFormat; |
|
62 | 59 | import java.util.List; |
63 | 60 | import java.util.Locale; |
64 | 61 | import java.util.Map; |
65 | | -import java.util.Optional; |
66 | 62 | import java.util.Properties; |
67 | 63 | import java.util.Queue; |
68 | 64 | import java.util.Set; |
|
83 | 79 | import org.jsoup.Jsoup; |
84 | 80 | import org.jsoup.select.Elements; |
85 | 81 | import org.sakaiproject.authz.api.AuthzRealmLockException; |
86 | | -import org.sakaiproject.authz.api.SecurityAdvisor; |
87 | 82 | import org.sakaiproject.authz.api.SecurityService; |
88 | | -import org.sakaiproject.lti.util.SakaiLTIUtil; |
89 | 83 | import org.sakaiproject.component.cover.ComponentManager; |
90 | 84 | import org.sakaiproject.component.cover.ServerConfigurationService; |
91 | 85 | import org.sakaiproject.content.api.ContentHostingService; |
|
94 | 88 | import org.sakaiproject.entity.api.EntityTransferrer; |
95 | 89 | import org.sakaiproject.entity.api.HttpAccess; |
96 | 90 | import org.sakaiproject.entity.api.Reference; |
97 | | -import org.sakaiproject.entity.api.ResourceProperties; |
98 | 91 | import org.sakaiproject.entity.api.ResourcePropertiesEdit; |
99 | 92 | import org.sakaiproject.entity.cover.EntityManager; |
100 | 93 | import org.sakaiproject.entitybroker.EntityReference; |
|
105 | 98 | import org.sakaiproject.entitybroker.entityprovider.capabilities.Statisticable; |
106 | 99 | import org.sakaiproject.entitybroker.util.AbstractEntityProvider; |
107 | 100 | import org.sakaiproject.exception.IdUnusedException; |
| 101 | +import org.sakaiproject.grading.api.ConflictingAssignmentNameException; |
108 | 102 | import org.sakaiproject.lessonbuildertool.LessonBuilderAccessAPI; |
109 | 103 | import org.sakaiproject.lessonbuildertool.SimplePage; |
110 | 104 | import org.sakaiproject.lessonbuildertool.SimplePageGroup; |
|
120 | 114 | import org.sakaiproject.lessonbuildertool.tool.beans.OrphanPageFinder; |
121 | 115 | import org.sakaiproject.lessonbuildertool.tool.beans.SimplePageBean; |
122 | 116 | import org.sakaiproject.lti.api.LTIService; |
| 117 | +import org.sakaiproject.lti.util.SakaiLTIUtil; |
123 | 118 | import org.sakaiproject.memory.api.MemoryService; |
124 | | -import org.sakaiproject.util.api.LinkMigrationHelper; |
125 | | -import org.sakaiproject.grading.api.ConflictingAssignmentNameException; |
126 | 119 | import org.sakaiproject.site.api.Group; |
127 | 120 | import org.sakaiproject.site.api.Site; |
128 | 121 | import org.sakaiproject.site.api.SitePage; |
|
133 | 126 | import org.sakaiproject.time.api.TimeService; |
134 | 127 | import org.sakaiproject.tool.api.Session; |
135 | 128 | import org.sakaiproject.tool.api.SessionManager; |
136 | | -import org.sakaiproject.tool.api.Tool; |
137 | 129 | import org.sakaiproject.tool.api.ToolManager; |
138 | 130 | import org.sakaiproject.tool.api.ToolSession; |
139 | | -import org.sakaiproject.util.RequestFilter; |
| 131 | +import org.sakaiproject.util.MergeConfig; |
140 | 132 | import org.sakaiproject.util.ResourceLoader; |
141 | 133 | import org.sakaiproject.util.Xml; |
| 134 | +import org.sakaiproject.util.api.LinkMigrationHelper; |
142 | 135 | import org.springframework.context.MessageSource; |
143 | 136 | import org.w3c.dom.Attr; |
144 | 137 | import org.w3c.dom.DOMException; |
|
150 | 143 | import lombok.extern.slf4j.Slf4j; |
151 | 144 | import uk.org.ponder.messageutil.MessageLocator; |
152 | 145 |
|
153 | | -import org.sakaiproject.util.MergeConfig; |
154 | | - |
155 | 146 | /** |
156 | 147 | * @author hedrick |
157 | 148 | * The goal is to get sites to save and copy. However there's actually no data |
@@ -1656,7 +1647,8 @@ public String mergeInternal(String siteId, Element root, String archivePath, Str |
1656 | 1647 | toolsReused.put(title, page.getPageId()); |
1657 | 1648 | reused = true; |
1658 | 1649 | } else { |
1659 | | - page = simplePageToolDao.makePage("0", siteId, title, 0L, 0L); |
| 1650 | + // Create page with initial toolId, parent relationships will be set later |
| 1651 | + page = simplePageToolDao.makePage("0", siteId, title, null, null); |
1660 | 1652 | log.debug("Created new page {}", page.getPageId()); |
1661 | 1653 | } |
1662 | 1654 |
|
@@ -1721,7 +1713,83 @@ public String mergeInternal(String siteId, Element root, String archivePath, Str |
1721 | 1713 | pageElementMap.put(oldPageId, pageElement); |
1722 | 1714 | } |
1723 | 1715 |
|
1724 | | - log.debug("Starting second pass over pages ({}) {} to create items", pageElementMap.size(), pageMap); |
| 1716 | + log.debug("Starting hierarchy calculation for {} pages", pageMap.size()); |
| 1717 | + |
| 1718 | + Map<Long, Long> calculatedParentMap = new HashMap<>(); |
| 1719 | + Map<Long, Long> calculatedTopParentMap = new HashMap<>(); |
| 1720 | + |
| 1721 | + // Get parent-child relationships from source site |
| 1722 | + Map<Long, List<Long>> subpageRefs = findReferencedPagesByItems(fromSiteId); |
| 1723 | + |
| 1724 | + // Build parent map from subpage references |
| 1725 | + for (Map.Entry<Long, List<Long>> entry : subpageRefs.entrySet()) { |
| 1726 | + Long oldParentPageId = entry.getKey(); |
| 1727 | + List<Long> oldChildPageIds = entry.getValue(); |
| 1728 | + |
| 1729 | + if (!pageMap.containsKey(oldParentPageId)) continue; |
| 1730 | + |
| 1731 | + for (Long oldChildPageId : oldChildPageIds) { |
| 1732 | + if (pageMap.containsKey(oldChildPageId)) { |
| 1733 | + calculatedParentMap.put(oldChildPageId, oldParentPageId); |
| 1734 | + } |
| 1735 | + } |
| 1736 | + } |
| 1737 | + |
| 1738 | + // Calculate top parents by walking up the tree |
| 1739 | + for (Long pageId : calculatedParentMap.keySet()) { |
| 1740 | + Long currentPageId = pageId; |
| 1741 | + Long topParent = null; |
| 1742 | + |
| 1743 | + while (calculatedParentMap.containsKey(currentPageId)) { |
| 1744 | + topParent = calculatedParentMap.get(currentPageId); |
| 1745 | + currentPageId = topParent; |
| 1746 | + } |
| 1747 | + |
| 1748 | + if (topParent != null) { |
| 1749 | + calculatedTopParentMap.put(pageId, topParent); |
| 1750 | + } |
| 1751 | + } |
| 1752 | + |
| 1753 | + // Apply calculated relationships to imported pages |
| 1754 | + int hierarchyUpdates = 0; |
| 1755 | + for (Map.Entry<Long, Long> entry : pageMap.entrySet()) { |
| 1756 | + Long oldPageId = entry.getKey(); |
| 1757 | + Long newPageId = entry.getValue(); |
| 1758 | + |
| 1759 | + SimplePage page = simplePageToolDao.getPage(newPageId); |
| 1760 | + if (page == null) continue; |
| 1761 | + |
| 1762 | + boolean updated = false; |
| 1763 | + |
| 1764 | + // Set parent relationship |
| 1765 | + if (calculatedParentMap.containsKey(oldPageId)) { |
| 1766 | + Long oldParentId = calculatedParentMap.get(oldPageId); |
| 1767 | + Long newParentId = pageMap.get(oldParentId); |
| 1768 | + if (newParentId != null) { |
| 1769 | + page.setParent(newParentId); |
| 1770 | + updated = true; |
| 1771 | + } |
| 1772 | + } |
| 1773 | + |
| 1774 | + // Set top parent relationship |
| 1775 | + if (calculatedTopParentMap.containsKey(oldPageId)) { |
| 1776 | + Long oldTopParentId = calculatedTopParentMap.get(oldPageId); |
| 1777 | + Long newTopParentId = pageMap.get(oldTopParentId); |
| 1778 | + if (newTopParentId != null) { |
| 1779 | + page.setTopParent(newTopParentId); |
| 1780 | + updated = true; |
| 1781 | + } |
| 1782 | + } |
| 1783 | + |
| 1784 | + if (updated) { |
| 1785 | + simplePageToolDao.quickUpdate(page); |
| 1786 | + hierarchyUpdates++; |
| 1787 | + } |
| 1788 | + } |
| 1789 | + |
| 1790 | + if (hierarchyUpdates > 0) { |
| 1791 | + log.info("Updated page hierarchies for {} imported pages", hierarchyUpdates); |
| 1792 | + } |
1725 | 1793 |
|
1726 | 1794 | // Process pages we inserted (in PageElementMap) to create the items |
1727 | 1795 | boolean needFix = false; |
@@ -1899,6 +1967,37 @@ public String mergeInternal(String siteId, Element root, String archivePath, Str |
1899 | 1967 | log.debug(result); |
1900 | 1968 | results.append(result); |
1901 | 1969 | } |
| 1970 | + |
| 1971 | + // Update toolIds for child pages |
| 1972 | + int toolIdUpdates = 0; |
| 1973 | + for (Map.Entry<Long, Long> entry : pageMap.entrySet()) { |
| 1974 | + Long oldPageId = entry.getKey(); |
| 1975 | + Long newPageId = entry.getValue(); |
| 1976 | + |
| 1977 | + // Only process child pages (those with topparent) |
| 1978 | + if (calculatedTopParentMap.containsKey(oldPageId)) { |
| 1979 | + Long oldTopParentId = calculatedTopParentMap.get(oldPageId); |
| 1980 | + Long newTopParentId = pageMap.get(oldTopParentId); |
| 1981 | + |
| 1982 | + if (newTopParentId != null) { |
| 1983 | + SimplePage page = simplePageToolDao.getPage(newPageId); |
| 1984 | + SimplePage topParentPage = simplePageToolDao.getPage(newTopParentId); |
| 1985 | + |
| 1986 | + if (page != null && topParentPage != null && topParentPage.getToolId() != null |
| 1987 | + && !topParentPage.getToolId().equals("0") && !topParentPage.getToolId().equals(page.getToolId())) { |
| 1988 | + page.setToolId(topParentPage.getToolId()); |
| 1989 | + simplePageToolDao.quickUpdate(page); |
| 1990 | + toolIdUpdates++; |
| 1991 | + log.debug("Updated toolId {} for page {} from topparent {}", topParentPage.getToolId(), newPageId, newTopParentId); |
| 1992 | + } |
| 1993 | + } |
| 1994 | + } |
| 1995 | + } |
| 1996 | + |
| 1997 | + if (toolIdUpdates > 0) { |
| 1998 | + log.info("Updated toolIds for {} child pages", toolIdUpdates); |
| 1999 | + } |
| 2000 | + |
1902 | 2001 | results.append("merging lessonbuilder tool " + siteId + " (" + count + ") items.\n"); |
1903 | 2002 | } |
1904 | 2003 | catch (DOMException e) |
|
0 commit comments