added:
[mir.git] / etc / producer / producers.xml
index 13bb6cb..b305c29 100755 (executable)
@@ -1,4 +1,4 @@
-<!-- 
+<!--
   This XML file defines a set of producers intended for a typical indymedia 
   site:
     - a start page
     - a feature archive
     - articles
     - media
+
+  please check the mir user's guide and developer's guide
+  for documentation on the syntax of this file
 -->  
 
 <producers>
+  <!-- This first section contains nodedefinitions. -->
+  <!-- A nodedefinition is a sort of "function" that can be "called" later -->
+  <!-- in a producer. -->
+
+  <!-- The Language node enumerates over all  the available languages  -->
+  <!-- and calls the subnode for each language.  This way the subnode  -->
+  <!-- is succesivelly called with its  pathprefix set to "en", "de",  -->
+  <!-- "fr", etc.  -->
   <nodedefinition name="Language">
     <parameters>
-      <string name="languagecondition" defaultvalue=""/>
+         <!-- by default, use all valid languages -->
+         <!-- 'ot' = "Other": used for translations.  -->
+      <string name="languagecondition" defaultvalue="code != 'ot'"/>
+         <!-- prefix of bundles that contain language translations -->
+         <!-- this will be: etc/bundles/producer_xx.properties -->
       <string name="bundle" defaultvalue="bundles.producer" />
+         <!-- "sub": reference  to subnode of the calling node -->
       <node name="sub"/>    
     </parameters>
 
     <definition>
       <List key="languages" table="language" selection="${languagecondition}" order="code"/>
       <Enumerate key="language" table="language" selection="${languagecondition}" order="code">
+        <!-- The  Resource node defines a function that can be used -->
+        <!-- in expressions. The name of the function is given by the  -->
+        <!-- "key" parameter. So in this case, it's lang. One -->
+        <!-- can henceforth  use expressions like  ${lang("page.title")} to -->
+        <!-- refer to a bundle value.                                                                      -->
         <Resource bundle="${bundle}" key="lang" language="${language.code}"/>
         <Define key="pathprefix" value="${language.code}" />
+        <Define key="languagepreference" value="${language.code}" />
+        <!-- This  <sub/> tag  is replaced  by the  node arguments  of this -->
+        <!-- "function". In other words, if  this function (nodedef) was   --> 
+        <!-- called this way: <Language>  <Generate ... > </Language> then -->  
+        <!-- the <sub/> tag is replaced by the <Generate ... > node.      -->
         <sub/>
+        <!-- This condition is meant  for sites where the startpage for, -->
+        <!-- say, english  prefer english translations  over non-english -->
+        <!-- originals. For those sites, an "original" startpage is also -->
+        <!-- generated,  which  always has  articles  in their  original -->
+        <!-- language.  A concrete example:                                                             -->
+               <!--                                                                                                                     -->
+        <!-- * say the site has languages english and german.            -->
+        <!-- * say article 1 was written in german                                              -->
+        <!-- * say article 2 was written in english, with a german              -->
+        <!--   translation                                               -->
+               <!--                                                                                                                     -->
+        <!-- Then the english startpage might  have article 1 in german  -->
+        <!-- and article 2 in english                                                                   -->
+               <!--                                                                                                                     -->
+        <!-- The german  startpage might have  article 1 in german  and  -->
+        <!-- the german translation of article 2                                                -->
+        <!--                                                                                                                    -->
+        <!-- The  Original startpage  might have  article 1  in  german  -->
+        <!-- and article 2 in english                                                                   -->
+        <If condition="language.code=='en'">
+          <then>
+            <Define key="pathprefix" value="or" />
+            <Define key="languagepreference" value="" />
+            <sub/>
+          </then>
+        </If>
       </Enumerate>
     </definition>
   </nodedefinition>
