Skip to content
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
3 changes: 0 additions & 3 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ api/src/org/labkey/api/action/StatusReportingRunnableAction.java -text
api/src/org/labkey/api/action/UrlProvider.java -text
api/src/org/labkey/api/admin/AbstractFolderContext.java -text
api/src/org/labkey/api/admin/AbstractFolderImportFactory.java -text
api/src/org/labkey/api/admin/AbstractImportContext.java -text
api/src/org/labkey/api/admin/ActionsHelper.java -text
api/src/org/labkey/api/admin/AdminBean.java -text
api/src/org/labkey/api/admin/AdminConsoleHeaderLinkProvider.java -text
Expand All @@ -217,7 +216,6 @@ api/src/org/labkey/api/admin/FolderSerializationRegistry.java -text
api/src/org/labkey/api/admin/FolderWriter.java -text
api/src/org/labkey/api/admin/FolderWriterFactory.java -text
api/src/org/labkey/api/admin/FolderWriterImpl.java -text
api/src/org/labkey/api/admin/ImportContext.java -text
api/src/org/labkey/api/admin/ImportException.java -text
api/src/org/labkey/api/admin/ImportOptions.java -text
api/src/org/labkey/api/admin/InvalidFileException.java -text
Expand Down Expand Up @@ -3170,7 +3168,6 @@ study/src/org/labkey/study/importer/StudyImporter.java -text
study/src/org/labkey/study/importer/StudyImporterFactory.java -text
study/src/org/labkey/study/importer/StudyImportFinalTask.java -text
study/src/org/labkey/study/importer/StudyImportInitialTask.java -text
study/src/org/labkey/study/importer/StudyJobSupport.java -text
study/src/org/labkey/study/importer/StudyViewsImporter.java -text
study/src/org/labkey/study/importer/TopLevelStudyPropertiesImporter.java -text
study/src/org/labkey/study/importer/TreatmentDataImporter.java -text
Expand Down
9 changes: 9 additions & 0 deletions wiki/schemas/wiki.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
</xsd:complexType>

<xsd:complexType name="wikiType">
<xsd:all>
<xsd:element name="aliases" minOccurs="0">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="alias" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation>The wiki page's name</xsd:documentation>
Expand Down
19 changes: 11 additions & 8 deletions wiki/src/org/labkey/wiki/WikiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -590,13 +590,16 @@ public boolean handlePost(WikiManageForm form, BindException errors)
Collection<String> existingAliases = WikiSelectManager.getAliases(getContainer(), _wiki.getRowId());
if (!newAliases.equals(existingAliases))
{
WikiManager mgr = WikiManager.get();
mgr.deleteAliases(c, wiki);

// Best effort for alias editing -- reshow with error message if duplicates are encountered, but
// regardless of errors, complete all other edits.
newAliases.forEach(alias->mgr.addAlias(getUser(), _wiki, alias, errors));
WikiCache.uncache(c, wiki, true);
try
{
// Best effort for alias editing -- reshow with error message if duplicates are encountered, but
// regardless of errors here, complete all other edits.
WikiManager.get().replaceAliases(_wiki, newAliases, errors);
}
finally
{
WikiCache.uncache(c, wiki, true);
}
}

getWikiManager().updateWiki(getUser(), _wiki, _wikiVersion, false);
Expand Down Expand Up @@ -2337,7 +2340,7 @@ protected ApiResponse insertWiki(SaveWikiForm form) throws Exception

//insert new wiki and new version
User user = getUser();
getWikiManager().insertWiki(user, c, wiki, wikiversion, null, false);
getWikiManager().insertWiki(user, c, wiki, wikiversion, null, false, null);

//if webPartId was sent, update the corresponding
//web part to show the newly inserted page
Expand Down
76 changes: 57 additions & 19 deletions wiki/src/org/labkey/wiki/WikiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ public Wiki getWikiByEntityId(Container c, String entityId)
null).getObject(Wiki.class);
}


