Nested Spaces
- XWiki
- Feature
- Completed
- [Iteration][UX] Extended Breadcrumb http://markmail.org/message/rab6vbxd6743gmrc (May 22, 2015)
- [Proposal] Introduce the notion of Nested Documents http://markmail.org/message/obuz4c27t4hf4jdc (Jun 3, 2015)
- [VOTE] Summary: NS, ND, Parent/Child http://markmail.org/thread/4555ofhj3dpzo5qe (Jun 23, 2015)
Description
Concept: Nested spaces (independent of parent/child relationship)
- User Stories
- Testing User Stories
- Use Cases (replaced with User Stories)
- Technical Implementation
- Questions
- Database Model
- Upgrade Guide
User Stories
The devs listed against the user stories below are responsible for the user story and to ensure it's delivered on time, with quality (and automated tests as much as possible) and in general to ensure that they work as expected. They must also ensure that all JIRAs for the stories have been created, assigned and they have defined "Fix Versions".
Legend:
- Partially implemented
- Fully implemented
- Not implemented yet
Create
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
CR1 | As a wiki user, I can create a document at path /A for my team so that I can store information about my team and our projects | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) | |
CR2 | As a wiki user, I can create a child document of document A at path /A/B so that I can store information about a sub-aspect of my team and our projects | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) | |
CR3 | As a wiki user, I can create a child document of document B at path /A/B/C so that I can store information about a sub-aspect of document B | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) | |
CR4 | As a wiki user, I can create a child document of document C at path /A/B/C/D so that I can store information about a sub-aspect of document C | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) | |
CR5 | As a wiki user, I can create a child document of any current document by adding a new part to the existing document path, so that I can create sub documents without restriction | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) | |
CR6 | As a wiki user, I can create a document at any arbitrary path without having to create the parent documents, so that I can organize my documents how I want | Eduard | 7.2M1 using URL and without the final Add Page UI and M3 with final UI | Action: XWIKI-12263 UI: XWIKI-12231 | (link) | (test) |
Update
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
UP1 | As a wiki user, I can rename my document and have its path change to match the updated name so that I can reveal a project that was previously under code name in the wiki | Marius | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12253, XWIKI-12388 | (link) (XWIKI-12482, XWIKI-12349) |
View
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
VI1 | As a wiki user, I can see a 'document does not exist' message if I visit a path that does not yet have a document so that I can clearly tell if there is a document at this path | Guillaume | 7.2M1 | N/A | (link) | ||
VI2 | As a wiki user, I can see an obvious 'create document' button when I visit a path that does not yet have a document, so that I can quickly create a document at any path | Guillaume | 7.2M1 | N/A | (link) | ||
VI3 | As a wiki user, I can see a breadcrumb of parent documents for the current document so that I understand my place within the document hierarchy | Guillaume | 7.2M2 | XWIKI-12220 | (link) | ||
VI4 | As a wiki user, I can see in the web browser the URL pointing at the current document and I understand my place within the document hierarchy | Vincent | 7.2M1 | XWIKI-12170, XWIKI-12169 | (link) | ||
VI5 | As a wiki user, I can click on any document name in the bread crumb so that I can view the content of that document quickly | Guillaume | 7.2M2 | XWIKI-12220 | (link) | ||
VI6 | As a wiki user, I can send someone the link to my document and when they visit the link they can see the document so that I can easily share my document with others | Vincent | 7.2M1 | XWIKI-12170, XWIKI-12169 | (link) |
Delete
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
DE1 | As a wiki user, I can delete a document without automatically deleting any sub documents so that I can remove a bad document without affecting good information in the child documents | Guillaume | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12268 | (link1, link2) |
Move
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
MO1 | As a wiki user, I can move my document from its current path to be a child document of any other document, so that I can transfer my project to another team's path | Marius | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12253, XWIKI-12388 | (link1, link2) | ||
MO2 | As a wiki user, I can move my document from its current path such that it no longer has a parent document and has a top-level path, so that I can move sub aspects out from my team's document path. | Marius | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12253, XWIKI-12388 | (link1, link2) | ||
MO3 | As a wiki user, I can move a document and all its child documents will move so that I don't have to manually do this for each child document | Marius | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12253, XWIKI-12388 | (link) | ||
MO4 | As a wiki user, I have an option to select to not move all child documents when I move a parent document so that existing children remain protected under their existing hierarchy. | Marius | 7.2M1 for API, 7.2M2 for plugging in the APIs and 7.2M3 for the UI | XWIKI-12253, XWIKI-12388 | (link) | ||
MO5 | As a wiki user, I can manually create an automatic redirect link to the new document path when I move a document so that existing bookmarks to the original document path continue to work, by manually creating a document with the old name and inserting some macro or velocity code to perform the redirect. | Marius | 7.2M1 | N/A | (link) |
Permissions
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
PE1 | As a wiki user, I can set an access permission on my document so that only a specific set of groups can see my document | Guillaume | 7.2M1 | (link) | |||
PE2 | As a wiki user, I can set a write permission on my document so that only a specific set of groups can edit my document | Guillaume | 7.2M1 | (link) | |||
PE3 | As a wiki admin, I can control the permissions of all children documents of the current document. The current document's creator and users with edit rights on it will also be able to modify its permissions (but not that of children). | Guillaume | 7.2RC1 | XWIKI-12219 | (link) | ||
PE4 | As a wiki user, I expect the permissions of a document will automatically apply to any child document (unless overridden on the child) so that I don't have to manage the permissions of my document hierarchy manually by hand | Guillaume | 7.2M1 | XWIKI-12284 | (link) | ||
PE5 | As a wiki user, I can set the permissions defined on a document to override any inherited permissions from parent documents so that I have explicit control over who can access or modify the document | Guillaume | 7.2M1 | (link) | |||
PE6 | As a wiki user, I can preserve all permissions defined in the document when I move it. | Guillaume | 7.2M1 without UI (depends on MO1-5), M3 with Move UI | XWIKI-12253 | (link) | ||
PE7 | As a wiki user, I expect to inherit all permissions from the new parent document (if any) when I move a document so that I can automatically take advantage of the new parent document's permission | Guillaume | 7.2M1 | (link) | |||
PE8 | As a wiki user, the XWiki Enterprise Solution will not allow me to move a document under a new parent document which will result in inheriting permissions that will not allow me to view the document after the move. | Marius | 7.2M3 | (link) |
Import/Export
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
IE1 | As a wiki user, I can keep the complete document path when exporting a document and when importing it back, import it in the exact same location | Thomas | 7.2M1 without UI, M2 with UI | XWIKI-12225 | (link) | unit | |
IE2 | As a wiki user, I can export the document's defined permissions so that I can preserve the same permissions when I import the document into a new system | Thomas | 7.2M1 without UI, M2 with UI | (link) | |||
IE3 | As a wiki user, I can export the document's history so that I can preserve the same history when I import the document into a new system | Thomas | 7.2M1 without UI, M2 with UI | (link) |
Backward Compatibility
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
BA1 | As a wiki user, I can use all the standard extensions included in XWiki Enterprise Solution without any conflicts with Nested Documents so that I can enjoy of the extensions in functionality that they provide. The exact list can be found by installing XWiki 7.1.1 going to the Wiki Administration page, and selecting “Installed Extensions” or navigating directly to: http://<server>/xwiki/bin/admin/XWiki/XWikiPreferences?editor=globaladmin§ion=XWiki.InstalledExtensions | Gabriela/Caty | 7.2RC1 |
Performance
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
PF1 | As a wiki owner, I want all features of XWiki to operate as well or better in term of response times (within 5%) when compared to the latest LTS (6.x branch), using exactly the same content of wiki pages | Thomas | 7.2RC1 |
Hooks
Hooks mean you don't have to rebuild XWiki from sources to be able to implement the listed features below. In addition you can upgrade without breaking compatibility (If you upgrade and you wish to benefit from changes made to VM files in your overridden VMs you’ll need to perform some manual merges).
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
HO1 | As a wiki user, I can select an option to remove all child documents when I delete a document so that I can remove an entire section of the wiki without having to do the tedious work of deleting the documents individually. | Vincent | 7.2M1 | N/A | It has been implemented in DE1 too! | ||
HO2 | As a wiki user, the XWiki Enterprise Solution will keep my documents private by providing other users with a 'document does not exist' message when they try to view a document that they don't have permission to access. This will prevent other users from gaining meaningful information by guessing URLs to private documents | Vincent | 7.2M1 | N/A | |||
HO3 | As a wiki user, I can leave a link to the new document path when I move a document so that existing bookmarks to the original document path continue to work | Marius | 7.2M1 | N/A | |||
HO4 | As a wiki user, I can set an ownership permission on my document so that only a specific set of groups can change the document's permission | Vincent | 7.2M1 | N/A | |||
HO5 | As a wiki user, I can see the ownership permission of documents that I also have access to so that I can contact the owner for questions or concerns | Vincent | 7.2M1 | N/A | |||
HO6 | As a wiki user, I will receive a warning when changing the permissions of a parent documents if any of its children have overridden their permissions so that I can know if my changes will conflict with the permissions of the child documents | Vincent | 7.2M1 | N/A | |||
HO7 | As a wiki owner, I have the option to set CKEditor as the default WYSIWIYG editor in replacement of the Google Web Toolkit (GWT) based WYSIWYG one | Marius | 7.2RC1 | N/A | (link) | (link) |
Macros
This means macros will allow implementation of the following stories in any XWiki document
ID | User Story Description | Responsible Dev | ETA | JIRAs | Status | Tested/Validated | Automated Test exist |
---|---|---|---|---|---|---|---|
MA1 | As a wiki user, I can see the tree structure of child documents for the top level documents of my current document's path so that I can understand the structure of the current document's document hierarchy | Marius | 7.2M2 | XWIKI-12174 | (link) | ||
MA2 | As a wiki user, I can click on any document in the tree structure so that I can view the content of that document quickly | Marius | 7.2M2 | XWIKI-12174 | (link) |
Testing User Stories
Provides additional explanations on how to test some user stories:
To edit the .vm files you can use the Skin Application Extension.
If you would like to know more about the Velocity APIs mentioned here, check the Scripting Documentation Application Extension on your own XWiki installation or look at the one that is running at platform.xwiki.org .
- HO1: Replace/Override delete.vm and add the necessary logic to perform child deletion by looping and calling XWiki.getDocument(...).deleteDocument(...). To test:#template("startpage.vm")
<div class="main">
<div id="mainContentArea">
<div id="xwikimessage">Whatever I want here!</div>
<div class="clearfloats"></div>
</div>## mainContentArea
</div>## main
#template("endpage.vm") - HO2: Replace/Override accessdenied.vm and use the message you wish to display.
- HO3: Modify rename.vm and add the necessary steps just after the call to $doc.rename($newDocReference, $backlinks, $children): recreate the document, set its content with a redirect and save it.
- HO4: Modify rightsUI.vm to add a check to verify if the current user is part of a given group. The $xwiki.getUser().isUserInGroup(groupname) API can be used. The groupname is the reference of the page defining the group, e.g “XWiki.XWikiAdminGroup”.
- HO5: Modify informationinline.vm to display the ownership permission of the current document. It depends what an “owner" of a document means. If it's its creator then it’s simple (you get the creator with $doc.getCreatorReference()). If you want to find all users that have access to the document then you need to get the full list of users in the wiki and then check for each one if he/she has access to that document. For the full list you can use the Query Manager (http://extensions.xwiki.org/xwiki/bin/view/Extension/Query+Module) to get all XWiki.XWikiUsers pages and then call $xcontext.hasAccessLevel() to see if the user has some access to the page (example1: http://www.xwiki.org/xwiki/bin/view/FAQ/How+to+check+if+a+user+has+programming+rights).
- HO6: Modify rightsUI.vm to perform additional checks by getting the list of children for a given parent (using the Query Manager) and for each child, check if the current user still has the permission being changed using hasAccessLevel() as above
- HO7: See documentation on how to perform this at http://extensions.xwiki.org/xwiki/bin/view/Extension/CKEditor+Integration#HReplacetheDefaultEditor
- PE4: Steps:
- Create the page A.B.C.WebHome
- Create A.WebHome
- Set the view right to XWikiAdminGroup on the space A by clicking on "Administer Space"
- Create a new user
- With this new user, you should not be able to view A.WebHome nor A.B.C.WebHome
- MO1-4/UP1/DE1: see here
- MA1/MA2: see here.
Use Cases (replaced with User Stories)
Assumption:
- Option 1 (without nested documents):http://localhost:8080/xwiki/bin/view/A/B/Cwhere A and B are spaces and C is a page.
- Option 2: (with nested documents):http://localhost:8080/xwiki/bin/view/A/B/C/WebHomewhere A, B and C are spaces.
Minimal list of Use Cases for M1/M2 for XWiki 7.2:
- UC1: Adding a page D under an existing page A/B/C, using the Add button
- Option 1: Not possible. The user first needs to rename page C into C.WebHome and then create page D under space C by using a Space Displayer in the Add Page UI. Requires T1, 3, 4, 5, 6, 11 -> M2
- Option 2: The Add Page UI asks the user to enter the name of the new page (D) and to choose under which document to put it (using a Document Hierarchy Displayer). Page D.WebHome is created under C. Requires T1, 3, 4, 5, 6, 11, 18 -> M2
- UC2: Ability to create a wiki link in wiki mode and once saved, navigate to it by clicking on it. For example: [[label>>A.B.C]]. Requires T1, 6, 11 -> M1
- UC3: Delete a page that has children pages. Requires T1, 6, 11 for option 1 (-> M1) + 18 for option 2 (-> M2)
- UC4: Ability to navigate to C.WebHome by using all the following URLs:
- http://localhost:8080/xwiki/bin/view/A/B/C/WebHome
- http://localhost:8080/xwiki/bin/view/A/B/C/
- http://localhost:8080/xwiki/bin/view/A/B/C
- Requires T1, 6, 11 -> M1
- UC5: Adding a page D under an existing page A/B/C using URL by typinghttp://localhost:8080/xwiki/bin/view/A/B/C/D
- Option 1: Not possible. The UI will say that page D doesn't exist and creating it will create a page with spaces A.B.C. However page D will not be under the existing page C. The user first needs to rename page C into C.WebHome and then it'll work. Requires T1, 6, 11 -> M1
- Option 2: The UI will say that page D doesn't exist and propose to create it. Clicking on it should create D.WebHome under space C. Requires T1, 6, 11, 18 -> M2
- UC6: Users should be able to navigate quickly to any parent space of the current page, using a breadcrumb
- Note: this means either changing the top level menu to support nested spaces and hiding the current breadcrumb (based on parent/child relationships) or simplifying the top level menu (see http://markmail.org/message/rab6vbxd6743gmrc ) and offering a different implementation of the breadcrumb based on document references.
- Requires T1, 6, 11, 8, 9, 19 -> M2
- UC7: Ability to create a new page under a non-existing page, using the Add button. Requires T1, 3, 4, 5, 6, 11 (+ 18) -> M2
- UC8: Ability to create a new page under a non-existing page, by directly typing the URL. Requires T1, 6, 11 -> M1
- UC9: Rename a page. Rename space of A.B.C.WebHome to be A instead of A.B.C. Requires T1, 3, 4, 5, 6, 11 (+18) -> M2
- UC10: Rename a page into a non-existing space. Rename space of A.B.C.WebHome to be A.D instead of A.B.C, where D doesn't exist. Requires T1, 3, 4, 5, 6, 11 (+18) -> M2
Other UC to implement:
See the tasks below.
Technical Implementation
List of all JIRA issues related to the Nested Spaces implementation:
Original list of tasks
Technically this means:
Id | Task Description | Version | Developer | JIRA |
---|---|---|---|---|
T1 | At the database level, we would need to make a change: store the full space reference (no wiki) in the existing space column + possibly add a new table for storing Spaces. Consequently modify all code calling XWikiDocument.get/setSpace() so that they call XWikiDocument.getDocumentReference(). Similarly modify all queries returning or filtering on the space column (web or space in HQL/XWQL). We also need an API to get the list of child spaces of a given parent space. | 7.2M1 | Thomas | XWIKI-12153 |
T2 | Write a migration to escape all existing "." in the space column. | 7.2M3 | Thomas | |
T3 | Create a Space Displayer (view + edit modes) to display/select a space | 7.2M1 | Edy? Marius Guillaume? | XWIKI-12176 |
T4 | Modify the Document Tree macro to support nested spaces. Add support for clicking on spaces to go to the space's WebHome page and thus not display WebHome in the list of docs for a space. | 7.2M1 | Marius | XWIKI-12173, XWIKI-12174 |
T5 | Modify the Page and Space creation UI to select in which space to create the new document or space (use the Space Displayer). Same for Copy and Rename UI actions. Note: Make sure to update the functional tests. Remove the Add/Delete/Rename Space features if T18 is accepted + Modify the Create Panel to only create pages and not spaces. | 7.2M2 | Edy Marius? Guillaume? | XWIKI-12231 |
T6 | Modify the Standard URL Scheme + all XWikiURLFactory implementations + URL module to support Nested Spaces (while still supporting current URL formats). Review and modify all URL handlers for URLs other than Entity URLs (REST, GWT, XMLRPC, WebDAV, etc) | 7.2M1 | Vincent Edy? Other? | XWIKI-12170, XWIKI-12169 |
T7 | Review and fix all places where spaces are stored. For example modify the Activity Stream's space column (activitystream.hbm.xml similarly to above for xwiki.hbm.xml) to use the full space reference + the Activity Stream code that uses it. | 7.2M2 | Thomas | |
T8 | Design new top level navigation and action menus to support multiple spaces | 7.2M1 | Caty | See Nested: Navigation and Actions |
T9 | Modify top level navigation and action menu to support multiple spaces | 7.2M2 | Guillaume | XWIKI-12189 |
T10 | Modify Admin UI to be able to navigate to nested spaces. | 7.2M3 | Edy Guillaume? Marius? | XWIKI-12172 |
T11 | Modify EntityReferenceValueProvider to return an EntityReference instead of a String to handle nested spaces. Since we won't be able to modify it without breaking backward compatibility we'll need to deprecate it and introduce a new interface | 7.2M1 | Thomas | XWIKI-12153 |
T12 | Modify the Page Displayer (view+edit modes) to support nested spaces | 7.2M3 | Marius | XWIKI-12176 |
T13 | Design a new way to display Page + Spaces + Wiki in a livetable (idea: use a single column) + ability to filter on wiki, spaces, page | 7.2M1 | Caty | See Nested: Livetable |
T14 | Based on the design (done in M1), modify the Livetables which display document names and spaces to better handle nested spaces (without any changes, the technical space reference will be printed). Example: Index's AllDocs pages | 7.2M3 | Guillaume? Marius Edy? | |
T15 | Rewrite the Space List Macro to display the spaces in a tree instead of a table + modify XWiki.getSpaces() API (deprecate + add a new one possibly) | 7.2M1 | Marius Edy? Other? | |
T16 | Modify the Space Facet of SOLR's Search UI to support Nested Spaces | 7.2M3 | Marius | XWIKI-12175 |
T17 | Modify UIs to never display "WebHome" (except for some very technical places). This is especially important if we decide to support "Nested Documents" by automatically creating spaces whenever the user creates a new page, thus always creating WebHome pages. However it's also important even if we don't do this. | 7.2M3 | Edy? Guillaume Marius? | XWIKI-12190 |
T18 | Create a space whenever a page is created (always create WebHome pages). This allows to have "nested documents"! Note that this probably also require disabling rights at the page level since it would no longer be necessary. First step is to send a proposal to the list to discuss it and decide if we want this. This could mean to remove the concept of Space everywhere in UIs. | 7.2M2 (Decision to be done in 7.1M1) | Edy? Guillaume Marius? | XWIKI-12193 |
T19 | Turn off the current breadcrumb by default + the ability to set the parent in edit mode, i.e. stop using parent/child relationship. See http://markmail.org/message/rab6vbxd6743gmrc | 7.2M3 | Marius Edy? Guillaume? | |
T20 | Review the main Extensions to locate Extensions that will need to be modified because they display Spaces in their UI (or use APIs that will be removed/deprecated such as getSpaces() (see above). What happens is that the space column in the database will now hold the nested space reference instead of just a single space name. Thus if the extension displays the space somewhere in its UI, it'll display for example "space1.space2" instead of just "space" before. While this is valid it may not be the best from a user POV. In practice when you move from single space to nested spaces you need to review the way you were doing things. For example imagine that you had a list of spaces displayed one under another. If you don't make any change you'll get a list with elements such as "space1", "space2.space3", "space4", "space5.space6.space7", etc. In practice with nested spaces what you'd like to have is a tree. Thus in order for those extensions displaying spaces, they'll need to have some improvements to support perfectly nested spaces from a user POV. | 7.2M1 | Gabriela Caty | See Contrib Extensions Review and XWiki Enterprise Extensions Review |
T21 | Modify the XAR format (and Import/Export) to support Nested Spaces | 7.2M2 | ? | |
T22 | Modify the Admin Import/Export UI to support Nested Spaces | 7.2M3 | ? | |
T23 | Add support for page renames without breaking existing bookmarks so that we can reorganize the default Flavor wiki pages we provide and use Nested spaces | 7.x? 8.x? | ? | |
T24 | Reorganize the default Flavor wiki pages and Core Extensions we provide to use Nested spaces | 7.x? 8.x? | ? | |
T25 | Add support for easy linking to WebHome page (Depends on T18) | 7.2M3 | ? | |
T26 | Prepare an Upgrade Guide. For ex if you do HQL like "where doc.space = 'somespace'" and add a parent or child space for somespace then the query will not return anything since you can have something like "parent.somespace.child" in the DB in the space column. | ? | ? |
URL + WikiLinks Implementation (T6 + T25)
There are 2 parts for URLs:
- Supporting implicit WebHome: URLs of type A/B/C where C is a space and WebHome is implicit (not specified in the URL). This is needed if T18 is accepted.
- Supporting nested elements.
Supporting Implicit WebHome
The problem for part 2 is that there's no way of knowing if "C" is a space or not just by looking at the URL. Thus, till Nested Documents is implemented in the DB the only solution is to check if a document named "C.WebHome" exists in the DB and if not, consider that the user is asking for page C in space A.B.
Note that it's more performant than doing: check if a document named "C" exists in the DB and if not consider that the user is asking for page "C.WebHome". The reason is because if T18 is accepted most documents will be named WebHome and thus checking for its existence is better since these will be in the "exist" cache.
However:
- This is a costly operation compared to not calling the DB at all
- The code needs to be refactored to ensure that the DB is ready before URL parsing is done (which is not the case right now!)
To alleviate the problem we could decide to have a configuration flag for this (till Nested Docs is implemented in the DB), and this flag would be off by default.
An alternative would be to find a way to separate links to spaces from links to documents in the URL (it would be up to the link generation code to generate the proper URL by checking for document existence). We could imagine for example to have a parameter: by default links without this parameter would be links to spaces (since with T18 it would become the norm) and when this param is specified it would be links to documents.
For example:
- Link to doc: /A/B/C?doc=true or /A/B/C?url=doc
- Link to WebHome: A/B/C
Similarly when parsing wiki links, we could add a link parameter whenever we need to link to a page not named WebHome (to avoid DB calls):
- [[label>>A.B.C]]: link to A.B.C.WebHome
- [[label>>A.B.C||action="viewpage"]]: link to A.B.C
Supporting Nested Elements
Right now the code implements:
// - 0 segments (e.g. ""): default document reference, "view" action
// - 1 segment (e.g. "/", "/Document"): default space, specified document (and default if empty), "view" action
// - 2 segments (e.g. "/Space/", "/Space/Document"): specified space, document (and default doc if empty),
// "view" action
// - 3 segments (e.g. "/action/Space/Document"): specified space, document (and default doc if empty),
// specified action
// - 4 segments (e.g. "/download/Space/Document/attachment"): specified space, document and attachment (and
// default doc if empty), "download" action
// - 4 segments or more (e.g. "/action/Space/Document/whatever/else"): specified space, document (and default
// doc if empty), specified "action" (if action != "download"), trailing segments ignored
The new rules would become:
- 0 segment (e.g. ""): default document reference, "view" action
- 1 segment (e.g. "/", "/Document"): default space (Main), specified document (and default if empty), "view" action
- 2 segments (e.g. "/Space/", "/Space/Document"): specified space, document (and default doc if empty "WebHome"), "view" action
- 3 segments:
- if xwiki.showviewaction=0 (e.g. "/Space1/Space2/Document"): "view" action. doc = Space1.Space2.Document
- if xwiki.showviewaction=1 (e.g. "/action/Space1/Document"): specified action, doc = Space1.Document
- 4 segments or more:
- if xwiki.showviewaction=0 (e.g. "/Space1/Space2/Space3/Document"): "view" action. doc = Space1.Space2.Space3.Document
- if xwiki.showviewaction=1 (e.g. "/action/Space1/Space2/Document", "/download/Space1/Document/attachment"):
- if action == "download": doc = Space1.Document
- if action != "download": doc = Space1.Space2.Document
Questions
- Regarding "Nested Documents":
- Edy: This also implies a change on the rights system because any right change on a parent is inherited by all its children, so you can no longer add a right exception on a parent without it being inherited by all its children (i.e. this exception automatically becomes a rule for the children). One solution would be to extend the XWikiRights class and add a flag to state if the right should cascade or not.
- Vincent: Thomas says this already exist and we already have XWikiRights and XWikiGlobalRights
- Edy: Could the concept of Space be rather be replaced by the concept of Parent, where all (logical) pages have a direct and relative parent and not an absolute space path? (open question)
- Vincent: Indeed the "space" column in the DB will become a "parent" column in the DB (with a different name since we already have a "parent" column used for parent/child relationship that will be turned off by default). Making it relative is possible but it would require adding another column with the full path since we need to be able to get the full reference of a document in a single DB query.
- Edy: This also implies a change on the rights system because any right change on a parent is inherited by all its children, so you can no longer add a right exception on a parent without it being inherited by all its children (i.e. this exception automatically becomes a rule for the children). One solution would be to extend the XWikiRights class and add a flag to state if the right should cascade or not.
Database Model
Links to study:
- http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back/48
- http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back/68
- http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back/77
- http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back/76
- http://www.slideshare.net/billkarwin/models-for-hierarchical-data
Nested Spaces
doc table:
- doc name
- space local reference (existing column which currently is the space name but which will be modified to contain the space reference)
- space id (from space table) - New column
space table (new table):
- name
- parent (local reference)
Example:
3 documents:
- space1.space2.space3.page1
- space1.space2.page2
- space2\..page3
-------------------------------------------------------
1 | page1 | space1.space2.space3 | 3
2 | page2 | space1.space2 | 2
3 | page3 | space2\. | 4
space id | name | parent
---------------------------------
1 | space1 |
2 | space2 | space1
3 | space3 | space1.space2
4 | space2. |
- UC1: Single query to find all documents located in space "space2"
- from doc, space where doc.spaceId = space.id and (space.name = "space2" or space.parent like "space2.%" or space.parent like "%.space2.%" or space.parent like "%.space2" or space.parent = "space2")
- Note: escape "." in input before creating the query
- Result: page1, page2
- UC2: Get all spaces under a given space (say "space1"), in a performant way (paged)
- select name from space where parent like "space1.%" or parent like "%.space1.%" or parent like "%.space1" or parent = "space1"
- Result: space2, space3
- UC3: Add a new document in an existing space: "page4" in space "space2"
- In the space table find the space id for "space2" using the "name" column, i.e. "2"
- Add the new doc entry in the doc table, using "2" as the spaceid and set the existing "space" column to be the "space1.space2" full reference
- UC4: Move a existing document into a different existing space: "page1" in space "space1"
- In a single DB transaction, do:
- Check if there are any document left in space "space3" or below (the space of "page1" before the change) and if empty delete the space table entry for "space3"
- Get the spaceid for space "space1"
- Update the doc table entry for "page1"
- In a single DB transaction, do:
- UC5: Add a new document into a new space: "page4" in space "space4"
- TODO
Problems
- <list any potential problems here>
Nested Documents
See NestedDocuments.
Upgrade Guide
This lists situations where the modifications brought by the Nested Spaces/Nested Documents implementation could cause problems when upgrading an existing XWiki and starting to use NS/ND:
- The document space field in the database (and the corresponding XWikiDocument#getSpace() method) now contains the serialized space reference instead of the space name. In practice what it means is that ".", ":" and "\" characters are going to be escaped with a "\" (a migration will automatically update those entries in the database when upgrading). For example a space named Space:with.special\char will be stored asSpace\:with\.special\\char. If you are manipulating only the document DocumentReference then it won't make any difference but in some cases it might do some differences depending how to request or use the document space.
- Various other API follow this space name to space reference change:
- XWiki#getSpaceDocsName methods: the passes String is interpreted as the space reference (since it's compared to the field in the database)
- If you have an Extension which uses a query on the Space, for example where doc.space = 'somespace' and the somespace Space is moved (to otherspace.somespace for example) then the Extension will not work properly anymore (this is because we store the full Space reference in there for NS). Thus you should move Extension Spaces only if the Extension supports this (for example by not hardcoding the Space). Said differently you should not consider that a moved Space has the same name than before.
- Extensions/code implementing XWikiURLFactory (or extending classes implementing XWikiURLFactory such as XWikiServletURLFactory) will need to be modified to handle nested spaces passed in the space parameter of the various APIs. Here's how to parse spaces passed as a String:private EntityReferenceResolver<String> relativeEntityReferenceResolver =
Utils.getComponent(EntityReferenceResolver.TYPE_STRING, "relative");
...
or
...
@Inject
@Named("relative")
private EntityReferenceResolver<String> relativeEntityReferenceResolver;
...
private List<String> extractSpaceNames(String spaces)
{
List<String> spaceNames = new ArrayList<>();
// Parse the spaces list into Space References
EntityReference spaceReference = this.relativeEntityReferenceResolver.resolve(spaces, EntityType.SPACE);
for (EntityReference reference : spaceReference.getReversedReferenceChain()) {
spaceNames.add(reference.getName());
}
return spaceNames;
} - Extensions/code implementing ExportURLFactoryActionHandler will also need to be modified to handle nested spaces passed in the space parameter.
- Extensions/code implementing EntityReferenceSerializer or DocumentReferenceResolver must now handle nested spaces (in the past they were already supposed to handle Nested Spaces but since it was not used they could take shortcuts and it wasn't visible. It's now going to fail, see XWIKI-12191).
- If your code or Extension uses the Parent/Child relationship (and uses Document#get/setParent()) then you should know that this feature is being deprecated (and is disabled by default) since it's replaced by the Nested Spaces feature (and hierarchy is now set in the Document References). Thus you'll need to adapt your code to use the Document Reference instead (and API like DocumentReference.getLastSpaceReference()).
Not fully decided yet:
- The space parameter of the XWiki.getSpacePreference(String preference, String space, String defaultValue, XWikiContext context) method is now accepting a nested space reference (e.g. A.B.C). Similar to point 1 above.