+
+  <nodedefinition name="RSSChannel">
+    <parameters>
+      <string name="articleSelection"/>
+      <string name="extratables" defaultvalue="none" />
+      <integer name="limit" defaultvalue="15"/>
+      <string name="channelidentifier" defaultvalue=""/>
+      <string name="channelfilename"/>
+      <string name="channeltitle"/>
+      <string name="articleprefix" defaultvalue="${config['Producer.PublicationHost']}/or" />
+      <string name="iconprefix" defaultvalue="${config['Producer.PublicationHost']}/icon" />
+      <string name="channelpublisher" defaultvalue="${config['Mir.Name']}" />
+      <string name="encoding" defaultvalue="UTF-8" />
+      <string name="channeldescription" defaultvalue=""/>
+      <string name="generator" defaultvalue="/RSS.template" />
+    </parameters>
+
+    <definition>
+      <If condition="extratables == 'none' ">
+        <then>
+          <List key="articles" table="content c" selection="${articleSelection}" order = "c.webdb_create desc, c.date desc" limit="limit" />
+        </then>
+        <else>
+          <List key="articles" table="content c" selection="${articleSelection}" order = "c.webdb_create desc, c.date desc" limit="limit" extratables="${extratables}" />
+        </else>
+      </If>
+      <If condition="channeldescription==''">
+        <then>
+         <Define key="channeldescription" value="${channeltitle}"/>
+       </then>
+      </If>
+      <If condition="channelidentifier==''">
+        <then>
+          <Define key="channelidentifier" value="${config['Producer.PublicationHost']}/or/${channelfilename}"/>
+        </then>
+      </If>
+
+      <Generate
+         parameters="${encoding}"
+         generator="${generator}"
+        destination="${config.storageRoot}/${channelfilename}"/>
+    </definition>
+  </nodedefinition>
+
+  <nodedefinition name="RSSChannelBundle">
+    <parameters>
+      <string name="extratables" defaultvalue="none" />
+      <string name="selection" defaultvalue="c.is_published='1'" />  
+      <string name="basefilename" defaultvalue="main" />
+    </parameters>
+    <definition>
+      <!-- newswire -->
+      <RSSChannel
+        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}"
+        channelfilename="${basefilename}-newswire.rss"
+        channeltitle="${config['Mir.Name']} ${basefilename} newswire"
+        limit="20"
+       extratables="${extratables}"
+      />
+      <RSSChannel
+        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}"
+        channelfilename="${basefilename}-newswire-content.rss"
+        channeltitle="${config['Mir.Name']} ${basefilename} newswire"
+        limit="20"
+        generator="RSS-full.template"
+       extratables="${extratables}"
+      />    
+      <!-- features -->
+      <RSSChannel
+        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}"
+        channelfilename="${basefilename}-features.rss"
+        channeltitle="${config['Mir.Name']} ${basefilename} features"
+        limit="20"
+       extratables="${extratables}"
+      />
+      <RSSChannel
+        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}"
+        channelfilename="${basefilename}-features-content.rss"
+        channeltitle="${config['Mir.Name']} ${basefilename} features"
+        limit="20"
+        generator="RSS-full.template"
+       extratables="${extratables}"
+      />
+    </definition>
+  </nodedefinition>
+
  
+  <!-- This second section contains actual producers that will appear  -->
+  <!-- on the admin->"Generate manually"->"advanced page".             -->
+
+  <!-- This producer generates html  pages, as well as media and video   -->
+  <!-- files for articles stored in the database.  -->
+
+  <!-- It's a  good example  of the use  of the "verb"  concept. The
+       "articles" producer (the  producer responsible for generating
+       article pages), can be called in 3 modes:
+       
+       *  changed, to  regenerate articles  with changes  (new ones,
+       recently  edited  ones,  or ones  with  added/removed/changed
+       comments/media). Note that in this case it will regenerate at
+       most 10 changes articles.
+       
+       * all, to regenerate all articles
+       
+       * sample to regenerate the 10 latest articles  -->
   <producer name="articles">
+    <!-- verbs define the different actions that may be done by  -->
+    <!-- this producer -->
     <verbs>
+      <!-- only generate articles that have changed (including new article) -->
       <verb name="changed" default="1">
         <Define key="verbcondition" value="(not is_produced)"/>
         <Set key="limit" value="10"/>
       </verb>
+      <!-- generate all articles in the db (under certain condiftions...) -->
       <verb name="all">
         <Define key="verbcondition" value=""/>
         <Set key="limit" value="-1"/>
       </verb>
 
+      <!-- only generate the last 10 articles in the db  -->
       <verb name="sample">
         <Define key="verbcondition" value=""/>
         <Set key="limit" value="10"/>
       </verb>
     </verbs>
     <body>
+      <!-- loop on all articles requested by the "verb"  -->
       <Enumerate key="article" table="content" selection="${verbcondition}"
                   limit="limit" order="webdb_create desc">