public void insertWiki(User user, Container c, Wiki wikiInsert, WikiVersion wikiversion, List<AttachmentFile> files, boolean copyHistory) throws IOException
// aliases: null and empty collection are equivalent (no aliases)
public void insertWiki(User user, Container c, Wiki wikiInsert, WikiVersion wikiversion, List<AttachmentFile> files, boolean copyHistory, @Nullable Collection<String> aliases) throws IOException
{
DbScope scope = comm.getSchema().getScope();

Expand Down Expand Up @@ -205,6 +205,11 @@ public void insertWiki(User user, Container c, Wiki wikiInsert, WikiVersion wiki

getAttachmentService().addAttachments(wikiInsert.getAttachmentParent(), files, user);

if (null != aliases)
{
WikiManager.get().addAliases(wikiInsert, aliases, null);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we delete existing aliases if there aren't any being passed in?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need... this is insertWiki(), so there are no aliases associated with the brand new wiki.

}

transaction.commit();
}
finally
Expand Down Expand Up @@ -313,21 +318,47 @@ private boolean updateWiki(User user, Wiki wikiNew, WikiVersion versionNew, bool
return true;
}

public void addAlias(User user, Wiki wiki, String alias, BindException errors)
/**
* Attempts to add the specified aliases to the specified wiki. This is a best effort operation; failure to add an
* alias (e.g., an alias that already exists in this container) will result in an error (added to the BindException
* collection if not null, otherwise logged as a warning) but adding will continue and no exception will be thrown.
*
* Callers are responsible for uncaching this wiki and the wiki container collections
*/
public void addAliases(Wiki wiki, @NotNull Collection<String> aliases, @Nullable BindException errors)
{
assert null != wiki.getContainerId();
Map<String, Object> map = new HashMap<>(Map.of("Container", wiki.getContainerId(), "Alias", alias, "PageRowId", wiki.getRowId()));
try
{
Table.insert(user, CommSchema.getInstance().getTableInfoPageAliases(), map);
}
catch (RuntimeSQLException e)
SqlExecutor executor = new SqlExecutor(CommSchema.getInstance().getSchema());

aliases.forEach(alias->
{
if (e.isConstraintException())
errors.rejectValue("name", ERROR_MSG, "Warning: Alias '" + alias + "' already exists in this folder.");
}
// Table.insert() provides no way to conditionalize the insert, resulting in constraint violation exceptions
// that kill the current transaction on PostgreSQL. We want "best effort" inserts here, so execute custom
// INSERT SQL instead.
SQLFragment sql = new SQLFragment("INSERT INTO ")
.append(CommSchema.getInstance().getTableInfoPageAliases().getSelectName())
.append(" (Container, Alias, PageRowId) SELECT ?, ?, ?\n")
.add(wiki.getContainerId())
.add(alias)
.add(wiki.getRowId())
.append("WHERE NOT EXISTS (SELECT * FROM ")
.append(CommSchema.getInstance().getTableInfoPageAliases().getSelectName())
.append(" WHERE Container = ? AND LOWER(Alias) = LOWER(?))")
.add(wiki.getContainerId())
.add(alias);
int rows = executor.execute(sql);

if (0 == rows)
{
if (null != errors)
errors.rejectValue("name", ERROR_MSG, "Warning: Alias '" + alias + "' already exists in this folder.");
else
LOG.warn("Attempt to add alias to wiki \"" + wiki.getName() + "\" failed; \"" + alias + "\" already exists in this folder.");
}
});
}

// Callers are responsible for uncaching this wiki and the wiki container collections
// null == wiki ==> delete all aliases in a container
// null != wiki ==> delete all aliases associated with a wiki
public void deleteAliases(Container c, @Nullable Wiki wiki)
Expand All @@ -339,6 +370,13 @@ public void deleteAliases(Container c, @Nullable Wiki wiki)
Table.delete(CommSchema.getInstance().getTableInfoPageAliases(), filter);
}

