Page MenuHomePhabricator

๐Ÿฃ Create an item
Open, Needs TriagePublic13 Estimated Story Points

Description

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

HTTP response coderesponse payload
Invalid edit tag400 "code": "invalid-edit-tag"
"message": "Invalid MediaWiki tag: {tag}"
Comment too long400 "code": "comment-too-long"
"message": "Comment must not be longer than {limit} characters"
Invalid data in field400 "code": "item-data-invalid-field"
"message": "Invalid input for '{field}'"
"context": { "path": "{field}", "value": "{value}" }
Unexpected field in item request400 "code": "unexpected-field"
"message": "The request body contains an unexpected field"
"context": { "field": "{field}" }
Item after changes missing label or description 400 "code": "missing-labels-and-descriptions"
"message": "Item requires at least a label or a description in a language"
When label, description or alias fields are selected but not filled (aka, empty)400 "code": "label/description/alias-list/alias-empty"
"message": "Label/Description/Alias list/Alias must not be empty"
"context": { "language": "{language_code}" }
Label and description have same value400 "code": "label-description-same-value"
"message": "Label and description for language '{language_code}' can not have the same value"
"context": { "language": "{language}" }
Label/description/alias too long400 "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}" }
Label/description/alias invalid400 "code": "invalid-label/description/alias"
"message": "Not a valid label/description/alias: {label/desc/alias}"
"context": { "language": "{language_code}" }
Alias type invalid400 "code": "invalid-alias-list"
"message": "Not a valid alias list"
"context": { "language": "{language_code}" }
Invalid language code400 "code": "invalid-language-code"
"message": "Not a valid language code: {language_code}"
"context": { "path": "{field}", "language": "{language_code}" }
Duplicate alias400 "code": "duplicate-alias"
"message": "Alias list contains a duplicate alias: '{alias}'"
"context": { "language": "{language_code}", "alias": "{alias}" }
Item with label and description already exists400 "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}" }
Sitelink conflict409 "code": "sitelink-conflict"
"message": "Sitelink is already being used on {other_item_id}"
"context": { "site-id": "{site_id}", "matching-item-id": "{duplicate_item_id}" }
Sitelink title field not provided400 "code": "sitelink-data-missing-title"
"message": "Mandatory sitelink title missing"
"context": { "site-id": "{site_id}" }
title is empty400 "code": "title-field-empty"
"message": "Title must not be empty"
"context": { "site-id": "{site_id}" }
Invalid title400 "code": "invalid-title-field"
"message": "Not a valid input for title field"
"context": { "site-id": "{site_id}" }
Value provided as a badge is not an item ID400 "code": "invalid-input-sitelink-badge"
"message": "Badge input is not an item ID: {value}"
"context": { "badge": "{value}", "site-id": "{site_id}" }
Item provided is not allowed as a sitelink badge400 "code": "item-not-a-badge"
"message": "Item ID provided as badge is not allowed as a badge: {item_id}"
"context": { "badge": "{item_id}", "site-id": "{site_id}" }
value of badges field is not a list400 "code": "invalid-sitelink-badges-format"
"message": "Value of badges field is not a list"
"context": { "site-id": "{site_id}" }
Title does not exist on the given site400 "code": "title-does-not-exist"
"message": "Page with title {title} does not exist on the given site"
"context": { "site-id": "{site_id}" }
Invalid site ID400 "code": "invalid-site-ID"
"message": "Not a valid site ID:'{site_id}'"
"context": { "site-id": "{site_id}" }
Invalid statement group object400 "code": "invalid-statement-group-type"
"message": "Not a valid statement group"
"context": { "path": "{property_id}" }
Invalid statement object400 "code": "invalid-statement-type"
"message": "Not a valid statement type"
"context": { "path": "{property_id/index}" }
Statement group empty400 "code": "statement-group-empty"
"message": "No statement has been added for property id: '{property_id}'"
"context": { "path": "{property_id}" }

Notes

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

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
Restricted Application added a subscriber: Aklapper. ยท View Herald TranscriptJul 28 2023, 2:05 PM
WMDE-leszek set the point value for this task to 13.Feb 1 2024, 11:33 AM

At least adding a label or a description in one language is mandatory

What if people want to make an item just with statement (programmatically)
And later have users or a community fill out sensible labels and or descriptions in various languages?
I'm sure I have seen this usecase occour multiple times with Wikibase in the past.

This feels like a requirement that should probably be per usecase of the software, for example I imagine it makes perfect sense on Wikidata to require one or more of these to be set, as is currently the requirement when creating Items through the UI.

Hi @Addshore, thanks for bringing that up. Currently the REST API is only being used on Wikidata and I can't yet say exactly when the two Wikibase products might want to start using it but it's not in the near future.

When this is the case and the user needs/feedback come in, we can make the needed change. I hope that helps

Muhammad_Yasser_Jazirahly_WMDE renamed this task from Create an item to ๐Ÿฃ Create an item.Mar 6 2024, 10:35 AM

Updates from daily today:

  • For statement invalid field error, we'd add the actual field that is incorrect also in the path. Example - /property_id/0/rank
  • For statement missing field error, we'd would not do this because the field is actually missing and it doesn't make sense to add it to the path. But, we should add a new field called field in the context which names the actual field that is missing [insert clown emoji here]