+        <!-- For each article, generate it's corresponding image files  -->
+        <!-- The  following  sql statements   select  images  that  are -->
+        <!-- associated  with  the   article  (either  directly  or -->
+        <!-- through comments). -->
+        <Enumerate 
+            key="media" table="image" 
+            selection="exists (select * from content_x_media where media_id=images.id and content_id=${article.id})
+               or      exists (select * from comment_x_media, comment
+                           where comment_id = comment.id and media_id=images.id and comment.to_media=${article.id})"
+            order="id desc">
+           <!-- The  generateMedia  node  instructs  the   media  handler
+               associated  with the  media to  "reproduce" the  media. In
+               practice  this can mean  generate an  icon from  an image,
+               writing an  image from  the database to  the web  root, or
+               create an  m3u file or  so.  Media handling is  limited at
+               this  moment,  but a serious redesign is planned -->
+           <GenerateMedia key="media" />
+        </Enumerate>
+        <!-- for each article, generate it's corresponding video files -->
+        <Enumerate 
+            key="media" table="video" 
+            selection="exists (select * from content_x_media where media_id=video.id and content_id=${article.id})
+               or      exists (select * from comment_x_media, comment
+                           where comment_id = comment.id and media_id=video.id and comment.to_media=${article.id})"
+            order="id desc">
+           <GenerateMedia key="media" />
+        </Enumerate>
+        <!-- for each article, generate it's corresponding audio files -->
+        <Enumerate 
+            key="media" table="audio" 
+            selection="exists (select * from content_x_media where media_id=audio.id and content_id=${article.id})
+               or      exists (select * from comment_x_media, comment
+                                       where comment_id = comment.id and media_id=audio.id and comment.to_media=${article.id})"
+            order="id desc">
+            
+           <GenerateMedia key="media" />
+        </Enumerate>
+        <!-- for each article, generate it's corresponding other media files
+              (like pdf's)  -->
+        <Enumerate 
+            key="media" table="otherMedia" 
+            selection="exists (select * from content_x_media where media_id=other_media.id and content_id=${article.id})
+               or      exists (select * from comment_x_media, comment
+                                       where comment_id = comment.id and media_id=other_media.id and comment.to_media=${article.id})"
+            order="id desc">
+            
+           <GenerateMedia key="media" />
+        </Enumerate>
+
         <If condition="article.is_published == '1'">
+          <!-- only generate published articles -->
           <then>
+            <!-- loop on all available languages -->
             <Language>
+              <!-- actually generate the article -->
               <Generate 
                 generator="/article.template" 
                 destination="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.shtml"/>
-              <Generate 
-                generator="/emailThisArticle.template" 
-                destination="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.txt"/>
-               <!--
-              <PDFPreFormat 
-                key="article" 
-                numLinesBetweenImages="3" 
-                charWidthCM="0.19" 
-                pixelWidthCM="0.035"
-                contentAreaWidthCM="16" 
-                lineHeightCM="0.5" />
-              <Generate 
-                generator="/printablecontent.template" 
-                destination="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.fo"
-                parameters="UTF-8" />
-              <PDFGenerate
-                generator="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.fo"
-                destination="${config.storageRoot}/${pathprefix}/${article.date.formatted.yyyy}/${article.date.formatted.MM}/${article.id}.pdf"
-                stylesheet="${config['Producer.HTML2FOStyleSheet']}" /> -->
-             </Language>
+            </Language>
+             <!-- generate the article's languagebar -->
+            <Generate 
+              generator="/languagebar.template" 
+              destination="${config.storageRoot}/languagebar/${article.to_original.date.formatted.yyyy}/${article.to_original.date.formatted.MM}/${article.to_original.id}.shtml"/>    
+             <!-- add article to the "search engine" index (lucene) -->
              <IndexContent key="article" pathToIndex="${config['IndexPath']}"/>
           </then>
+          <!-- if article is not published, remove it from the search index -->
           <else>
             <UnIndexContent key="article" pathToIndex="${config['IndexPath']}"/>
           </else>
         </If>
+        <!-- mark (tag) the article as produced -->
         <MarkContent key="article"/>            
       </Enumerate>
     </body>
   </producer>  
 
+  <!-- generates the left column  -->
   <producer name="navigation">
     <verbs>
       <verb name="generate" default="1" description="generates the left column"/>
       </verb>
       <verb name="all">
         <Set key="pages" value="-1"/>
-      </verb> 
+      </verb>
     </verbs>
     <body>
         <Define key="docSuffix" value=".shtml"/>
         <Define key="storageSuffix" value=".shtml"/>
-        
-        <Batch key="articles" infokey="batch" table="content" 
+
+        <Batch key="articles" infokey="batch" table="content"
                process="pages" batchsize="20" minbatchsize="10"
                selection="is_published='1' and to_article_type = ${articletype.newswire}"
                order="webdb_create asc">
               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
 
-              <Generate 
-                  generator="newswirearchive.template" 
+              <Generate
+                  generator="newswirearchive.template"
                   destination="${storagePrefix}${batch.current.identifier}${storageSuffix}"/>
 
             </Language>
               <Define key="pagePrefix" value="${pathprefix}/newswire/archive"/>
               <Define key="storagePrefix" value="${config[&quot;Producer.StorageRoot&quot;]}/${pagePrefix}"/>
               <Define key="docPrefix" value="${config[&quot;Producer.DocRoot&quot;]}/${pagePrefix}"/>
-              <Generate 
-                  generator="batchnav.template" 
+              <Generate
+                  generator="batchnav.template"
                   destination="${storagePrefix}nav${storageSuffix}"/>
             </Language>
           </batchlist>
         <Define key="docSuffix" value=".shtml"/>
         <Define key="storageSuffix" value=".shtml"/>
         
-        <List key="special" table="content" 
-          selection="is_published='1' and to_article_type = ${articletype.topicspecial} and id in (select content_id from content_x_topic where topic_id = ${topic.id})"
-          order = "webdb_create desc" limit="1"/>
+        <List key="special" table="content c" 
+          selection="c.is_published='1' and c.to_article_type = ${articletype.topicspecial} and c.id=cxt.content_id and cxt.topic_id = ${topic.id}"
+          order = "webdb_create desc" limit="1"
+          extratables="content_x_topic cxt"/>
       
-        <Batch key="articles" infokey="batch" table="content" 
+        <Batch key="articles" infokey="batch" table="content c
                process="pages" batchsize="20" minbatchsize="10"
-               selection="is_published='1' and to_article_type in (${articletype.newswire}, ${articletype.feature}) and id in (select content_id from content_x_topic where topic_id = ${topic.id})"
-               order="webdb_create asc">
+               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}"
+               order="webdb_create asc" extratables="content_x_topic cxt">
           <batches>
             <Language>
               <Define key="pagePrefix" value="${pathprefix}/${topic.filename}/archive"/>
     </body>
   </producer>
   
