added:
[mir.git] / etc / producer / producers.xml
1 <!--
2   This XML file defines a set of producers intended for a typical indymedia 
3   site:
4     - a start page
5     - a navigational bar
6     - topic pages
7     - a newswire archive
8     - a feature archive
9     - articles
10     - media
11
12   please check the mir user's guide and developer's guide
13   for documentation on the syntax of this file
14 -->  
15
16 <producers>
17   <!-- This first section contains nodedefinitions. -->
18   <!-- A nodedefinition is a sort of "function" that can be "called" later -->
19   <!-- in a producer. -->
20
21   <!-- The Language node enumerates over all  the available languages  -->
22   <!-- and calls the subnode for each language.  This way the subnode  -->
23   <!-- is succesivelly called with its  pathprefix set to "en", "de",  -->
24   <!-- "fr", etc.  -->
25   <nodedefinition name="Language">
26     <parameters>
27           <!-- by default, use all valid languages -->
28           <!-- 'ot' = "Other": used for translations.  -->
29       <string name="languagecondition" defaultvalue="code != 'ot'"/>
30           <!-- prefix of bundles that contain language translations -->
31           <!-- this will be: etc/bundles/producer_xx.properties -->
32       <string name="bundle" defaultvalue="bundles.producer" />
33           <!-- "sub": reference  to subnode of the calling node -->
34       <node name="sub"/>    
35     </parameters>
36
37     <definition>
38       <List key="languages" table="language" selection="${languagecondition}" order="code"/>
39       <Enumerate key="language" table="language" selection="${languagecondition}" order="code">
40         <!-- The  Resource node defines a function that can be used -->
41         <!-- in expressions. The name of the function is given by the  -->
42         <!-- "key" parameter. So in this case, it's lang. One -->
43         <!-- can henceforth  use expressions like  ${lang("page.title")} to -->
44         <!-- refer to a bundle value.                                                                       -->
45         <Resource bundle="${bundle}" key="lang" language="${language.code}"/>
46         <Define key="pathprefix" value="${language.code}" />
47         <Define key="languagepreference" value="${language.code}" />
48         <!-- This  <sub/> tag  is replaced  by the  node arguments  of this -->
49         <!-- "function". In other words, if  this function (nodedef) was   --> 
50         <!-- called this way: <Language>  <Generate ... > </Language> then -->  
51         <!-- the <sub/> tag is replaced by the <Generate ... > node.       -->
52         <sub/>
53         <!-- This condition is meant  for sites where the startpage for, -->
54         <!-- say, english  prefer english translations  over non-english -->
55         <!-- originals. For those sites, an "original" startpage is also -->
56         <!-- generated,  which  always has  articles  in their  original -->
57         <!-- language.  A concrete example:                                                              -->
58                 <!--                                                                                                                     -->
59         <!-- * say the site has languages english and german.            -->
60         <!-- * say article 1 was written in german                                               -->
61         <!-- * say article 2 was written in english, with a german               -->
62         <!--   translation                                               -->
63                 <!--                                                                                                                     -->
64         <!-- Then the english startpage might  have article 1 in german  -->
65         <!-- and article 2 in english                                                                    -->
66                 <!--                                                                                                                     -->
67         <!-- The german  startpage might have  article 1 in german  and  -->
68         <!-- the german translation of article 2                                                 -->
69         <!--                                                                                                                     -->
70         <!-- The  Original startpage  might have  article 1  in  german  -->
71         <!-- and article 2 in english                                                                    -->
72         <If condition="language.code=='en'">
73           <then>
74             <Define key="pathprefix" value="or" />
75             <Define key="languagepreference" value="" />
76             <sub/>
77           </then>
78         </If>
79       </Enumerate>
80     </definition>
81   </nodedefinition>
82
83   <nodedefinition name="RSSChannel">
84     <parameters>
85       <string name="articleSelection"/>
86       <string name="extratables" defaultvalue="none" />
87       <integer name="limit" defaultvalue="15"/>
88       <string name="channelidentifier" defaultvalue=""/>
89       <string name="channelfilename"/>
90       <string name="channeltitle"/>
91       <string name="articleprefix" defaultvalue="${config['Producer.PublicationHost']}/or" />
92       <string name="iconprefix" defaultvalue="${config['Producer.PublicationHost']}/icon" />
93       <string name="channelpublisher" defaultvalue="${config['Mir.Name']}" />
94       <string name="encoding" defaultvalue="UTF-8" />
95       <string name="channeldescription" defaultvalue=""/>
96       <string name="generator" defaultvalue="/RSS.template" />
97     </parameters>
98
99     <definition>
100       <If condition="extratables == 'none' ">
101         <then>
102           <List key="articles" table="content c" selection="${articleSelection}" order = "c.webdb_create desc, c.date desc" limit="limit" />
103         </then>
104         <else>
105           <List key="articles" table="content c" selection="${articleSelection}" order = "c.webdb_create desc, c.date desc" limit="limit" extratables="${extratables}" />
106         </else>
107       </If>
108       <If condition="channeldescription==''">
109         <then>
110           <Define key="channeldescription" value="${channeltitle}"/>
111         </then>
112       </If>
113       <If condition="channelidentifier==''">
114         <then>
115           <Define key="channelidentifier" value="${config['Producer.PublicationHost']}/or/${channelfilename}"/>
116         </then>
117       </If>
118
119       <Generate
120          parameters="${encoding}"
121          generator="${generator}"
122          destination="${config.storageRoot}/${channelfilename}"/>
123     </definition>
124   </nodedefinition>
125
126   <nodedefinition name="RSSChannelBundle">
127     <parameters>
128       <string name="extratables" defaultvalue="none" />
129       <string name="selection" defaultvalue="c.is_published='1'" />  
130       <string name="basefilename" defaultvalue="main" />
131     </parameters>
132     <definition>
133       <!-- newswire -->
134       <RSSChannel
135         articleSelection="(c.to_article_type in (${articletype.newswire}) or (c.to_article_type=${articletype.translation} and c.to_original.to_articletype in (${articletype.newswire}))) and ${selection}"
136         channelfilename="${basefilename}-newswire.rss"
137         channeltitle="${config['Mir.Name']} ${basefilename} newswire"
138         limit="20"
139         extratables="${extratables}"
140       />
141       <RSSChannel
142         articleSelection="(c.to_article_type in (${articletype.newswire}) or (c.to_article_type=${articletype.translation} and c.to_original.to_articletype in (${articletype.newsire}))) and ${selection}"
143         channelfilename="${basefilename}-newswire-content.rss"
144         channeltitle="${config['Mir.Name']} ${basefilename} newswire"
145         limit="20"
146         generator="RSS-full.template"
147         extratables="${extratables}"
148       />    
149       <!-- features -->
150       <RSSChannel
151         articleSelection="(c.to_article_type in (${articletype.feature},${articletype.startspecial},${articletype.topicspecial}) or (c.to_article_type=${articletype.translation} and c.to_original.to_articletype in (${articletype.feature},${articletype.startspecial},${articletype.topicspecial}))) and ${selection}"
152         channelfilename="${basefilename}-features.rss"
153         channeltitle="${config['Mir.Name']} ${basefilename} features"
154         limit="20"
155         extratables="${extratables}"
156       />
157       <RSSChannel
158         articleSelection="(c.to_article_type in (${articletype.feature},${articletype.startspecial},${articletype.topicspecial}) or (c.to_article_type=${articletype.translation} and c.to_original.to_articletype in (${articletype.feature},${articletype.startspecial},${articletype.topicspecial}))) and ${selection}"
159         channelfilename="${basefilename}-features-content.rss"
160         channeltitle="${config['Mir.Name']} ${basefilename} features"
161         limit="20"
162         generator="RSS-full.template"
163         extratables="${extratables}"
164       />
165     </definition>
166   </nodedefinition>
167
168  
169   <!-- This second section contains actual producers that will appear  -->
170   <!-- on the admin->"Generate manually"->"advanced page".             -->
171
172   <!-- This producer generates html  pages, as well as media and video   -->
173   <!-- files for articles stored in the database.  -->
174
175   <!-- It's a  good example  of the use  of the "verb"  concept. The
176        "articles" producer (the  producer responsible for generating
177        article pages), can be called in 3 modes:
178        
179        *  changed, to  regenerate articles  with changes  (new ones,
180        recently  edited  ones,  or ones  with  added/removed/changed
181        comments/media). Note that in this case it will regenerate at
182        most 10 changes articles.
183        
184        * all, to regenerate all articles
185        
186        * sample to regenerate the 10 latest articles  -->
187   <producer name="articles">
188     <!-- verbs define the different actions that may be done by  -->
189     <!-- this producer -->
190     <verbs>
191       <!-- only generate articles that have changed (including new article) -->
192       <verb name="changed" default="1">
193         <Define key="verbcondition" value="(not is_produced)"/>
194         <Set key="limit" value="10"/>
195       </verb>
196       <!-- generate all articles in the db (under certain condiftions...) -->
197       <verb name="all">
198         <Define key="verbcondition" value=""/>
199         <Set key="limit" value="-1"/>
200       </verb>
201
202       <!-- only generate the last 10 articles in the db  -->
203       <verb name="sample">
204         <Define key="verbcondition" value=""/>
205         <Set key="limit" value="10"/>
206       </verb>
207     </verbs>
208     <body>
209       <!-- loop on all articles requested by the "verb"  -->
210       <Enumerate key="article" table="content" selection="${verbcondition}"
211                   limit="limit" order="webdb_create desc">
212         <!-- For each article, generate it's corresponding image files  -->
213         <!-- The  following  sql statements   select  images  that  are -->
214         <!-- associated  with  the   article  (either  directly  or -->
215         <!-- through comments). -->
216         <Enumerate 
217             key="media" table="image" 
218             selection="exists (select * from content_x_media where media_id=images.id and content_id=${article.id})
219                or      exists (select * from comment_x_media, comment
220                            where comment_id = comment.id and media_id=images.id and comment.to_media=${article.id})"
221             order="id desc">
222            <!-- The  generateMedia  node  instructs  the   media  handler
223                associated  with the  media to  "reproduce" the  media. In
224                practice  this can mean  generate an  icon from  an image,
225                writing an  image from  the database to  the web  root, or
226                create an  m3u file or  so.  Media handling is  limited at
227                this  moment,  but a serious redesign is planned -->
228            <GenerateMedia key="media" />
229         </Enumerate>
230         <!-- for each article, generate it's corresponding video files -->
231         <Enumerate 
232             key="media" table="video" 
233             selection="exists (select * from content_x_media where media_id=video.id and content_id=${article.id})
234                or      exists (select * from comment_x_media, comment
235                            where comment_id = comment.id and media_id=video.id and comment.to_media=${article.id})"
236             order="id desc">
237            <GenerateMedia key="media" />
238         </Enumerate>
239         <!-- for each article, generate it's corresponding audio files -->
240         <Enumerate 
241             key="media" table="audio" 
242             selection="exists (select * from content_x_media where media_id=audio.id and content_id=${article.id})
243                or      exists (select * from comment_x_media, comment
244                                        where comment_id = comment.id and media_id=audio.id and comment.to_media=${article.id})"
245             order="id desc">
246             
247            <GenerateMedia key="media" />
248         </Enumerate>
249         <!-- for each article, generate it's corresponding other media files
250               (like pdf's)  -->
251         <Enumerate 
252             key="media" table="otherMedia" 
253             selection="exists (select * from content_x_media where media_id=other_media.id and content_id=${article.id})
254                or      exists (select * from comment_x_media, comment
255                                        where comment_id = comment.id and media_id=other_media.id and comment.to_media=${article.id})"
256             order="id desc">
257             
258            <GenerateMedia key="media" />
259         </Enumerate>
260
261         <If condition="article.is_published == '1'">
262           <!-- only generate published articles -->
263           <then>
264             <!-- loop on all available languages -->
265             <Language>
266               <!-- actually generate the article -->
267               <Generate 
268                 generator="/article.template" 
269                 destination="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.shtml"/>
270             </Language>
271              <!-- generate the article's languagebar -->
272             <Generate 
273               generator="/languagebar.template" 
274               destination="${config.storageRoot}/languagebar/${article.to_original.date.formatted.yyyy}/${article.to_original.date.formatted.MM}/${article.to_original.id}.shtml"/>     
275              <!-- add article to the "search engine" index (lucene) -->
276              <IndexContent key="article" pathToIndex="${config['IndexPath']}"/>
277           </then>
278           <!-- if article is not published, remove it from the search index -->
279           <else>
280             <UnIndexContent key="article" pathToIndex="${config['IndexPath']}"/>
281           </else>
282         </If>
283         <!-- mark (tag) the article as produced -->
284         <MarkContent key="article"/>            
285       </Enumerate>
286     </body>
287   </producer>  
288
289   <!-- generates the left column  -->
290   <producer name="navigation">
291     <verbs>
292       <verb name="generate" default="1" description="generates the left column"/>
293     </verbs>
294     <body>
295       <Language>
296         <Generate 
297             generator="/navigation.template" 
298             destination="${config.storageRoot}/${pathprefix}/navigation.inc"/>
299       </Language>
300     </body>
301   </producer>
302   
303   <producer name="staticimages">
304     <verbs>
305       <verb name="generate" default="1" description="copies all the static image files into place"/>
306     </verbs>
307     <body>
308       <CopyDir destination="img" source="etc/producer/images"/>
309     </body>
310   </producer>
311   
312   <producer name="newswirearchive">
313     <verbs>
314       <verb name="new">
315         <Set key="pages" value="3"/>
316       </verb>
317       <verb name="all">
318         <Set key="pages" value="-1"/>
319       </verb>
320     </verbs>
321     <body>
322         <Define key="docSuffix" value=".shtml"/>
323         <Define key="storageSuffix" value=".shtml"/>
324
325         <Batch key="articles" infokey="batch" table="content"
326                process="pages" batchsize="20" minbatchsize="10"
327                selection="is_published='1' and to_article_type = ${articletype.newswire}"
328                order="webdb_create asc">
329           <batches>
330             <Language>
331               <Define key="pagePrefix" value="${pathprefix}/newswire/archive"/>
332               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
333               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
334
335               <Generate
336                   generator="newswirearchive.template"
337                   destination="${storagePrefix}${batch.current.identifier}${storageSuffix}"/>
338
339             </Language>
340           </batches>
341           <batchlist>
342             <Language>
343               <Define key="pagePrefix" value="${pathprefix}/newswire/archive"/>
344               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
345               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
346               <Generate
347                   generator="batchnav.template"
348                   destination="${storagePrefix}nav${storageSuffix}"/>
349             </Language>
350           </batchlist>
351         </Batch>
352     </body>
353   </producer>
354
355   <producer name="featurearchive">
356     <verbs>
357       <verb name="new">
358         <Set key="pages" value="3"/>
359       </verb>
360       <verb name="all">
361         <Set key="pages" value="-1"/>
362       </verb> 
363     </verbs>
364     <body>
365         <Define key="docSuffix" value=".shtml"/>
366         <Define key="storageSuffix" value=".shtml"/>
367         
368         <Batch key="articles" infokey="batch" table="content" 
369                process="pages" batchsize="20" minbatchsize="10"
370                selection="is_published='1' and to_article_type in (${articletype.feature}, ${articletype.startspecial})"
371                order="webdb_create asc">
372           <batches>
373             <Language>
374               <Define key="pagePrefix" value="${pathprefix}/feature/archive"/>
375               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
376               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
377
378               <Generate 
379                   generator="featurearchive.template" 
380                   destination="${storagePrefix}${batch.current.identifier}${storageSuffix}"/>
381
382             </Language>
383           </batches>
384           <batchlist>
385             <Language>
386               <Define key="pagePrefix" value="${pathprefix}/feature/archive"/>
387               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
388               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
389               <Generate 
390                   generator="batchnav.template" 
391                   destination="${storagePrefix}nav${storageSuffix}"/>
392             </Language>
393           </batchlist>
394         </Batch>
395     </body>
396   </producer>
397
398   <producer name="topicpages">
399     <verbs>
400       <verb name="new">
401         <Set key="_topics" value="-1"/>
402         <Set key="pages" value="3"/>
403       </verb>
404       <verb name="all">
405         <Set key="_topics" value="-1"/>
406         <Set key="pages" value="-1"/>
407       </verb> 
408       <verb name="sample">
409         <Set key="_topics" value="2"/>
410         <Set key="pages" value="4"/>
411       </verb> 
412     </verbs>
413     <body>
414       <Enumerate key="topic" table="topic" limit="_topics">
415         <Define key="docSuffix" value=".shtml"/>
416         <Define key="storageSuffix" value=".shtml"/>
417         
418         <List key="special" table="content c" 
419           selection="c.is_published='1' and c.to_article_type = ${articletype.topicspecial} and c.id=cxt.content_id and cxt.topic_id = ${topic.id}"
420           order = "webdb_create desc" limit="1"
421           extratables="content_x_topic cxt"/>
422       
423         <Batch key="articles" infokey="batch" table="content c" 
424                process="pages" batchsize="20" minbatchsize="10"
425                selection="c.is_published='1' and c.to_article_type in (${articletype.newswire}, ${articletype.feature}) and c.id=cxt.content_id and cxt.topic_id = ${topic.id}"
426                order="webdb_create asc" extratables="content_x_topic cxt">
427           <batches>
428             <Language>
429               <Define key="pagePrefix" value="${pathprefix}/${topic.filename}/archive"/>
430               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
431               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
432
433               <Generate 
434                   generator="topicpage.template" 
435                   destination="${storagePrefix}${batch.current.identifier}${storageSuffix}"/>
436
437             </Language>
438           </batches>
439           <batchlist>
440             <Language>
441               <Define key="pagePrefix" value="${pathprefix}/${topic.filename}/archive"/>
442               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
443               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
444               <Generate 
445                   generator="batchnav.template" 
446                   destination="${storagePrefix}nav${storageSuffix}"/>
447             </Language>
448           </batchlist>
449         </Batch>
450       </Enumerate>
451     </body>
452   </producer>
453   
454   <!-- generates the main html page (startpage) of an indymedia site  -->
455   <producer name="startpage">
456     <verbs>
457       <verb name="generate" default="1" description="Generates the startpage"/>
458     </verbs>
459
460     <body>
461       <List key="startspecial" table="content" limit="1"
462         selection="is_published=true and to_article_type=${articletype.startspecial}"
463         order="webdb_create desc"/>
464                                         
465       <List key="features" table="content" limit="10" 
466         selection="is_published=true and to_article_type=${articletype.feature}"
467         order="webdb_create desc"/>
468
469       <List key="newswire" table="content" limit="30"
470         selection="is_published=true and to_article_type=${articletype.newswire}"
471         order="webdb_create desc"/>
472         
473       <List key="breakingnews" table="breakingNews" limit="10"
474          order="webdb_create desc"/>
475         
476       <Language>
477         <Generate 
478             generator="/startpage.template" 
479             destination="${config.storageRoot}/${pathprefix}/index.shtml"/>
480       </Language>
481     </body>
482   </producer>  
483   
484   <!-- Use rsync to copy static site to mirrors (only if requested   -->
485   <!-- in config file)  -->
486   <producer name="synchronization">
487     <verbs>
488       <verb name="run" default="1" description="Synchronizes the publication site with the production site"/>
489     </verbs>
490
491     <body>
492        <ReportChanges format="${config.now.formatted['HH:mm:ss']} ${change.type} ${config['Producer.ProductionHost']}${change.path}"
493                   file="${config['Producer.StorageRoot']}/changes/changes${config.now.formatted['yyyyMMdd']}.txt"
494                              basepath="${config['Producer.StorageRoot']}" />
495
496     
497
498
499       <If condition="config['Rsync'] in ('1', 'y', 'yes', 'Y')">
500         <then>
501           <Execute command="${config['Rsync.Script.Path']}"/>
502         </then>
503       </If>
504     </body>
505   </producer>  
506   
507   
508   <producer name="media">
509     <verbs>
510       <verb name="new" default="1">
511         <Define key="verbcondition" value="(not is_produced)"/>
512         <Set key="limit" value="10"/>
513       </verb>
514       <verb name="all">
515         <Define key="verbcondition" value=""/>
516         <Set key="limit" value="-1"/>
517       </verb>
518
519       <verb name="sample">
520         <Define key="verbcondition" value=""/>
521         <Set key="limit" value="10"/>
522       </verb>
523     </verbs>
524     <body>
525       <Enumerate 
526           key="media" table="image" 
527           selection="${verbcondition}"
528           limit="limit" 
529           order="webdb_create desc">
530           
531          <GenerateMedia key="media" />
532       </Enumerate>
533       <Enumerate 
534           key="media" table="video" 
535           selection="${verbcondition}"
536           limit="limit" 
537           order="webdb_create desc">
538           
539          <GenerateMedia key="media" />
540       </Enumerate>
541       <Enumerate 
542           key="media" table="audio" 
543           selection="${verbcondition}"
544           limit="limit" 
545           order="webdb_create desc">
546           
547          <GenerateMedia key="media" />
548       </Enumerate>
549       <Enumerate 
550           key="media" table="otherMedia" 
551           selection="${verbcondition}"
552           limit="limit" 
553           order="webdb_create desc">
554           
555          <GenerateMedia key="media" />
556       </Enumerate>
557     </body>
558   </producer>  
559
560   <producer name="syndication">
561     <verbs>
562       <verb name="generate" />
563     </verbs>
564     <body>
565       <!-- the main features and newswire -->
566       <RSSChannelBundle />
567       
568       <!-- the topic features and newswires -->
569       <Enumerate key="topic" table="topic">
570         <RSSChannelBundle
571           basefilename="${topic.filename}"
572           selection="c.id=cxt.content_id and cxt.topic_id = ${topic.id}"
573           extratables="content_x_topic cxt"
574         />
575       </Enumerate>
576       
577       
578
579     </body>
580
581   </producer>
582
583   <producer name="radicalendar">
584     <verbs>
585       <verb name="pull" />
586     </verbs>
587     <body>
588       <!-- groupname you will see as the value of "group" in the url for your radicalendar page, -->
589       <!--      gmtoffset is in minutes                                                          -->
590       <Radicalendar key="calendar" groupname="_imc" gmtoffset="60"  />
591       <Generate 
592         generator="/radicalendar.template" 
593         destination="${config.storageRoot}/calendarinclude.shtml"/>
594
595
596     </body>
597   </producer>
598
599   
600 </producers>
601
602