Adamw has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/74305


Change subject: Generalized mailing job queue
......................................................................

Generalized mailing job queue

Change-Id: I36cd21a1bff531931565e1248e8c39edd0a066c4
---
A sites/all/modules/wmf_common/wmf_communication/Job.php
M sites/all/modules/wmf_common/wmf_communication/Mailer.php
A sites/all/modules/wmf_common/wmf_communication/MailingTemplate.php
A sites/all/modules/wmf_common/wmf_communication/Recipient.php
M sites/all/modules/wmf_common/wmf_communication/Templating.php
M sites/all/modules/wmf_common/wmf_communication/Translation.php
A sites/all/modules/wmf_common/wmf_communication/tests/Job.test
A sites/all/modules/wmf_common/wmf_communication/tests/TestThankyouTemplate.php
A 
sites/all/modules/wmf_common/wmf_communication/tests/templates/html/thank_you.it.html
A 
sites/all/modules/wmf_common/wmf_communication/tests/templates/txt/thank_you.it.txt
A 
sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.info
A 
sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.module
A sites/all/modules/wmf_common/wmf_communication/wmf_communication.drush.inc
M sites/all/modules/wmf_common/wmf_communication/wmf_communication.info
A sites/all/modules/wmf_common/wmf_communication/wmf_communication.install
M sites/all/modules/wmf_common/wmf_communication/wmf_communication.module
16 files changed, 609 insertions(+), 8 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/crm 
refs/changes/05/74305/1

