1. Usage

1.1. Rules to assign routes and/or templates to articles

With the API, it is possible to create and manage rules in order to assign a route and/or a template to content received in a package from a provider based on the metadata in that package.

The rules themselves are to be written in Symfony’s expression language, documentation for which can be found here: http://symfony.com/doc/current/components/expression_language/syntax.html

The article document generated from the package can be referenced directly in the rule. So, here is an example of a rule:

1
2
3
4
5
6
'article.getMetadataByKey("var_name") matches "/regexExp/"'
# ..
'article.getMetadataByKey("urgency") > 1'
# or
'article.getMetadataByKey("lead") matches "/Text/"'
# etc.

A priority can also be assigned to the rule. This is simply an integer. The rules are ordered by their priority (the greater the value, the higher the priority) before searching for the first one which matches.

The route to be assigned is identified by its id, for example:

1
'articles/features'

If a template name parameter (templateName) is given with the rule, this template will be assigned to the article instead of the one in the route.

Every rule is automatically processed when the content is pushed to api/v1/content/push API endpoint. The SWP\Bundle\ContentBundle\EventListener\ProcessArticleRulesSubscriber subscriber subscribes to SWP\Bundle\ContentBundle\ArticleEvents::PRE_CREATE event and runs the processing when needed.

1.2. Pushing Content to Web Publisher

1.2.1. Content Push API Endpoint

Content Push API Endpoint

Method URL
POST /api/v1/content/push

Resource details

Response format JSON
Authentication No

Example Request

1
POST https://<tenant_name>.domain.com/api/v1/content/push

Example Response

1
2
3
{
    "status": "OK"
}

Response status code is 201.

1.2.2. Which content formats are allowed to be pushed?

The Superdesk Web Publisher can receive content of different formats, by default the IPTC’s ninjs format is supported.

  • ninjs - standardizes the representation of news in JSON - a lightweight, easy-to-parse, data interchange format.

In Superdesk Web Publisher we use an extension of the standard IPTC’s ninjs format (to validate incoming request’s content), which is extended by some additional fields:

  • uri was replaced by guid: uri should be the resource identifier on the web but since the item was not published yet it can’t be determined at this point
  • added priority field
  • added service field
  • added slugline field
  • added keywords field
  • associations dictionary may contain entire items like in this ninjs example: http://dev.iptc.org/ninjs-Examples-3

By default, Superdesk Web Publisher is meant to work with our in-house content creation software called Superdesk which uses the above extension of ninjs format to store the data. That’s why in Web Publisher the incoming content is being validated in the same format.

In the future we could also support other IPTC formats, like: NewsML-G2, NITF etc. So you would be able to push content to Web Publisher in format that fits you best.

