wikidata_adaptor 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.env.test +7 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +45 -0
  5. data/.yardopts +10 -0
  6. data/CHANGELOG.md +106 -0
  7. data/CLAUDE.md +200 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/COVERAGE.md +77 -0
  10. data/Gemfile +20 -0
  11. data/Gemfile.lock +124 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +269 -0
  14. data/Rakefile +18 -0
  15. data/integration/.env.example +20 -0
  16. data/integration/README.md +58 -0
  17. data/integration/config/99_IntegrationTesting.php +3 -0
  18. data/integration/config/wikibase-php.ini +15 -0
  19. data/integration/docker-compose.yml +98 -0
  20. data/lib/wikidata_adaptor/rest_api/aliases.rb +88 -0
  21. data/lib/wikidata_adaptor/rest_api/descriptions.rb +138 -0
  22. data/lib/wikidata_adaptor/rest_api/items.rb +36 -0
  23. data/lib/wikidata_adaptor/rest_api/labels.rb +138 -0
  24. data/lib/wikidata_adaptor/rest_api/open_api_document.rb +15 -0
  25. data/lib/wikidata_adaptor/rest_api/properties.rb +36 -0
  26. data/lib/wikidata_adaptor/rest_api/property_data_types.rb +15 -0
  27. data/lib/wikidata_adaptor/rest_api/search_item.rb +44 -0
  28. data/lib/wikidata_adaptor/rest_api/search_property.rb +44 -0
  29. data/lib/wikidata_adaptor/rest_api/sitelinks.rb +59 -0
  30. data/lib/wikidata_adaptor/rest_api/statements.rb +153 -0
  31. data/lib/wikidata_adaptor/rest_api.rb +32 -0
  32. data/lib/wikidata_adaptor/test_helpers/rest_api/aliases.rb +229 -0
  33. data/lib/wikidata_adaptor/test_helpers/rest_api/descriptions.rb +308 -0
  34. data/lib/wikidata_adaptor/test_helpers/rest_api/items.rb +213 -0
  35. data/lib/wikidata_adaptor/test_helpers/rest_api/labels.rb +302 -0
  36. data/lib/wikidata_adaptor/test_helpers/rest_api/open_api_document.rb +29 -0
  37. data/lib/wikidata_adaptor/test_helpers/rest_api/properties.rb +233 -0
  38. data/lib/wikidata_adaptor/test_helpers/rest_api/property_data_types.rb +23 -0
  39. data/lib/wikidata_adaptor/test_helpers/rest_api/search_item.rb +118 -0
  40. data/lib/wikidata_adaptor/test_helpers/rest_api/search_property.rb +118 -0
  41. data/lib/wikidata_adaptor/test_helpers/rest_api/sitelinks.rb +143 -0
  42. data/lib/wikidata_adaptor/test_helpers/rest_api/statements.rb +475 -0
  43. data/lib/wikidata_adaptor/test_helpers/rest_api/support/support.rb +310 -0
  44. data/lib/wikidata_adaptor/test_helpers/rest_api.rb +89 -0
  45. data/lib/wikidata_adaptor/version.rb +6 -0
  46. data/lib/wikidata_adaptor.rb +28 -0
  47. data/sig/wikidata_adaptor.rbs +4 -0
  48. metadata +106 -0
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataAdaptor
4
+ class RestApi
5
+ # https://doc.wikimedia.org/Wikibase/master/js/rest-api/#/statements
6
+ module Statements
7
+ # Retrieve Statements from an Item.
8
+ #
9
+ # Optional filter:
10
+ # params[:property] => property ID (e.g., "P31")
11
+ def get_item_statements(item_id, params = { property: nil })
12
+ query = params[:property] ? "?property=#{CGI.escape(params[:property])}" : ""
13
+ get_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements#{query}")
14
+ end
15
+
16
+ # Retrieve a single Statement from an Item.
17
+ def get_item_statement(item_id, statement_id)
18
+ get_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements/#{statement_id}")
19
+ end
20
+
21
+ # Add a Statement to an Item.
22
+ #
23
+ # @param [String] item_id The ID of the Item.
24
+ # @param [Hash] payload Statement and edit metadata.
25
+ #
26
+ # @return [Hash] The newly created Statement.
27
+ def post_item_statement(item_id, payload)
28
+ post_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements", payload)
29
+ end
30
+
31
+ # Retrieve a single Statement (global).
32
+ def get_statement(statement_id)
33
+ get_json("#{endpoint}/v1/statements/#{statement_id}")
34
+ end
35
+
36
+ # Retrieve Statements from a Property.
37
+ def get_property_statements(property_id)
38
+ get_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements")
39
+ end
40
+
41
+ # Retrieve a single Statement from a Property.
42
+ def get_property_statement(property_id, statement_id)
43
+ get_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements/#{statement_id}")
44
+ end
45
+
46
+ # Add a Statement to a Property.
47
+ #
48
+ # @param [String] property_id The ID of the Property.
49
+ # @param [Hash] payload Statement and edit metadata.
50
+ #
51
+ # @return [Hash] The newly created Statement.
52
+ def post_property_statement(property_id, payload)
53
+ post_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements", payload)
54
+ end
55
+
56
+ # Replace a Statement on an Item.
57
+ #
58
+ # @param [String] item_id The ID of the Item.
59
+ # @param [String] statement_id The Statement ID.
60
+ # @param [Hash] payload Statement and edit metadata.
61
+ #
62
+ # @return [Hash] The replaced Statement.
63
+ def put_item_statement(item_id, statement_id, payload)
64
+ put_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements/#{statement_id}", payload)
65
+ end
66
+
67
+ # Replace a Statement on a Property.
68
+ #
69
+ # @param [String] property_id The ID of the Property.
70
+ # @param [String] statement_id The Statement ID.
71
+ # @param [Hash] payload Statement and edit metadata.
72
+ #
73
+ # @return [Hash] The replaced Statement.
74
+ def put_property_statement(property_id, statement_id, payload)
75
+ put_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements/#{statement_id}", payload)
76
+ end
77
+
78
+ # Replace a Statement (global).
79
+ #
80
+ # @param [String] statement_id The Statement ID.
81
+ # @param [Hash] payload Statement and edit metadata.
82
+ #
83
+ # @return [Hash] The replaced Statement.
84
+ def put_statement(statement_id, payload)
85
+ put_json("#{endpoint}/v1/statements/#{statement_id}", payload)
86
+ end
87
+
88
+ # Apply JSON Patch operations to a Statement on an Item.
89
+ #
90
+ # @param [String] item_id The ID of the Item.
91
+ # @param [String] statement_id The Statement ID.
92
+ # @param [Hash] payload JSON Patch operations and edit metadata.
93
+ #
94
+ # @return [Hash] The updated Statement.
95
+ def patch_item_statement(item_id, statement_id, payload)
96
+ patch_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements/#{statement_id}", payload)
97
+ end
98
+
99
+ # Apply JSON Patch operations to a Statement on a Property.
100
+ #
101
+ # @param [String] property_id The ID of the Property.
102
+ # @param [String] statement_id The Statement ID.
103
+ # @param [Hash] payload JSON Patch operations and edit metadata.
104
+ #
105
+ # @return [Hash] The updated Statement.
106
+ def patch_property_statement(property_id, statement_id, payload)
107
+ patch_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements/#{statement_id}", payload)
108
+ end
109
+
110
+ # Apply JSON Patch operations to a Statement (global).
111
+ #
112
+ # @param [String] statement_id The Statement ID.
113
+ # @param [Hash] payload JSON Patch operations and edit metadata.
114
+ #
115
+ # @return [Hash] The updated Statement.
116
+ def patch_statement(statement_id, payload)
117
+ patch_json("#{endpoint}/v1/statements/#{statement_id}", payload)
118
+ end
119
+
120
+ # Delete a Statement from an Item.
121
+ #
122
+ # @param [String] item_id The ID of the Item.
123
+ # @param [String] statement_id The Statement ID.
124
+ # @param [Hash] payload Edit metadata (comment).
125
+ #
126
+ # @return [String] Confirmation message.
127
+ def delete_item_statement(item_id, statement_id, payload)
128
+ delete_json("#{endpoint}/v1/entities/items/#{CGI.escape(item_id)}/statements/#{statement_id}", payload)
129
+ end
130
+
131
+ # Delete a Statement from a Property.
132
+ #
133
+ # @param [String] property_id The ID of the Property.
134
+ # @param [String] statement_id The Statement ID.
135
+ # @param [Hash] payload Edit metadata (comment).
136
+ #
137
+ # @return [String] Confirmation message.
138
+ def delete_property_statement(property_id, statement_id, payload)
139
+ delete_json("#{endpoint}/v1/entities/properties/#{CGI.escape(property_id)}/statements/#{statement_id}", payload)
140
+ end
141
+
142
+ # Delete a Statement (global).
143
+ #
144
+ # @param [String] statement_id The Statement ID.
145
+ # @param [Hash] payload Edit metadata (comment).
146
+ #
147
+ # @return [String] Confirmation message.
148
+ def delete_statement(statement_id, payload)
149
+ delete_json("#{endpoint}/v1/statements/#{statement_id}", payload)
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adapter for the wikibase REST API
4
+ #
5
+ # @see https://doc.wikimedia.org/Wikibase/master/js/rest-api/
6
+ module WikidataAdaptor
7
+ # Wikidata REST API class
8
+ class RestApi < ApiAdaptor::Base
9
+ require_relative "rest_api/open_api_document"
10
+ require_relative "rest_api/items"
11
+ require_relative "rest_api/sitelinks"
12
+ require_relative "rest_api/properties"
13
+ require_relative "rest_api/labels"
14
+ require_relative "rest_api/descriptions"
15
+ require_relative "rest_api/aliases"
16
+ require_relative "rest_api/statements"
17
+ require_relative "rest_api/property_data_types"
18
+ require_relative "rest_api/search_item"
19
+ require_relative "rest_api/search_property"
20
+ include WikidataAdaptor::RestApi::OpenApiDocument
21
+ include WikidataAdaptor::RestApi::Items
22
+ include WikidataAdaptor::RestApi::Sitelinks
23
+ include WikidataAdaptor::RestApi::Properties
24
+ include WikidataAdaptor::RestApi::Labels
25
+ include WikidataAdaptor::RestApi::Descriptions
26
+ include WikidataAdaptor::RestApi::Aliases
27
+ include WikidataAdaptor::RestApi::Statements
28
+ include WikidataAdaptor::RestApi::PropertyDataTypes
29
+ include WikidataAdaptor::RestApi::SearchItem
30
+ include WikidataAdaptor::RestApi::SearchProperty
31
+ end
32
+ end
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataAdaptor
4
+ module TestHelpers
5
+ module RestApi
6
+ # WebMock stubs for Wikibase REST API alias endpoints
7
+ module Aliases
8
+ ######################################
9
+ # GET /v1/entities/items/:item_id/aliases
10
+ ######################################
11
+ def stub_get_item_aliases(item_id)
12
+ stub_rest_api_request(
13
+ :get,
14
+ "/v1/entities/items/#{item_id}/aliases",
15
+ response_body: {
16
+ en: [
17
+ "Douglas Noel Adams",
18
+ "Douglas Noël Adams"
19
+ ],
20
+ fr: [
21
+ "Douglas Noel Adams"
22
+ ]
23
+ }
24
+ )
25
+ end
26
+
27
+ #####################################################
28
+ # GET /v1/entities/items/:item_id/aliases/:language_code
29
+ #####################################################
30
+ def stub_get_item_alias(item_id, language_code)
31
+ stub_rest_api_request(
32
+ :get,
33
+ "/v1/entities/items/#{item_id}/aliases/#{language_code}",
34
+ response_body: [
35
+ "Douglas Noel Adams",
36
+ "Douglas Noël Adams"
37
+ ]
38
+ )
39
+ end
40
+
41
+ ############################################################
42
+ # POST /v1/entities/items/:item_id/aliases/:language_code
43
+ ############################################################
44
+ def stub_post_item_aliases(item_id, language_code, payload, response_body: nil)
45
+ stub_rest_api_request(
46
+ :post,
47
+ "/v1/entities/items/#{item_id}/aliases/#{language_code}",
48
+ response_status: 200,
49
+ with: { body: payload.to_json },
50
+ response_body: response_body || ["Douglas Noel Adams", "Douglas Noël Adams"]
51
+ )
52
+ end
53
+
54
+ # Stub POST item aliases request returning 201 Created
55
+ #
56
+ # @param [String] item_id The item ID
57
+ # @param [String] language_code The language code
58
+ # @param [Hash] payload The request payload
59
+ # @param [Array<String>, nil] response_body Optional custom response
60
+ #
61
+ # @return [WebMock::RequestStub]
62
+ def stub_post_item_aliases_created(item_id, language_code, payload, response_body: nil)
63
+ stub_rest_api_request(
64
+ :post,
65
+ "/v1/entities/items/#{item_id}/aliases/#{language_code}",
66
+ response_status: 201,
67
+ with: { body: payload.to_json },
68
+ response_body: response_body || ["Douglas Noel Adams", "Douglas Noël Adams"]
69
+ )
70
+ end
71
+
72
+ # Stub POST item aliases request returning 500 error
73
+ #
74
+ # @param [String] item_id The item ID
75
+ # @param [String] language_code The language code
76
+ # @param [Hash] payload The request payload
77
+ #
78
+ # @return [WebMock::RequestStub]
79
+ def stub_post_item_aliases_unexpected_error(item_id, language_code, payload)
80
+ stub_rest_api_request(
81
+ :post,
82
+ "/v1/entities/items/#{item_id}/aliases/#{language_code}",
83
+ response_status: 500,
84
+ with: { body: payload.to_json },
85
+ response_body: {
86
+ code: "unexpected-error",
87
+ message: "Unexpected Error"
88
+ }
89
+ )
90
+ end
91
+
92
+ ########################################
93
+ # GET /v1/entities/properties/:property_id/aliases
94
+ ########################################
95
+ def stub_get_property_aliases(property_id)
96
+ stub_rest_api_request(
97
+ :get,
98
+ "/v1/entities/properties/#{property_id}/aliases",
99
+ response_body: {
100
+ en: ["is a"],
101
+ fr: ["est un"]
102
+ }
103
+ )
104
+ end
105
+
106
+ ########################################################
107
+ # GET /v1/entities/properties/:property_id/aliases/:language_code
108
+ ########################################################
109
+ def stub_get_property_alias(property_id, language_code)
110
+ stub_rest_api_request(
111
+ :get,
112
+ "/v1/entities/properties/#{property_id}/aliases/#{language_code}",
113
+ response_body: ["is a"]
114
+ )
115
+ end
116
+
117
+ ################################################################
118
+ # POST /v1/entities/properties/:property_id/aliases/:language_code
119
+ ################################################################
120
+ def stub_post_property_aliases(property_id, language_code, payload, response_body: nil)
121
+ stub_rest_api_request(
122
+ :post,
123
+ "/v1/entities/properties/#{property_id}/aliases/#{language_code}",
124
+ response_status: 200,
125
+ with: { body: payload.to_json },
126
+ response_body: response_body || ["is a", "is an"]
127
+ )
128
+ end
129
+
130
+ # Stub POST property aliases request returning 201 Created
131
+ #
132
+ # @param [String] property_id The property ID
133
+ # @param [String] language_code The language code
134
+ # @param [Hash] payload The request payload
135
+ # @param [Array<String>, nil] response_body Optional custom response
136
+ #
137
+ # @return [WebMock::RequestStub]
138
+ def stub_post_property_aliases_created(property_id, language_code, payload, response_body: nil)
139
+ stub_rest_api_request(
140
+ :post,
141
+ "/v1/entities/properties/#{property_id}/aliases/#{language_code}",
142
+ response_status: 201,
143
+ with: { body: payload.to_json },
144
+ response_body: response_body || ["is a", "is an"]
145
+ )
146
+ end
147
+
148
+ # Stub POST property aliases request returning 500 error
149
+ #
150
+ # @param [String] property_id The property ID
151
+ # @param [String] language_code The language code
152
+ # @param [Hash] payload The request payload
153
+ #
154
+ # @return [WebMock::RequestStub]
155
+ def stub_post_property_aliases_unexpected_error(property_id, language_code, payload)
156
+ stub_rest_api_request(
157
+ :post,
158
+ "/v1/entities/properties/#{property_id}/aliases/#{language_code}",
159
+ response_status: 500,
160
+ with: { body: payload.to_json },
161
+ response_body: {
162
+ code: "unexpected-error",
163
+ message: "Unexpected Error"
164
+ }
165
+ )
166
+ end
167
+
168
+ ###########################################
169
+ # PATCH /v1/entities/items/:item_id/aliases
170
+ ###########################################
171
+ def stub_patch_item_aliases(item_id, payload, response_body: nil)
172
+ stub_rest_api_request(
173
+ :patch,
174
+ "/v1/entities/items/#{item_id}/aliases",
175
+ with: { body: payload.to_json },
176
+ response_body: response_body || {
177
+ en: ["Douglas Noel Adams", "Douglas Noël Adams", "DNA"],
178
+ fr: ["Douglas Noel Adams"]
179
+ }
180
+ )
181
+ end
182
+
183
+ # Stub PATCH item aliases request returning 500 error
184
+ #
185
+ # @param [String] item_id The item ID
186
+ # @param [Hash] payload The request payload
187
+ #
188
+ # @return [WebMock::RequestStub]
189
+ def stub_patch_item_aliases_unexpected_error(item_id, payload)
190
+ stub_rest_api_request(
191
+ :patch,
192
+ "/v1/entities/items/#{item_id}/aliases",
193
+ response_status: 500,
194
+ with: { body: payload.to_json },
195
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
196
+ )
197
+ end
198
+
199
+ #################################################
200
+ # PATCH /v1/entities/properties/:property_id/aliases
201
+ #################################################
202
+ def stub_patch_property_aliases(property_id, payload, response_body: nil)
203
+ stub_rest_api_request(
204
+ :patch,
205
+ "/v1/entities/properties/#{property_id}/aliases",
206
+ with: { body: payload.to_json },
207
+ response_body: response_body || { en: ["is a", "is an"], fr: ["est un"] }
208
+ )
209
+ end
210
+
211
+ # Stub PATCH property aliases request returning 500 error
212
+ #
213
+ # @param [String] property_id The property ID
214
+ # @param [Hash] payload The request payload
215
+ #
216
+ # @return [WebMock::RequestStub]
217
+ def stub_patch_property_aliases_unexpected_error(property_id, payload)
218
+ stub_rest_api_request(
219
+ :patch,
220
+ "/v1/entities/properties/#{property_id}/aliases",
221
+ response_status: 500,
222
+ with: { body: payload.to_json },
223
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
224
+ )
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end