Working Copy
Contents
Working Copy#
Note
This is only available on Plone 5.
Plone has the "Working copy" feature provided by the core package plone.app.iterate
.
It allows the users to create a working copy of a (published or live) content object and
work with it until it's ready to be published without having to edit the original object.
This process has several steps of it's life cycle:
Create working Copy (aka Check-out)#
The user initiates the process and creates a "working copy" by "checking out" the content:
http
POST /plone/document/@workingcopy HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X POST http://nohost/plone/document/@workingcopy -H "Accept: application/json" --user admin:secret
httpie
http POST http://nohost/plone/document/@workingcopy Accept:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/document/@workingcopy', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
and receives the response:
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/document
{
"@id": "http://localhost:55001/plone/copy_of_document"
}
Get the working copy#
A working copy has been created and can be accessed querying the content:
http
GET /plone/document/@workingcopy HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/document/@workingcopy -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/document/@workingcopy Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/document/@workingcopy', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
and receives the response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"working_copy": {
"@id": "http://localhost:55001/plone/copy_of_document",
"created": "1995-07-31T13:45:00",
"creator_name": "admin",
"creator_url": "http://localhost:55001/plone/author/admin",
"title": "Test document"
},
"working_copy_of": null
}
the GET content of any object, also states the location of the working copy, if any (working_copy
).
http
GET /plone/document HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/document -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/document Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/document', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"@components": {
"actions": {
"@id": "http://localhost:55001/plone/document/@actions"
},
"breadcrumbs": {
"@id": "http://localhost:55001/plone/document/@breadcrumbs"
},
"contextnavigation": {
"@id": "http://localhost:55001/plone/document/@contextnavigation"
},
"navigation": {
"@id": "http://localhost:55001/plone/document/@navigation"
},
"types": {
"@id": "http://localhost:55001/plone/document/@types"
},
"workflow": {
"@id": "http://localhost:55001/plone/document/@workflow"
}
},
"@id": "http://localhost:55001/plone/document",
"@type": "Document",
"UID": "SomeUUID000000000000000000000001",
"allow_discussion": false,
"contributors": [],
"created": "1995-07-31T13:45:00",
"creators": [
"test_user_1_"
],
"description": "",
"effective": null,
"exclude_from_nav": false,
"expires": null,
"id": "document",
"is_folderish": false,
"language": "",
"layout": "document_view",
"lock": {
"created": "1995-07-31T17:30:00",
"creator": "admin",
"creator_name": "admin",
"creator_url": "http://localhost:55001/plone/author/admin",
"locked": true,
"name": "iterate.lock",
"stealable": false,
"time": 807211800.0,
"timeout": 4294967280,
"token": "0.12345678901234567-0.98765432109876543-00105A989226:1630609830.249"
},
"modified": "1995-07-31T17:30:00",
"next_item": {
"@id": "http://localhost:55001/plone/copy_of_document",
"@type": "Document",
"description": "",
"title": "Test document"
},
"parent": {
"@id": "http://localhost:55001/plone",
"@type": "Plone Site",
"description": "",
"title": "Plone site"
},
"previous_item": {},
"relatedItems": [],
"review_state": "private",
"rights": "",
"subjects": [],
"table_of_contents": null,
"text": null,
"title": "Test document",
"version": "current",
"working_copy": {
"@id": "http://localhost:55001/plone/copy_of_document",
"created": "1995-07-31T13:45:00",
"creator_name": "admin",
"creator_url": "http://localhost:55001/plone/author/admin",
"title": "Test document"
},
"working_copy_of": null
}
the GET content of any a working copy also returns the original (working_copy_of
):
http
GET /plone/copy_of_document HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/copy_of_document -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/copy_of_document Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/copy_of_document', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"@components": {
"actions": {
"@id": "http://localhost:55001/plone/copy_of_document/@actions"
},
"breadcrumbs": {
"@id": "http://localhost:55001/plone/copy_of_document/@breadcrumbs"
},
"contextnavigation": {
"@id": "http://localhost:55001/plone/copy_of_document/@contextnavigation"
},
"navigation": {
"@id": "http://localhost:55001/plone/copy_of_document/@navigation"
},
"types": {
"@id": "http://localhost:55001/plone/copy_of_document/@types"
},
"workflow": {
"@id": "http://localhost:55001/plone/copy_of_document/@workflow"
}
},
"@id": "http://localhost:55001/plone/copy_of_document",
"@type": "Document",
"UID": "SomeUUID000000000000000000000002",
"allow_discussion": false,
"contributors": [],
"created": "1995-07-31T13:45:00",
"creators": [
"test_user_1_"
],
"description": "",
"effective": null,
"exclude_from_nav": false,
"expires": null,
"id": "copy_of_document",
"is_folderish": false,
"language": "",
"layout": "document_view",
"lock": {
"locked": false,
"stealable": true
},
"modified": "1995-07-31T17:30:00",
"next_item": {},
"parent": {
"@id": "http://localhost:55001/plone",
"@type": "Plone Site",
"description": "",
"title": "Plone site"
},
"previous_item": {
"@id": "http://localhost:55001/plone/document",
"@type": "Document",
"description": "",
"title": "Test document"
},
"relatedItems": [],
"review_state": "private",
"rights": "",
"subjects": [],
"table_of_contents": null,
"text": null,
"title": "Test document",
"version": "current",
"working_copy": {
"@id": "http://localhost:55001/plone/copy_of_document",
"created": "1995-07-31T13:45:00",
"creator_name": "admin",
"creator_url": "http://localhost:55001/plone/author/admin",
"title": "Test document"
},
"working_copy_of": {
"@id": "http://localhost:55001/plone/document",
"title": "Test document"
}
}
Check-in#
Once the user has finished editing the working copy and wants to update the original with the changes in there, or "check-in" the working copy.
http
PATCH /plone/copy_of_document/@workingcopy HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X PATCH http://nohost/plone/copy_of_document/@workingcopy -H "Accept: application/json" --user admin:secret
httpie
http PATCH http://nohost/plone/copy_of_document/@workingcopy Accept:application/json -a admin:secret
python-requests
requests.patch('http://nohost/plone/copy_of_document/@workingcopy', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
and receives the response:
HTTP/1.1 204 No Content
The working copy is deleted afterwards as a result of this process. The PATCH can also be issued in the original (baseline) object.
Delete the working copy (cancel check-out)#
If you want to cancel the checkout and delete the working copy (in both the original and the working copy):
http
DELETE /plone/copy_of_document/@workingcopy HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X DELETE http://nohost/plone/copy_of_document/@workingcopy -H "Accept: application/json" --user admin:secret
httpie
http DELETE http://nohost/plone/copy_of_document/@workingcopy Accept:application/json -a admin:secret
python-requests
requests.delete('http://nohost/plone/copy_of_document/@workingcopy', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
and receives the response:
HTTP/1.1 204 No Content
When a working copy is deleted using the "normal" delete action, it also deletes the
relation and cancels the check-out, but that is handled by plone.app.iterate
internals.