Superdesk ninjs extension schema used by Web Publisher:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
{
    "$schema": "http://json-schema.org/draft-03/schema#",
    "id" : "http://www.iptc.org/std/ninjs/ninjs-schema_1.1.json#",
    "type" : "object",
    "title" : "IPTC ninjs - News in JSON - version 1.1 (approved, 2014-03-12) / document revision of 2014-11-15: geometry_* moved under place",
    "description" : "A news item as JSON object -- copyright 2014 IPTC - International Press Telecommunications Council - www.iptc.org - This document is published under the Creative Commons Attribution 3.0 license, see  http://creativecommons.org/licenses/by/3.0/  $$comment: as of 2014-03-13 ",
    "additionalProperties" : false,
    "patternProperties" : {
        "^description_[a-zA-Z0-9_]+" : {
            "description" : "A free-form textual description of the content of the item. (The string appended to description_ in the property name should reflect the format of the text)",
            "type" : "string"
        },
        "^body_[a-zA-Z0-9_]+" : {
            "description" : "The textual content of the news object. (The string appended to body_ in the property name should reflect the format of the text)",
            "type" : "string"
        }
    },
    "properties" : {
        "guid" : {
            "description" : "The identifier for this news object",
            "type" : "string",
            "format" : "guid",
            "required" : true
        },
        "type" : {
            "description" : "The generic news type of this news object",
            "type" : "string",
            "enum" : ["text", "audio", "video", "picture", "graphic", "composite"]
        },
        "slugline" : {
            "description" : "The slugline",
            "type" : "string",
            "required" : true
        },
        "mimetype" : {
            "description" : "A MIME type which applies to this news object",
            "type" : "string"
        },
        "representationtype" : {
            "description" : "Indicates how complete this representation of a news item is",
            "type" : "string",
            "enum" : ["complete", "incomplete"]
        },
        "profile" : {
            "description" : "An identifier for the kind of content of this news object",
            "type" : "string"
        },
        "version" : {
            "description" : "The version of the news object which is identified by the uri property",
            "type" : "string"
        },
        "versioncreated" : {
            "description" : "The date and time when this version of the news object was created",
            "type" : "string",
            "format" : "date-time"
        },
        "embargoed" : {
            "description" : "The date and time before which all versions of the news object are embargoed. If absent, this object is not embargoed.",
            "type" : "string",
            "format" : "date-time"
        },
        "pubstatus" : {
            "description" : "The publishing status of the news object, its value is *usable* by default.",
            "type" : "string",
            "enum" : ["usable", "withheld", "canceled"]
        },
        "urgency" : {
            "description" : "The editorial urgency of the content from 1 to 9. 1 represents the highest urgency, 9 the lowest.",
            "type" : "number"
        },
        "priority" : {
            "description" : "The editorial priority of the content from 1 to 9. 1 represents the highest priority, 9 the lowest.",
            "type" : "number"
        },
        "copyrightholder" : {
            "description" : "The person or organisation claiming the intellectual property for the content.",
            "type" : "string"
        },
        "copyrightnotice" : {
            "description" : "Any necessary copyright notice for claiming the intellectual property for the content.",
            "type" : "string"
        },
        "usageterms" : {
            "description" : "A natural-language statement about the usage terms pertaining to the content.",
            "type" : "string"
        },
        "language" : {
            "description" : "The human language used by the content. The value should follow IETF BCP47",
            "type" : "string"
        },
        "service" : {
            "description" : "A service e.g. World Photos, UK News etc.",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of a service",
                        "type" : "string"
                    },
                    "code" : {
                        "description": "The code for the service in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    }
                }
            }
        },
        "person" : {
            "description" : "An individual human being",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of a person",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the person",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the person",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "code" : {
                        "description": "The code for the person in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    }
                }
            }
        },
        "organisation" : {
            "description" : "An administrative and functional structure which may act as as a business, as a political party or not-for-profit party",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of the organisation",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the organisation",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the organisation",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "code" : {
                        "description": "The code for the organisation in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    },
                    "symbols" : {
                        "description" : "Symbols used for a finanical instrument linked to the organisation at a specific market place",
                        "type" : "array",
                        "items" : {
                            "type" : "object",
                            "additionalProperties" : false,
                            "properties" : {
                                "ticker" : {
                                    "description" : "Ticker symbol used for the financial instrument",
                                    "type": "string"
                                },
                                "exchange" : {
                                    "description" : "Identifier for the marketplace which uses the ticker symbols of the ticker property",
                                    "type" : "string"
                                }
                            }
                        }
                    }
                }
            }
        },
        "place" : {
            "description" : "A named location",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "patternProperties" : {
                    "^geometry_[a-zA-Z0-9_]+" : {
                        "description" : "An object holding geo data of this place. Could be of any relevant geo data JSON object definition.",
                        "type" : "object"
                    }
                },
                "properties" : {
                    "name" : {
                        "description" : "The name of the place",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the place",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the place",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "qcode" : {
                        "description": "The code for the place in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    },
                    "state" : {
                        "description" : "The state for the place",
                        "type" : "string"
                    },
                    "group" : {
                        "description" : "The place group",
                        "type" : "string"
                    },
                    "name" : {
                        "description" : "The place name",
                        "type" : "string"
                    },
                    "country" : {
                        "description" : "The country name",
                        "type" : "string"
                    },
                    "world_region" : {
                        "description" : "The world region",
                        "type" : "string"
                    }
                }
            }
        },
        "subject" : {
            "description" : "A concept with a relationship to the content",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of the subject",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the subject",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the subject",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "code" : {
                        "description": "The code for the subject in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    }
                }
            }
        },
        "event" : {
            "description" : "Something which happens in a planned or unplanned manner",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of the event",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the event",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the event",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "code" : {
                        "description": "The code for the event in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    }
                }
            }
        },
        "object" : {
            "description" : "Something material, excluding persons",
            "type" : "array",
            "items" : {
                "type" : "object",
                "additionalProperties" : false,
                "properties" : {
                    "name" : {
                        "description" : "The name of the object",
                        "type" : "string"
                    },
                    "rel" : {
                        "description" : "The relationship of the content of the news object to the object",
                        "type" : "string"
                    },
                    "scheme" : {
                        "description" : "The identifier of a scheme (= controlled vocabulary) which includes a code for the object",
                        "type" : "string",
                        "format" : "uri"
                    },
                    "code" : {
                        "description": "The code for the object in a scheme (= controlled vocabulary) which is identified by the scheme property",
                        "type" : "string"
                    }
                }
            }
        },
        "byline" : {
            "description" : "The name(s) of the creator(s) of the content",
            "type" : "string"
        },
        "headline" : {
            "description" : "A brief and snappy introduction to the content, designed to catch the reader's attention",
            "type" : "string"
        },
        "located" : {
            "description" : "The name of the location from which the content originates.",
            "type" : "string"
        },
        "keywords": {
            "description" : "Content keywords",
            "type" : "array"
        },
        "renditions" : {
            "description" : "Wrapper for different renditions of non-textual content of the news object",
            "type" : "object",
            "additionalProperties" : false,
            "patternProperties" : {
                "^[a-zA-Z0-9]+" : {
                    "description" : "A specific rendition of a non-textual content of the news object.",
                    "type" : "object",
                    "additionalProperties" : false,
                    "properties" : {
                        "href" : {
                            "description" : "The URL for accessing the rendition as a resource",
                            "type" : "string",
                            "format" : "uri"
                        },
                        "mimetype" : {
                            "description" : "A MIME type which applies to the rendition",
                            "type" : "string"
                        },
                        "title" : {
                            "description" : "A title for the link to the rendition resource",
                            "type" : "string"
                        },
                        "height" : {
                            "description" : "For still and moving images: the height of the display area measured in pixels",
                            "type" : "number"
                        },
                        "width" : {
                            "description" : "For still and moving images: the width of the display area measured in pixels",
                            "type" : "number"
                        },
                        "sizeinbytes" : {
                            "description" : "The size of the rendition resource in bytes",
                            "type" : "number"
                        }
                    }
                }
            }
        },
        "associations" : {
            "description" : "Content of news objects which are associated with this news object.",
            "type" : "object",
            "additionalProperties" : false,
            "patternProperties" : {
                "^[a-zA-Z0-9]+" :  { "$ref": "http://www.iptc.org/std/ninjs/ninjs-schema_1.0.json#" }
            }
        }
    }
}