diff --git a/sites/all/modules/wmf_common/wmf_communication/Job.php 
b/sites/all/modules/wmf_common/wmf_communication/Job.php
new file mode 100644
index 0000000..e3620e1
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/Job.php
@@ -0,0 +1,63 @@
+<?php namespace wmf_communication;
+
+use \Exception;
+
+class Job {
+    protected $id;
+    protected $template;
+
+    static function getJob( $id ) {
+        $job = new Job();
+        $job->id = $id;
+
+        $row = db_select( 'wmf_communication_job' )
+            ->fields( 'wmf_communication_job' )
+            ->condition( 'id', $id )
+            ->execute()
+            ->fetchAssoc();
+
+        if ( !$row ) {
+            throw new Exception( 'No such job found: ' . $id );
+        }
+
+        $templateClass = $row['template_class'];
+        if ( !class_exists( $templateClass ) ) {
+            throw new Exception( 'Could not find mailing template class: ' . 
$templateClass );
+        }
+        $job->template = new $templateClass;
+        if ( !( $job->template instanceof IMailingTemplate ) ) {
+            throw new Exception( 'Mailing template class must implement 
IMailingTemplate' );
+        }
+
+        return $job;
+    }
+
+    function run() {
+        $mailer = new Mailer();
+
+        while ( $recipients = Recipient::getQueuedBatch( $this->id ) ) {
+            foreach ( $recipients as $recipient ) {
+                $bodyTemplate = $this->template->getBodyTemplate( $recipient );
+
+                $email = array(
+                    'from_name' => $this->template->getFromName(),
+                    'from_address' => $this->template->getFromAddress(),
+                    'reply_to' => $this->template->getFromAddress(),
+                    'to_name' => $recipient->getName(),
+                    'to_address' => $recipient->getEmail(),
+                    'subject' => $this->template->getSubject( $recipient ),
+                    'plaintext' => $bodyTemplate->render( 'txt' ),
+                    'html' => $bodyTemplate->render( 'html' ),
+                );
+
+                $success = $mailer->send( $email );
+
+                if ( $success ) {
+                    $recipient->setSuccessful();
+                } else {
+                    $recipient->setFailed();
+                }
+            }
+        }
+    }
+}
diff --git a/sites/all/modules/wmf_common/wmf_communication/Mailer.php 
b/sites/all/modules/wmf_common/wmf_communication/Mailer.php
index b437190..6accf4b 100644
--- a/sites/all/modules/wmf_common/wmf_communication/Mailer.php
+++ b/sites/all/modules/wmf_common/wmf_communication/Mailer.php
@@ -1,10 +1,8 @@
-<?php
+<?php namespace wmf_communication;
+
 /**
  * TODO: really decouple from implementation
  */
-
-namespace wmf_communication;
-
 class Mailer {
     function __construct() {
         require_once implode(DIRECTORY_SEPARATOR, 
array(variable_get('wmf_common_phpmailer_location', ''), 
'class.phpmailer.php'));
diff --git a/sites/all/modules/wmf_common/wmf_communication/MailingTemplate.php 
b/sites/all/modules/wmf_common/wmf_communication/MailingTemplate.php
new file mode 100644
index 0000000..64c5076
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/MailingTemplate.php
@@ -0,0 +1,45 @@
+<?php namespace wmf_communication;
+
+interface IMailingTemplate {
+    function getSubject( $recipient );
+
+    function getBodyTemplate( $recipient );
+}
+
+/**
+ * Most mailings will extend this class and simply define a subject key and 
template path.
+ */
+abstract class AbstractMailingTemplate implements IMailingTemplate {
+    abstract function getSubjectKey();
+
+    abstract function getTemplateDir();
+
+    abstract function getTemplateName();
+
+    function getFromAddress() {
+        return variable_get( 'thank_you_from_address', null );
+    }
+
+    function getFromName() {
+        return variable_get( 'thank_you_from_name', null );
+    }
+
+    function getSubject( $recipient ) {
+        return Translation::get_translated_message( $this->getSubjectKey(), 
$recipient->getLanguage() );
+    }
+
+    function getBodyTemplate( $recipient ) {
+        $templateParams = array(
+            'name' => $recipient->getName(),
+            'email' => $recipient->getEmail(),
+        );
+        $templateParams = array_merge( $templateParams, $recipient->getVars() 
);
+
+        return new Templating(
+            $this->getTemplateDir(),
+            $this->getTemplateName(),
+            $recipient->getLanguage(),
+            $templateParams
+        );
+    }
+}
diff --git a/sites/all/modules/wmf_common/wmf_communication/Recipient.php 
b/sites/all/modules/wmf_common/wmf_communication/Recipient.php
new file mode 100644
index 0000000..84540d1
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/Recipient.php
@@ -0,0 +1,94 @@
+<?php namespace wmf_communication;
+
+use \Exception;
+
+class Recipient {
+    protected $contactId;
+    protected $jobId;
+    protected $status;
+    protected $vars = array();
+
+    /**
+     * Get queued recipients, up to $batchSize.
+     *
+     * Call repeatedly until empty set is returned.
+     */
+    static function getQueuedBatch( $jobId, $batchSize = 100 ) {
+        $result = db_select( 'wmf_communication_recipient' )
+            ->fields( 'wmf_communication_recipient' )
+            ->condition( 'job_id', $jobId )
+            ->condition( 'status', 'queued' )
+            ->range( 0, $batchSize )
+            ->execute();
+
+        $recipients = array();
+        while ( $row = $result->fetchAssoc() ) {
+            $recipients[] = new Recipient( $row );
+        }
+        return $recipients;
+    }
+
+    function __construct( $dbRow ) {
+        $this->contactId = $dbRow['contact_id'];
+        $this->jobId = $dbRow['job_id'];
+        $this->status = $dbRow['status'];
+
+        if ( $dbRow['vars'] ) {
+            $this->vars = json_decode( $dbRow['vars'], true );
+            if ( $this->vars === null ) {
+                throw new Exception( 'Could not decode serialized vars, error 
code: ' . json_last_error() );
+            }
+        }
+
+        // FIXME: Get contact details en masse.
+        // TODO: Maybe we want to decouple from the civi db, and keep all 
necessary contact
+        // info in the recipient table.
+        $api = civicrm_api_classapi();
+        $success = $api->Contact->get( array(
+            'id' => $this->contactId,
+            'return' => 'email,display_name,preferred_language',
+            'version' => 3,
+        ) );
+        if ( !$success ) {
+            throw new Exception( $api->errorMsg() );
+        }
+        $values = $api->values();
+        if ( $values ) {
+            $this->contact = array_pop( $values );
+        } else {
+            throw new Exception( 'Tried to email a non-existent contact, ' . 
$this->contactId );
+        }
+    }
+
+    function getEmail() {
+        return $this->contact->email;
+    }
+
+    function getName() {
+        return $this->contact->display_name;
+    }
+
+    function getLanguage() {
+        return Translation::normalize_language_code( 
$this->contact->preferred_language );
+    }
+
+    function getVars() {
+        return $this->vars;
+    }
+
+    function setFailed() {
+        $this->setStatus( 'failed' );
+    }
+
+    function setSuccessful() {
+        $this->setStatus( 'successful' );
+    }
+
+    function setStatus( $status ) {
+        db_update( 'wmf_communication_recipient' )
+            ->fields( array(
+                'status' => $status
+            ) )
+            ->execute();
+    }
+}
diff --git a/sites/all/modules/wmf_common/wmf_communication/Templating.php 
b/sites/all/modules/wmf_common/wmf_communication/Templating.php
index df60c35..3e48c03 100644
--- a/sites/all/modules/wmf_common/wmf_communication/Templating.php
+++ b/sites/all/modules/wmf_common/wmf_communication/Templating.php
@@ -1,6 +1,6 @@
-<?php
+<?php namespace wmf_communication;
 
-namespace wmf_communication;
+use \Exception;
 
 class Templating {
     protected $twig;
@@ -22,6 +22,7 @@
 
     function render( $format )
     {
+        $template = null;
         $language = $this->language;
         do {
             try {
@@ -33,6 +34,10 @@
             $language = Translation::next_fallback( $language );
         } while ( $language );
 
+        if ( !$template ) {
+            throw new Exception( "Cannot load template {$this->template_name} 
/ {$this->language} . {$format}" );
+        }
+
         return $template->render( $this->template_params );
     }
 }
diff --git a/sites/all/modules/wmf_common/wmf_communication/Translation.php 
b/sites/all/modules/wmf_common/wmf_communication/Translation.php
index 64d1792..e3ed7b1 100644
--- a/sites/all/modules/wmf_common/wmf_communication/Translation.php
+++ b/sites/all/modules/wmf_common/wmf_communication/Translation.php
@@ -1,6 +1,6 @@
-<?php
+<?php namespace wmf_communication;
 
-namespace wmf_communication;
+use \Exception;
 
 class Translation {
     //TODO: get from MediaWiki
diff --git a/sites/all/modules/wmf_common/wmf_communication/tests/Job.test 
b/sites/all/modules/wmf_common/wmf_communication/tests/Job.test
new file mode 100644
index 0000000..db1a02d
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/tests/Job.test
@@ -0,0 +1,84 @@
+<?php
+
+use wmf_communication\Job;
+
+require_once 'TestThankyouTemplate.php';
+
+class JobTest extends DrupalWebTestCase {
+    protected $profile = 'minimal';
+
+    public static function getInfo() {
+        return array(
+            'name' => 'Mailing Job',
+            'group' => 'Wikimedia',
+            'description' => 'Create and run a mailing job',
+        );
+    }
+
+    public function setUp() {
+        // FIXME: cheat by taking some variables from the live db
+        $phpmailerDir = variable_get( 'wmf_common_phpmailer_location', '' );
+        $twigDir = variable_get( 'wmf_common_twig_location', '' );
+        $diDir = variable_get( 'wmf_common_di_location', '' );
+
+        parent::setUp( 'wmf_communication', 'wmf_common' );
+
+        variable_set( 'wmf_common_phpmailer_location', $phpmailerDir );
+        variable_set( 'wmf_common_twig_location', $twigDir );
+        variable_set( 'wmf_common_di_location', $diDir );
+
+        variable_set( 'thank_you_from_address', '[email protected]' );
+        variable_set( 'thank_you_from_name', 'Testus' );
+
+        $api = civicrm_api_classapi();
+        $success = $api->Contact->create( array(
+            'contact_type' => 'Individual',
+            'email' => '[email protected]',
+            'first_name' => 'Foo',
+            'last_name' => 'Beer',
+            'preferred_language' => 'it',
+            'version' => 3,
+        ) );
+        if ( !$success ) {
+            $this->fail( $api->errorMsg() );
+        }
+        $result = $api->values();
+        $contact = array_pop( $result );
+        $this->contactId = $contact->id;
+
+        $this->jobId = db_insert( 'wmf_communication_job' )
+            ->fields( array(
+                'template_class' => 'TestThankyouTemplate',
+            ) )
+            ->execute();
+
+        db_insert( 'wmf_communication_recipient' )
+            ->fields( array(
+                'job_id' => $this->jobId,
+                'contact_id' => $this->contactId,
+                'status' => 'queued',
+                'vars' => json_encode( array(
+                    'contribution' => array(
+                        'receive_date' => date( DateTime::ISO8601 ),
+                        'contribution_source' => 'EUR 22.11',
+                    ),
+                ) ),
+            ) )
+            ->execute();
+    }
+
+    public function testRun() {
+        $job = Job::getJob( $this->jobId );
+        $this->assertNotNull( $job, "Got the job" );
+        $job->run();
+
+        //FIXME: simpletest fails to override the mailer, so something must be 
done to disable phpmailer
+        $mails = $this->drupalGetMails();
+        $this->verbose(json_encode($mails));
+        //...
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+}
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/tests/TestThankyouTemplate.php 
b/sites/all/modules/wmf_common/wmf_communication/tests/TestThankyouTemplate.php
new file mode 100644
index 0000000..d2613c3
--- /dev/null
+++ 
b/sites/all/modules/wmf_common/wmf_communication/tests/TestThankyouTemplate.php
@@ -0,0 +1,17 @@
+<?php
+
+use wmf_communication\AbstractMailingTemplate;
+
+class TestThankyouTemplate extends AbstractMailingTemplate {
+    function getSubjectKey() {
+        return 'donate_interface-email-subject';
+    }
+
+    function getTemplateName() {
+        return 'thank_you';
+    }
+
+    function getTemplateDir() {
+        return __DIR__ . "/templates";
+    }
+}
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/tests/templates/html/thank_you.it.html
 
b/sites/all/modules/wmf_common/wmf_communication/tests/templates/html/thank_you.it.html
new file mode 100644
index 0000000..a2e0ea5
--- /dev/null
+++ 
b/sites/all/modules/wmf_common/wmf_communication/tests/templates/html/thank_you.it.html
@@ -0,0 +1,83 @@
+<p>Caro {{contact.first_name}},</p>
+
+<p>Grazie per la tua donazione alla Wikimedia Foundation. È stata davvero 
apprezzata di
+cuore!</p>
+
+<p>È facile ignorare i nostri banner, perciò sono davvero felice che tu non 
l'abbia
+fatto. È così che Wikipedia paga le proprie bollette: persone come te che 
donano un po'
+del loro denaro per permetterci di mantenere questo sito disponibile 
gratuitamente in
+tutto il mondo.</p>
+
+<p>Molte persone mi hanno detto che donano a Wikipedia perché lo considerano 
un atto
+utile, e si fidano del progetto anche se non è perfetto, perché è scritto per 
loro.
+Wikipedia non è fatta per supportare una qualche agenzia di pubbliche 
relazioni o una
+particolare ideologia, né cerca di persuadere le persone a credere in qualcosa 
che non
+sia vero. Il nostro obiettivo è dire la verità, e lo possiamo fare grazie a 
te. Il tuo
+supporto economico al sito ci permette di restare indipendenti e di fornirti 
ciò di cui
+hai bisogno e ciò che vuoi da Wikipedia. Esattamente come è giusto che sia.</p>
+
+<p>È necessario che tu sappia che la tua donazione non copre solamente i costi 
correlati
+al tuo uso del progetto. Il donatore medio copre i costi del proprio utilizzo 
ma anche per
+quello di migliaia di altre persone. La tua donazione rende Wikipedia 
utilizzabile da
+tutti: un'ambiziosa bambina di Bangalore che sta imparando da autodidatta a 
programmare al
+computer; una casalinga di mezza età di Vienna alla quale è stato appena 
diagnosticato
+il morbo di Parkinson; un romanziere che sta studiando la letteratura 
britannica di metà
+Ottocento; un bambino salvadoregno di dieci anni che ha appena scoperto Carl 
Sagan.</p>
+
+<p>A nome di queste persone e del mezzo miliardo di altri lettori di Wikipedia 
e i suoi
+progetti fratelli, ti ringrazio per il tuo supporto al nostro impegno nel 
rendere la
+conoscenza umana disponibile per tutti. La tua donazione rende il mondo un 
posto migliore.
+Grazie.</p>
+
+<p>La maggior parte delle persone non sa che Wikipedia funziona come 
un'associazione no
+profit. Magari potresti occuparti di diffondere questa e-mail a qualche tuo 
amico per
+incoraggiare anche loro ad effettuare una donazione. E se sei interessato, 
puoi provare tu
+stesso ad aggiungere qualche nuova informazione a Wikipedia. Se trovi un 
refuso o qualche
+piccolo errore, correggilo; se trovi qualche informazione mancante, 
aggiungila.</p>
+
+<p>Apprezzo molto la fiducia che ci hai accordato, e prometto che utilizzeremo 
il tuo
+denaro al meglio.</p>
+
+<p>Grazie,<br />
+Sue</p>
+
+<br />
+<p>Sue Gardner<br />
+Direttore esecutivo,<br />
+Fondazione Wikimedia</p>
+
+<p>Per le tue registrazioni: La tua donazione il {{contribution.receive_date}} 
è stata
+{{contribution.contribution_source|l10n_currency(locale)}}.{% if recurring 
%}{% include
+'recurring/it.html' ignore missing %}{% endif %}</p>
+
+<p>Questa lettera può servire come prova della tua donazione. Nessun bene o 
servizio è
+stato fornito, in tutto o in parte, per questo contributo. La Wikimedia 
Foundation, Inc.
+è un'organizzazione no profit di beneficenza con esenzione fiscale negli Stati 
Uniti. Il
+nostro indirizzo è 149 New Montgomery, 3rd Floor, San Francisco, CA, 94105. 
Numero di
+esenzione fiscale (Stati Uniti): 20-0049703</p>
+
+<p>Puoi seguirci su <a href="https://twitter.com/Wikipedia";>Twitter</a>, <a
+href="https://identi.ca/wikipedia";>identi.ca</a> o <a
+href="https://plus.google.com/+Wikipedia/posts";>Google+</a>, mettere un "mi 
piace" su <a
+href="https://www.facebook.com/wikipedia";>Facebook</a> e leggere <a
+href="https://blog.wikimedia.org";>il nostro blog</a>. Di seguito puoi trovare: 
il <a
+href="https://wikimediafoundation.org/wiki/Annual_Report";>Rapporto annuale 
2010/2011 della
+Wikimedia Foundation</a>, il <a
+href="http://upload.wikimedia.org/wikipedia/foundation/4/4f/2012-13_Wikimedia_Foundation_Plan_FINAL_FOR_WEBSITE.pdf";>Piano
+annuale 2012/2013 della Wikimedia Foundation</a> e il <a
+href="https://wikimediafoundation.org/wiki/Wikimedia_Movement_Strategic_Plan_Summary";>Piano
+strategico quinquennale della Wikimedia Foundation</a>. Puoi anche comprare 
merchandise di
+Wikipedia su <a href="https://shop.wikimedia.org";>shop.wikimedia.org</a>.</p>
+
+<div style="padding:0 10px 5px 10px; border:1px solid black;">
+
+<p><i>Disiscrizione</i></p>
+
+<p>In quanto donatore, saremmo felici di aggiornarti sulle attività della 
comunità e le
+raccolte fondi. Se però preferisci non ricevere questo genere di email, clicca 
sul link
+sottostante e il tuo nominativo sarà prontamente cancellato dalla lista.</p>
+
+<a style="padding-left: 25px;" href="{{unsubscribe_link|raw}}">Unsubscribe | 
Non sottoscrivere</a>
+
+</div>
+
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/tests/templates/txt/thank_you.it.txt
 
b/sites/all/modules/wmf_common/wmf_communication/tests/templates/txt/thank_you.it.txt
new file mode 100644
index 0000000..a87b2aa
--- /dev/null
+++ 
b/sites/all/modules/wmf_common/wmf_communication/tests/templates/txt/thank_you.it.txt
@@ -0,0 +1,91 @@
+
+
+       Caro {{contact.first_name}}, 
+
+       Grazie per la tua donazione alla Wikimedia Foundation. È stata
+davvero apprezzata di cuore! 
+
+       È facile ignorare i nostri banner, perciò sono davvero felice che tu
+non l'abbia fatto. È così che Wikipedia paga le proprie bollette: persone
+come te che donano un po' del loro denaro per permetterci di mantenere
+questo sito disponibile gratuitamente in tutto il mondo. 
+
+       Molte persone mi hanno detto che donano a Wikipedia perché lo
+considerano un atto utile, e si fidano del progetto anche se non è perfetto,
+perché è scritto per loro. Wikipedia non è fatta per supportare una qualche
+agenzia di pubbliche relazioni o una particolare ideologia, né cerca di
+persuadere le persone a credere in qualcosa che non sia vero. Il nostro
+obiettivo è dire la verità, e lo possiamo fare grazie a te. Il tuo supporto
+economico al sito ci permette di restare indipendenti e di fornirti ciò di cui
+hai bisogno e ciò che vuoi da Wikipedia. Esattamente come è giusto che
+sia. 
+
+       È necessario che tu sappia che la tua donazione non copre solamente i
+costi correlati al tuo uso del progetto. Il donatore medio copre i costi
+del proprio utilizzo ma anche per quello di migliaia di altre persone. La
+tua donazione rende Wikipedia utilizzabile da tutti: un'ambiziosa bambina
+di Bangalore che sta imparando da autodidatta a programmare al computer;
+una casalinga di mezza età di Vienna alla quale è stato appena
+diagnosticato il morbo di Parkinson; un romanziere che sta studiando la 
letteratura
+britannica di metà Ottocento; un bambino salvadoregno di dieci anni che ha
+appena scoperto Carl Sagan. 
+
+       A nome di queste persone e del mezzo miliardo di altri lettori di
+Wikipedia e i suoi progetti fratelli, ti ringrazio per il tuo supporto al
+nostro impegno nel rendere la conoscenza umana disponibile per tutti. La tua
+donazione rende il mondo un posto migliore. Grazie. 
+
+       La maggior parte delle persone non sa che Wikipedia funziona come
+un'associazione no profit. Magari potresti occuparti di diffondere questa 
e-mail a
+qualche tuo amico per incoraggiare anche loro ad effettuare una donazione. E
+se sei interessato, puoi provare tu stesso ad aggiungere qualche nuova
+informazione a Wikipedia. Se trovi un refuso o qualche piccolo errore, 
correggilo;
+se trovi qualche informazione mancante, aggiungila. 
+
+       Apprezzo molto la fiducia che ci hai accordato, e prometto che
+utilizzeremo il tuo denaro al meglio. 
+
+       Grazie,
+ Sue 
+
+       Sue Gardner
+ Direttore esecutivo,
+ Fondazione Wikimedia 
+
+       Per le tue registrazioni: La tua donazione il
+{{contribution.receive_date}} è stata 
{{contribution.contribution_source|l10n_currency(locale)}}.{%
+if recurring %}{% include 'recurring/it.html' ignore missing %}{% endif
+%} 
+
+       Questa lettera può servire come prova della tua donazione. Nessun
+bene o servizio è stato fornito, in tutto o in parte, per questo
+contributo. La Wikimedia Foundation, Inc. è un'organizzazione no profit di
+beneficenza con esenzione fiscale negli Stati Uniti. Il nostro indirizzo è 149
+New Montgomery, 3rd Floor, San Francisco, CA, 94105. Numero di esenzione
+fiscale (Stati Uniti): 20-0049703 
+
+       Puoi seguirci su Twitter [1], identi.ca [2] o Google+ [3], mettere un
+"mi piace" su Facebook [4] e leggere il nostro blog [5]. Di seguito puoi
+trovare: il Rapporto annuale 2010/2011 della Wikimedia Foundation [6], il
+Piano annuale 2012/2013 della Wikimedia Foundation [7] e il Piano
+strategico quinquennale della Wikimedia Foundation [8]. Puoi anche comprare
+merchandise di Wikipedia su shop.wikimedia.org [9].  
+
+       _Disiscrizione_ 
+
+       In quanto donatore, saremmo felici di aggiornarti sulle attività
+della comunità e le raccolte fondi. Se però preferisci non ricevere questo
+genere di email, clicca sul link sottostante e il tuo nominativo sarà
+prontamente cancellato dalla lista. Unsubscribe | Non sottoscrivere [10] 
+
+
+[1] https://twitter.com/Wikipedia
+[2] https://identi.ca/wikipedia
+[3] https://plus.google.com/+Wikipedia/posts
+[4] https://www.facebook.com/wikipedia
+[5] https://blog.wikimedia.org
+[6] https://wikimediafoundation.org/wiki/Annual_Report
+[7] 
http://upload.wikimedia.org/wikipedia/foundation/4/4f/2012-13_Wikimedia_Foundation_Plan_FINAL_FOR_WEBSITE.pdf
+[8] 
https://wikimediafoundation.org/wiki/Wikimedia_Movement_Strategic_Plan_Summary
+[9] https://shop.wikimedia.org
+[10] {{unsubscribe_link|raw}}
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.info
 
b/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.info
new file mode 100644
index 0000000..ba832e7
--- /dev/null
+++ 
b/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.info
@@ -0,0 +1,6 @@
+name = WMF Communication Test Cases
+description = Simpletests
+package = Wikimedia
+core = 7.x
+dependencies[] = wmf_communication
+files[] = Job.test
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.module
 
b/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.module
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ 
b/sites/all/modules/wmf_common/wmf_communication/tests/wmf_communication_tests.module
@@ -0,0 +1 @@
+<?php
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.drush.inc 
b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.drush.inc
new file mode 100644
index 0000000..7fb2403
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.drush.inc
@@ -0,0 +1,30 @@
+<?php
+
+function wmf_communication_drush_command()
+{
+    $items = array(
+        'wmf-send-letters' => array(
+            'description' => 'Run a prepared mailing job',
+            'arguments' => array(
+                'job' => 'Job id',
+            ),
+            'required-arguments' => true,
+        ),
+    );
+
+    return $items;
+}
+
+function wmf_communication_drush_help($section)
+{
+    switch ($section) {
+    case 'drush:wmf-send-letters':
+        return dt('Run a prepared mailing job.');
+    }
+}
+
+function drush_wmf_communication_wmf_send_letters()
+{
+    $options = drush_get_arguments();
+    module_invoke('wmf_communication', 'send_letters', $options[1] );
+}
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.info 
b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.info
index 727c368..921affd 100644
--- a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.info
+++ b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.info
@@ -3,3 +3,10 @@
 core = 7.x
 package = Wikimedia
 dependencies[] = wmf_common
+dependencies[] = wmf_civicrm
+files[] = Job.php
+files[] = Mailer.php
+files[] = MailingTemplate.php
+files[] = Recipient.php
+files[] = Templating.php
+files[] = Translation.php
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.install 
b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.install
new file mode 100644
index 0000000..b91f750
--- /dev/null
+++ b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.install
@@ -0,0 +1,67 @@
+<?php
+
+function wmf_communication_schema() {
+    $schema['wmf_communication_job'] = array(
+        'description' => 'Specification of mail job',
+        'fields' => array(
+            'id' => array(
+                'type' => 'serial',
+                'unsigned' => true,
+                'not null' => true,
+            ),
+            'template_class' => array(
+                'type' => 'varchar',
+                'length' => 128,
+                'not null' => true,
+            ),
+        ),
+        'primary key' => array('id'),
+        'indexes' => array(
+            'job_template' => array('template_class'),
+        ),
+    );
+
+    $schema['wmf_communication_recipient'] = array(
+        'description' => 'Record linking contact and mail job',
+        'fields' => array(
+            'contact_id' => array(
+                'type' => 'int',
+                'unsigned' => true,
+                'not null' => true,
+            ),
+            'job_id' => array(
+                'type' => 'int',
+                'unsigned' => true,
+                'not null' => true,
+            ),
+            'status' => array(
+                'type' => 'varchar',
+                'length' => 32,
+            ),
+            'vars' => array(
+                'description' => 'Extra parameters to pass during template 
rendering, specific to this contact.  Stored as JSON.',
+                'type' => 'text',
+                #'serialize' => true,
+            ),
+        ),
+        'indexes' => array(
+            'recipient_status' => array('status'),
+            'recipient_job' => array('job_id'),
+        ),
+        'unique keys' => array(
+            'recipient_contact_job' => array('contact_id', 'job_id'),
+        ),
+        'foreign keys' => array(
+            'recipient_job' => array(
+                'table' => 'wmf_communication_job',
+                'columns' => array('job_id' => 'id'),
+            ),
+            'recipient_contact' => array(
+                'table' => 'civicrm.civicrm_contact',
+                'columns' => array('contact_id' => 'id'),
+            ),
+        ),
+    );
+
+    return $schema;
+}
diff --git 
a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.module 
b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.module
index 918dec1..8876c00 100644
--- a/sites/all/modules/wmf_common/wmf_communication/wmf_communication.module
+++ b/sites/all/modules/wmf_common/wmf_communication/wmf_communication.module
@@ -1,5 +1,15 @@
 <?php
 
+# oh well, Drupal's registry won't do namespaces until d8.
+require_once 'Job.php';
 require_once 'Mailer.php';
+require_once 'MailingTemplate.php';
+require_once 'Recipient.php';
 require_once 'Templating.php';
 require_once 'Translation.php';
+
+use wmf_communication\Job;
+
+function wmf_communication_send_letters( $jobId ) {
+    Job::getJob( $jobId )->run();
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/74305
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I36cd21a1bff531931565e1248e8c39edd0a066c4
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/crm
Gerrit-Branch: master
Gerrit-Owner: Adamw <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to