As a developer, I want to be able to create a new Wikidata item in its entirety
`POST rest.php/wikibase/v0/entities/items`
```
{
"item": {
"labels": {}, [label or description in one language code is mandatory]
"descriptions": {},
"aliases": {},
"sitelinks": {}
"statements": {}
},
"comment": ... (optional)
"tags": [ ... ] (optional)
"bot": false (optional)
}
```
**Acceptance criteria**
- At least adding a label or a description in one language is mandatory
- 201 response code on success and location header in the successful creation response
- Ignore HTTP conditional request headers
- Statement errors can be handled similar to those in `POST /entities/items/{item_id}/statements`. Only additional change is adding the the index of the problem statement to the path context of the error message in the form `/property_id/index_of_erronic_statement`
- Ignore id and type fields and don't consider them unexpected
- ETag, last-modified and location (URI of the newly created item) as response headers.
- Handle user authentication/authorization like in `POST /entities/items/{item_id}/statements`
- Client can provide additional edit metadata: mediawiki tags, edit summary text to append to the automated summary, and a bot edit flag, like in POST /entities/items/{item_id}/statements
**Error cases to consider**
<table>
<tr>
<th>
</th>
<th>HTTP response code</th>
<th>response payload</th>
</tr>
<tr>
<td>Invalid edit tag</td>
<td>400</td>
<td>
`"code": "invalid-edit-tag"`
`"message": "Invalid MediaWiki tag: {tag}"`
</td>
</tr>
<tr>
<td>Comment too long</td>
<td>400</td>
<td>
`"code": "comment-too-long"`
`"message": "Comment must not be longer than {limit} characters"`
</td>
</tr>
<tr>
<td>Invalid data in field</td>
<td>400</td>
<td>
`"code": "item-data-invalid-field"`
`"message": "Invalid input for '{field}'"`
`"context": { "path": "{field}", "value": "{value}" }`
</td>
</tr>
<tr>
<td>Unexpected field in item request</td>
<td>400</td>
<td>
`"code": "unexpected-field"`
`"message": "The request body contains an unexpected field"`
`"context": { "field": "{field}" }`
</td>
</tr>
<tr>
<td>Item after changes missing label or description </td>
<td>400</td>
<td>
`"code": "missing-labels-and-descriptions"`
`"message": "Item requires at least a label or a description in a language"`
</td>
</tr>
<tr>
<td>When label, description or alias fields are selected but not filled (aka, empty)</td>
<td>400</td>
<td>
`"code": "label/description/alias/alias list-empty"`
`"message": "Label/Description/Alias list/Alias must not be empty"`
`"context": { "language": "{language_code}" }`
</td>
</tr>
<tr>
<td>Label and description have same value</td>
<td>400</td>
<td>
`"code": "label-description-same-value"`
`"message": "Label and description for language '{language_code}' can not have the same value"`
`"context": { "language": "{language}" }`
</td>
</tr>
<tr>
<td>Label/description/alias too long</td>
<td>400</td>
<td>
`"code": "label/description/alias-too-long"`
`"message": "Label/Description/Alias must be no more than {limit} characters long"`
`"context": { "language": "{language_code}", "character-limit": "{limit}" }`
</td>
</tr>
<tr>
<td>Label/description/alias invalid</td>
<td>400</td>
<td>
`"code": "invalid-label/description/alias"`
`"message": "Not a valid label/description/alias: {label/desc/alias}"`
`"context": { "language": "{language_code}" }`
</td>
</tr>
<tr>
<td>Invalid language code</td>
<td>400</td>
<td>
`"code": "invalid-language-code"`
`"message": "Not a valid language code: {language_code}"`
`"context": { "path": "{field}", "language": "{language_code}" }`
</td>
</tr>
<tr>
<td>Duplicate alias</td>
<td>400</td>
<td>
`"code": "duplicate-alias"`
`"message": "Alias list contains a duplicate alias: '{alias}'"`
`"context": { "language": "{language_code}", "alias": "{alias}" }`
</td>
</tr>
<tr>
<td>Item with label and description already exists</td>
<td>400</td>
<td>
`"code": "item-label-description-duplicate"`
`"message": "Item '{duplicate_item_id}' already has label '{label}' associated with language code '{language}', using the same description text"`
`"context": { "language": "{language}", "label": "{label}", "description": "{description}", "matching-item-id": "{duplicate_item_id}" }`
</td>
</tr>
<tr>
<td>Sitelink conflict</td>
<td>409</td>
<td>
`"code": "sitelink-conflict"`
`"message": "Sitelink is already being used on {other_item_id}"`
`"context": { "site": "{site_id}", "matching-item-id": "{duplicate_item_id}" }`
</td>
</tr>
<tr>
<td>Sitelink title field not provided</td>
<td>400</td>
<td>
`"code": "sitelink-data-missing-title"`
`"message": "Mandatory sitelink title missing"`
`"context": { "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>title is empty</td>
<td>400</td>
<td>
`"code": "title-field-empty"`
`"message": "Title must not be empty"`
`"context": { "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>Invalid title</td>
<td>400</td>
<td>
`"code": "invalid-title-field"`
`"message": "Not a valid input for title field"`
`"context": { "site": "{site_id}" }`
</tr>
<tr>
<td>Value provided as a badge is not an item ID</td>
<td>400</td>
<td>
`"code": "invalid-input-sitelink-badge"`
`"message": "Badge input is not an item ID: {value}"`
`"context": { "badge": "{value}", "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>Item provided is not allowed as a sitelink badge</td>
<td>400</td>
<td>
`"code": "item-not-a-badge"`
`"message": "Item ID provided as badge is not allowed as a badge: {item_id}"`
`"context": { "badge": "{item_id}", "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>value of badges field is not a list</td>
<td>400</td>
<td>
`"code": "invalid-sitelink-badges-format"`
`"message": "Value of badges field is not a list"`
`"context": { "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>Title does not exist on the given site</td>
<td>400</td>
<td>
`"code": "title-does-not-exist"`
`"message": "Page with title {title} does not exist on the given site"`
`"context": { "site": "{site_id}" }`
</td>
</tr>
<tr>
<td>Invalid site ID</td>
<td>400</td>
<td>
`"code": "invalid-site-ID"`
`"message": "Not a valid site ID:'{site_id}'"`
`"context": { "site": "{site_id}" }`
</td>
</tr>
</table>
**Notes**
- Automated edit summary to be of the type: `/* wbeditentity-create-item:0| */`
- How Action API does it: https://www.wikidata.org/w/api.php?action=help&modules=wbeditentity
**Task breakdown**
* add to OAS
* create ItemDeserializer (plugs together all the existing deserializers for labels, descriptions, aliases, statements, sitelinks)
* create `ItemCreator` interface with a `create( Item $item, EditMetadata $editMetadata ): ItemRevision;` and implementation. We can likely reuse the existing `EntityUpdater` class which might then need a better name.
* happy path
* include revision ID and last modified date
* edit summary
* authorization
* add new method to `PermissionChecker::canCreateItem( User $user ): bool` and implement it
* top-level field validation
* covers `item-data-invalid-field`, `unexpected-field`, `missing-labels-and-descriptions`
* field validation
* apply middlewares (the usual ones except the one for conditional requests)
* spec tests
* mark production ready