1.2.3. How Content is Pushed to Web Publisher?

Making a POST request to api/v1/content/push API endpoint, you can push whatever content you want in request’s payload. See Content Push API Endpoint section.

The below diagram shows the data flow from the moment of their receipt by the content/push API endpoint until it’s saved as a resulting Article object in the persistence backend.

../../_images/swp_data_flow.png

As you can see the request is being sent first, then the request’s content is validated using Web Publisher validators (see validators Usage section for more info about validators).

Once the content passes the validation (i.e. submitted content is for example in ninjs format), a respective transformer/parser (see Using Transformer Chain Service for more details) transforms (according to submitted content) the incoming data to format which is understandable by Web Publisher, i.e. Package and Item objects which are reflecting the submitted content.

Once this is done, the converted request’s content is being persisted in Web Publisher persistence backend as a representation of Package and Item objects.

The last step is converting already persisted Package and Item objects to Article object which is used by Web Publisher internally and on which every operation is being made.

1.2.4. How the article’s slug is being generated?

The article’s slug is being generated from the slugline field, if it is not empty, else the headline property’s value (according to ninjs IPTC format) is used to populate the article`s slug.

Warning

If the slugline property in incoming data is missing or is empty, the article’s slug will be generated from the headline, which means if you would want to change the headline and submit content again, a new article will be created instead as the article’s slug will be generated from the headline field.

1.2.5. What happens when I want to change article’s title?

You can change existing article’s title in the content that you are sending to Web Publisher. Let’s say we have a simple text item or package in ninjs format, as it is defined according to Which content formats are allowed to be pushed?.

Once the item/package headline is changed and the whole content is pushed to Web Publisher again, the article’s title will be updated automatically.

1.2.6. What happens when I want to change article’s slug?

If an article already exists and you want to change the article’s slug, the content which you used to create the article for the first time should be re-sent with modified slugline property. Once you change the slugline property’s value and submit it again to Web Publisher, a new article will be created.

1.2.7. How do I auto-publish an article?

In some cases, you will need to publish an article automatically, without additional action. In this bundle a special logic has been implemented which is responsible for the auto publishing articles, which is based on the rules. You can read more about rules in sections: Rules to assign routes and/or templates to articles, RuleBundle - Usage section.

All you need to do in order to auto-publish your articles, you need to first add a rule. If the article will match the rule, it will be auto published.

Create a new rule:

1
$ curl 'http://localhost/api/v1/rules/' -H 'Content-Type: application/x-www-form-urlencoded' --data 'rule%5Bpriority%5D=1&rule%5Bexpression%5D=article.getMetadataByKey(%22located%22)+matches+%22%2FSydney%2F%22&rule%5Bconfiguration%5D%5B0%5D%5Bkey%5D=published&rule%5Bconfiguration%5D%5B0%5D%5Bvalue%5D=true' --compressed

Submitted rule’s expression:

1
article.getMetadataByKey("located") matches "/Sydney/"

Submitted rule’s configuration:

1
2
rule[configuration][0][key]: published
rule[configuration][0][value]: true

It means that if the above rule’s expression matches any article, it will apply the configuration to it - in this case it will publish article.