// Callers are responsible for uncaching this wiki and the wiki container collections
public void replaceAliases(Wiki wiki, Collection<String> newAliases, @Nullable BindException errors)
{
deleteAliases(wiki.lookupContainer(), wiki);
addAliases(wiki, newAliases, errors);
}

public void deleteWiki(User user, Container c, Wiki wiki, boolean isDeletingSubtree) throws SQLException
{
//shift children to new parent, or delete recursively if deleting the whole subtree
Expand Down Expand Up @@ -526,11 +564,11 @@ public Wiki copyPage(User user, Container cSrc, Wiki srcPage, Container cDest, L
Wiki wiki = WikiSelectManager.getWiki(cSrc, srcName);
Collection<Attachment> attachments = wiki.getAttachments();
List<AttachmentFile> files = getAttachmentService().getAttachmentFiles(wiki.getAttachmentParent(), attachments);

Collection<String> aliases = WikiSelectManager.getAliases(cSrc, wiki.getRowId());

final WikiVersion[] wikiVersions;

if(!isCopyingHistory)
if (!isCopyingHistory)
{
wikiVersions = new WikiVersion[] { srcPage.getLatestVersion() };
}
Expand All @@ -540,7 +578,7 @@ public Wiki copyPage(User user, Container cSrc, Wiki srcPage, Container cDest, L
}

boolean firstVersion = true;
for(WikiVersion wikiVersion : wikiVersions)
for (WikiVersion wikiVersion : wikiVersions)
{
//new wiki version
WikiVersion newWikiVersion = new WikiVersion(destName);
Expand All @@ -550,9 +588,9 @@ public Wiki copyPage(User user, Container cSrc, Wiki srcPage, Container cDest, L
newWikiVersion.setCreated((wikiVersion.getCreated()));
newWikiVersion.setRendererTypeEnum(wikiVersion.getRendererTypeEnum());

if(firstVersion)
if (firstVersion)
{
insertWiki(user, cDest, newWikiPage, newWikiVersion, files, isCopyingHistory);
insertWiki(user, cDest, newWikiPage, newWikiVersion, files, isCopyingHistory, aliases);
firstVersion = false;
}
else
Expand Down Expand Up @@ -862,7 +900,7 @@ public void insertWiki(User user, Container c, String name, String body, WikiRen

try
{
insertWiki(user, c, wiki, wikiversion, null, false);
insertWiki(user, c, wiki, wikiversion, null, false, null);
}
catch (IOException e)
{
Expand Down Expand Up @@ -1096,7 +1134,7 @@ public void testWiki() throws IOException, SQLException
wikiversion.setTitle("Topic A");
wikiversion.setBody("[pageA]");

_m.insertWiki(user, c, wikiA, wikiversion, null, false);
_m.insertWiki(user, c, wikiA, wikiversion, null, false, null);

// verify objects
wikiA = WikiSelectManager.getWikiFromDatabase(c, "pageA");
Expand Down
2 changes: 1 addition & 1 deletion wiki/src/org/labkey/wiki/WikiModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private void loadWikiContent(@Nullable Container c, User user, String name, Stri

try
{
getWikiManager().insertWiki(user, c, wiki, wikiversion, null, false);
getWikiManager().insertWiki(user, c, wiki, wikiversion, null, false, null);
}
catch (IOException e)
{
Expand Down
2 changes: 1 addition & 1 deletion wiki/src/org/labkey/wiki/WikiSelectManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
public class WikiSelectManager
{
// List of page names in this folder, in depth-first tree order
public static List<String> getPageNames(Container c)
public static @NotNull List<String> getPageNames(Container c)
{
return getWikiCollections(c).getNames();
}
Expand Down
33 changes: 13 additions & 20 deletions wiki/src/org/labkey/wiki/WikiWebdavProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,16 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* User: matthewb
* Date: Oct 21, 2008
* Time: 9:52:40 AM
* WikiWebdavProvider is NOT used. It was previously registered to provide a WebDAV @wiki node but was unregistered in
* 2019 since clients didn't seem to be using it.
*/

public class WikiWebdavProvider implements WebdavService.Provider
{
final static String WIKI_NAME = "@wiki";

// currently addChildren is called only for web folders
// currently, addChildren is called only for web folders
@Override
@Nullable
public Set<String> addChildren(@NotNull WebdavResource target, boolean isListing)
Expand Down Expand Up @@ -154,8 +151,7 @@ public Collection<String> listNames()
List<String> names = WikiSelectManager.getPageNames(_c);
ArrayList<String> strs = new ArrayList<>();
strs.add(WikiWriterFactory.WIKIS_FILENAME);
if (names != null)
strs.addAll(names);
strs.addAll(names);

return strs;
}
Expand Down Expand Up @@ -211,7 +207,7 @@ public String getExecuteHref(ViewContext context)
}

/** An XML file with metadata about all wikis in current container,
* including parenting, title, whether or not to show attachments, etc */
* including parenting, title, whether to show attachments, etc */
public static class WikiMetadata extends AbstractDocumentResource
{
private final WikiProviderResource _parent;
Expand Down Expand Up @@ -277,8 +273,14 @@ private byte[] getContent() throws IOException
wikiXml.setTitle(wikiVersion.getTitle());
wikiXml.setShowAttachments(wiki.isShowAttachments());
wikiXml.setShouldIndex(wiki.isShouldIndex());
List<String> attachmentNames = wiki.getAttachments().stream().map(Attachment::getName).collect(Collectors.toList());
List<String> attachmentNames = wiki.getAttachments().stream().map(Attachment::getName).toList();
wikiXml.setAttachmentsOrder(StringUtils.join(attachmentNames, ';'));
Collection<String> aliases = WikiSelectManager.getAliases(_parent._c, wiki.getRowId());
if (!aliases.isEmpty())
{
WikiType.Aliases aliasesXml = wikiXml.addNewAliases();
aliasesXml.setAliasArray(aliases.toArray(new String[0]));
}
}

XmlOptions options = new XmlOptions();
Expand Down Expand Up @@ -308,7 +310,6 @@ public long getContentLength() throws IOException
return getContent().length;
}
}


public static class WikiFolder extends AbstractWebdavResourceCollection
{
Expand All @@ -327,14 +328,12 @@ public static class WikiFolder extends AbstractWebdavResourceCollection
_attachments = AttachmentService.get().getAttachmentResource(getPath(), _wiki.getAttachmentParent());
}


@Override
public boolean canDelete(User user, boolean forDelete, List<String> message)
{
return false; // NYI
}


@Override
public boolean canRename(User user, boolean forRename)
{
Expand All @@ -347,7 +346,6 @@ public boolean canCreateCollection(User user, boolean forCreate)
return false;
}


@Override
public boolean exists()
{
Expand All @@ -360,8 +358,7 @@ public synchronized Collection<String> listNames()
{
if (!exists())
return Collections.emptyList();
List<String> ret = new ArrayList<>();
ret.addAll(_attachments.listNames());
List<String> ret = new ArrayList<>(_attachments.listNames());
ret.add(getDocumentName(_wiki));
return ret;
}
Expand Down Expand Up @@ -401,21 +398,18 @@ public String getExecuteHref(ViewContext context)
}
}


static String getResourcePath(Wiki page)
{
String docname = getDocumentName(page);
return AbstractWebdavResource.c(page.getContainerPath(), WIKI_NAME, page.getName(), docname);
}


static String getResourcePath(Container c, String name, WikiRendererType type)
{
String docname = type.getDocumentName(name);
return AbstractWebdavResource.c(c.getPath(), WIKI_NAME, name,docname);
}


public static String getDocumentName(Wiki wiki)
{
WikiVersion v = wiki.getLatestVersion();
Expand All @@ -430,7 +424,6 @@ public static String getDocumentName(Wiki wiki)
return r.getDocumentName(wiki.getName());
}


public static class WikiPageResource extends AbstractDocumentResource
{
@Nullable WikiFolder _folder = null;
Expand Down
Loading