+  <!-- generates the main html page (startpage) of an indymedia site  -->
   <producer name="startpage">
     <verbs>
       <verb name="generate" default="1" description="Generates the startpage"/>
     </body>
   </producer>  
   
+  <!-- Use rsync to copy static site to mirrors (only if requested   -->
+  <!-- in config file)  -->
   <producer name="synchronization">
     <verbs>
       <verb name="run" default="1" description="Synchronizes the publication site with the production site"/>
     </verbs>
 
     <body>
+       <ReportChanges format="${config.now.formatted['HH:mm:ss']} ${change.type} ${config['Producer.ProductionHost']}${change.path}"
+                 file="${config['Producer.StorageRoot']}/changes/changes${config.now.formatted['yyyyMMdd']}.txt"
+                            basepath="${config['Producer.StorageRoot']}" />
+
+    
+
+
       <If condition="config['Rsync'] in ('1', 'y', 'yes', 'Y')">
         <then>
           <Execute command="${config['Rsync.Script.Path']}"/>
       </Enumerate>
     </body>
   </producer>  
+
+  <producer name="syndication">
+    <verbs>
+      <verb name="generate" />
+    </verbs>
+    <body>
+      <!-- the main features and newswire -->
+      <RSSChannelBundle />
+      
+      <!-- the topic features and newswires -->
+      <Enumerate key="topic" table="topic">
+        <RSSChannelBundle
+          basefilename="${topic.filename}"
+         selection="c.id=cxt.content_id and cxt.topic_id = ${topic.id}"
+          extratables="content_x_topic cxt"
+        />
+      </Enumerate>
+      
+      
+
+    </body>
+
+  </producer>
+
+  <producer name="radicalendar">
+    <verbs>
+      <verb name="pull" />
+    </verbs>
+    <body>
+      <!-- groupname you will see as the value of "group" in the url for your radicalendar page, -->
+      <!--      gmtoffset is in minutes                                                                 -->
+      <Radicalendar key="calendar" groupname="_imc" gmtoffset="60"  />
+      <Generate 
+        generator="/radicalendar.template" 
+        destination="${config.storageRoot}/calendarinclude.shtml"/>
+
+
+    </body>
+  </producer>
+
   
 </producers>