Add a cron which checks the best mail addresses which is stored
authorNicolas Iooss <nicolas.iooss_git@polytechnique.org>
Mon, 17 Feb 2014 21:29:38 +0000 (22:29 +0100)
committerNicolas Iooss <nicolas.iooss_git@polytechnique.org>
Wed, 19 Feb 2014 19:45:43 +0000 (20:45 +0100)
The cron script computes the selected mail address for each profile and warns
once a week if the result doesn't match the database data.

Also make Address::updateBestMail static public so that there is no need to
create an object per profile in the cron script and there is no code
duplication to find which address would be selected.

bin/cron/bestmail.check.php [new file with mode: 0755]
classes/address.php
configs/platal.cron.in

diff --git a/bin/cron/bestmail.check.php b/bin/cron/bestmail.check.php
new file mode 100755 (executable)
index 0000000..6074e73
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/php5 -q
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2014 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+/**
+ * Check that for every profile, the best postal address which is used to
+ * send mail is the right one according to a rule in Address::updateAxMail().
+ *
+ * To fix something which has been reported by this script, you only need to
+ * run "Address::updateBestMail($pid)" with $pid being the Profile ID
+ */
+
+require '../connect.db.inc.php';
+require_once '../../classes/address.php';
+
+$admin_visibility = Visibility::get(Visibility::VIEW_ADMIN);
+
+// Enumerate every profile
+$pids = XDB::iterRow("SELECT pid from profiles");
+while ($row = $pids->next()) {
+    $pid = $row[0];
+
+    // Find the address which would be selected as "AX mail"
+    // But don't update anything
+    $best_mail = Address::updateBestMail($pid, true);
+    if (is_null($best_mail)) {
+        continue;
+    }
+
+    // Just continue if the returned address is already selected
+    $flags = new PlFlagSet($best_mail['flags']);
+    if ($flags->hasFlag('dn_best_mail')) {
+        continue;
+    }
+
+    // The current profile is buggy.
+    // Let's fetch more data to print detailed information
+    $profile = Profile::get($pid);
+    $addresses = ProfileField::getForPID('ProfileAddresses', array($pid), $admin_visibility);
+    $addresses = $addresses->get(Profile::ADDRESS_POSTAL);
+
+    $old_mail = null;
+    $new_mail = null;
+    foreach ($addresses as $addr) {
+        if ($addr->flags->hasFlag('dn_best_mail')) {
+            $old_mail = $addr;
+        } else if ($addr->id == $best_mail['id']) {
+            $new_mail = $addr;
+        }
+    }
+
+    echo "Profile " . $profile->hrid() . " ($pid) has a wrongly selected best mail.\n";
+    if (is_null($old_mail)) {
+        echo "... no currently selected best mail\n";
+    } else {
+        echo "... currently selected best mail: " . $old_mail->formatted_address .
+            " (flags: " . $old_mail->flags->flags() . ", pub: " . $old_mail->pub . ")\n";
+    }
+    if (is_null($new_mail)) {
+        echo "... unable to find newly selected best mail (BUG!)\n";
+    } else {
+        echo "... best mail that would be selected: " . $new_mail->formatted_address .
+            " (flags: " . $new_mail->flags->flags() . ", pub: " . $new_mail->pub . ")\n";
+    }
+    echo "\n";
+}
+
+print "Done.\n";
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker fenc=utf-8:
+?>
index b3e9da9..2ebe8b5 100644 (file)
@@ -728,7 +728,7 @@ class Address
             }
 
             if ($this->pid != 0) {
-                $this->updateBestMail();
+                self::updateBestMail($this->pid);
             }
         }
     }
@@ -736,13 +736,19 @@ class Address
     /**
      * Upate the denormalized flag which is used to mark the best mail to use
      * when sending postal mail
+     *
+     * Call with $fake to true to only get which address would be selected,
+     * without updating anything in the database.
+     * Returns an array describing the selected profile address
      */
-    private function updateBestMail()
+    static public function updateBestMail($pid, $fake=false)
     {
-        XDB::execute("UPDATE  profile_addresses
-                         SET  flags = REPLACE(flags, 'dn_best_mail', '')
-                       WHERE  pid = {?}",
-                     $this->pid);
+        if (!$fake) {
+            XDB::execute("UPDATE  profile_addresses
+                             SET  flags = REPLACE(flags, 'dn_best_mail', '')
+                           WHERE  pid = {?}",
+                         $pid);
+        }
 
         /* Following order is selected to find the best mail:
          *  * Use addresses without the deliveryIssue flag if possible.
@@ -752,21 +758,22 @@ class Address
          *  * If there are still several addresses in the selection, try not
          *    to select the ones with "job" type.
          */
-        $best_mail = XDB::fetchOneAssoc("SELECT  pid, jobid, groupid, type, id
+        $best_mail = XDB::fetchOneAssoc("SELECT  pid, jobid, groupid, type, id, flags
                                          FROM  profile_addresses
                                         WHERE  FIND_IN_SET('mail', flags) AND pid = {?}
                                      ORDER BY  FIND_IN_SET('deliveryIssue', flags),
                                                NOT FIND_IN_SET('current', flags),
                                                FIND_IN_SET('secondary', flags), type = 'job'
                                         LIMIT  1",
-                                      $this->pid);
+                                      $pid);
 
-        if ($best_mail) {
+        if (!$fake && $best_mail) {
             XDB::execute("UPDATE  profile_addresses
                              SET  flags = CONCAT(flags, ',dn_best_mail')
                            WHERE  pid = {?} AND jobid = {?} AND groupid = {?} AND type = {?} AND id = {?}",
                          $best_mail['pid'], $best_mail['jobid'], $best_mail['groupid'], $best_mail['type'], $best_mail['id']);
         }
+        return $best_mail;
     }
 
     public function updateGeocoding($text)
index 5d6d823..82a09d2 100644 (file)
@@ -9,6 +9,7 @@ WD=/home/web/prod/platal/bin/cron
 0 20 2-31 * *   web     cd $WD; ./emails.check.php | mail -e -s "Qualite de l'annuaire"                   hotliners@staff.m4x.org
 0 20 1 * *      web     cd $WD; ./emails.check.php  -v | mail -e -s "Qualite de l'annuaire : verbeux"                   hotliners@staff.m4x.org
 0 22 * * *      web     cd $WD; ./phones.check.php > /dev/null
+0 30 * * 1      web     cd $WD; ./bestmail.check.php
 
 # inscription report
 0  6 * * 1     web     cd $WD; ./registrations.php