function display($self_link) {
        $this->self_link = $self_link;

        #print "<pre>"; print_r($_POST); print "</pre>";
        $view = get_http_var('view', 'needattention');
        $id = get_http_var("id");
        $rep_id = get_http_var("rep_id");

        // Display about id
        if ($id) {
            if ($this->do_actions($id)) {
#               header("Location: ".$_SERVER['REQUEST_URI'] . "\n");
#               exit;
            }

            // Navigation bar
            $this->render_bar($view, false, $id);

            // Display general information
            print "<h2>Message id " . make_ids_links($id) . ":</h2>";

            $message = msg_admin_get_message($id);
            msg_check_error($message);
            $this->print_message($message);

            // Commands
            $form = new HTML_QuickForm('messageForm', 'post', $self_link);
            if (!get_http_var('note')) {
                $actiongroup[] = &HTML_QuickForm::createElement('text', 'notebody', null, array('size'=>30));
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'note', 'Note');
            }
            $actiongroup[] = &HTML_QuickForm::createElement('static', null, null, " <b>Action:</b>");
            if ($message['frozen']) {
                if ($message['state'] != 'error' and $message['state'] != 'failed' and $message['state'] != 'failed_closed') 
                    $actiongroup[] = &HTML_QuickForm::createElement('submit', 'error', 'Error with email');
                if ($message['state'] != 'failed' and $message['state'] != 'failed_closed')
                    $actiongroup[] = &HTML_QuickForm::createElement('submit', 'failed', 'Fail silently');
                if ($message['state'] != 'error' and $message['state'] != 'failed' and $message['state'] != 'failed_closed')
                    $actiongroup[] = &HTML_QuickForm::createElement('submit', 'thaw', 'Thaw');
            }
            else {
                if ($message['state'] != 'error' and $message['state'] != 'failed' and $message['state'] != 'failed_closed') 
                    $actiongroup[] = &HTML_QuickForm::createElement('submit', 'freeze', 'Freeze');
            }
            if ($message['no_questionnaire'])
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'yes_questionnaire', 'Allow Questionnaire');
            else
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'no_questionnaire', 'No Questionnaire');
            if ($message['state'] == 'pending')
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'ready', 'Confirm');
            elseif ($message['state'] == 'failed' || $message['state'] == 'failed_closed')
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'ready', 'Retry');

            if (!get_http_var('body'))
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'body', 'View Body');
            else
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'nobody', 'Hide Body');
            if (!get_http_var('wire_emails'))
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'wire_emails', 'View Emails');
            else
                $actiongroup[] = &HTML_QuickForm::createElement('submit', 'no_wire_emails', 'Hide Emails');
            $form->addElement('hidden', 'id', $id);
            $form->addElement('hidden', 'token', get_token());
            $form->addGroup($actiongroup, "actiongroup", "",' ', false);

            admin_render_form($form);
            print 'Similar messages: ';
            print '<a href="'
                    .  htmlspecialchars(url_new("", true, 'view', 'similarbody', 'simto', $id, 'id', null))
                    .  '">different rep</a>, ';
            print '<a href="'
                    .  htmlspecialchars(url_new("", true, 'view', 'similarbodysamerep', 'simto', $id, 'id', null))
                    .  '">same rep</a> ';

            // Links to send messages to sender
            print " Email sender: <small>";
            make_mailto_link($message['sender_email'], 
                "Your message to " . $message['recipient_name'] . " has not been sent",
                "Hi " . $message['sender_name']. ",

Unfortunately, your message to " . $message['recipient_name'] . " has not been sent. You can only use our service to write to your own elected representatives, not to representatives for other places.  Here is a full explanation as to why we have this policy:
    http://www.writetothem.com/about-qa#onlyrep

There's a copy of your message below, so you can send it another way, if you like.

-------------------------------------------------------------",
                "write-to-own-reps-only");
            make_mailto_link($message['sender_email'], 
                "Your message to " . $message['recipient_name'],
                "Hi " . $message['sender_name']. ",



-------------------------------------------------------------\n\n".
                $message['message'],
                "blank-mail-quoting-message");
            print "</small>";

            // Body text if enabled
            if (get_http_var('body')) {
                print "<h2>Body text of message (only read if you really need to)</h2>";
                print "<blockquote>";
                print nl2br(htmlspecialchars($message['message']));
                print "</blockquote>";
            }

            // Body text if enabled
            if (get_http_var('wire_emails')) {
                foreach (array('representative', 'confirm', 'confirm-reminder', 'failure', 'questionnaire', 'questionnaire-reminder') as $type) {
                    print "<h2>Wire text of email - $type</h2>";
                    $wire = msg_admin_get_wire_email($message['id'], $type);
                    if (msg_get_error($wire)) {
                        print "Error contacting queue:";
                        print_r($wire);
                    } else {
                        print "<pre>";
                        print ms_make_clickable(htmlspecialchars($wire));
                        print "</pre>";
                    }
                }
            }

            // Questionnaire answers if there are any
            if (is_array($message['questionnaires']) and count($message['questionnaires']) > 0) {
                print "<h2>Questionnaire Responses</h2>";
                foreach ($message['questionnaires'] as $q) {
                    if ($q['question_id'] == 0) {
                        print "Reply within two/three weeks:";
                    } elseif ($q['question_id'] == 1) {
                        print "First time contacted any representative:";
                    } else {
                        print $q['question_id'] . ":";
                    }
                    print " <b>" . $q['answer'] .  "</b><br>";
                }
            }
 
            // Log of what has happened to message
            $allevents = get_http_var('allevents', 0);

            print '<h2>' .
                    ($allevents
                        ? 'All events for this message'
                        : 'Important events for this message')
                    . '</h2>';

            print ($allevents
                    ? '<a href="'
                        . htmlspecialchars(url_new('', true, 'allevents', null))
                        . '">View only important events</a>'
                    : '<a href="'
                        . htmlspecialchars(url_new('', true, 'allevents', 1))
                        . '">View all events</a>');
                    
            $recents = msg_admin_message_events($id, !$allevents);
            if (msg_get_error($recents)) {
                print "Error contacting queue:";
                print_r($recents);
                $recents = array();
            }

            $this->print_events($recents);

            if (count($message['bounces']) > 0) {
                print "<h2>Bounce Messages</h2>";
                foreach ($message['bounces'] as $bounce) {
                    print "<hr>";
                    print "<blockquote>" .  nl2br(htmlspecialchars($bounce)) .  "</blockquote>";
                }
                print "<hr>";
                if ($message['state'] == 'bounce_confirm') {
                    $form = new HTML_QuickForm('bounceForm', 'post', $self_link);
                    $bouncegroup[] = &HTML_QuickForm::createElement('submit', 'error', 'Fatal Delivery Error');
                    $bouncegroup[] = &HTML_QuickForm::createElement('submit', 'bounce_wait', 'Temporary Problem');
                    $bouncegroup[] = &HTML_QuickForm::createElement('submit', 'ready', 'Fatal Delivery Error, but should retry with same details');
                    $form->addGroup($bouncegroup, "bouncegroup", "Which kind of bounce message is this?",' ', false);
                    $form->addElement('hidden', 'id', $id);
                    $form->addElement('hidden', 'token', get_token());
                    admin_render_form($form);
                }
            }
         } elseif ($view == 'statistics') {
            // Display general statistics
            $stats = msg_admin_get_stats(1);
            if (msg_get_error($stats)) {
                print "Error contacting queue:";
                print_r($stats);
            }

            $freq_referrers_day = msg_admin_get_popular_referrers(60 * 60 * 24);
            if (msg_get_error($freq_referrers_day)) {
                print "Error contacting queue:";
                print_r($freq_referrers_day);
            }

            $freq_referrers_week = msg_admin_get_popular_referrers(60 * 60 * 24 * 7);
            if (msg_get_error($freq_referrers_week)) {
                print "Error contacting queue:";
                print_r($freq_referrers_week);
            }

            // Navigation bar
            $this->render_bar($view, false, $id);


?>
<h2>Queue statistics</h2>
<p>
<b><?=$stats["created_1"]?></b> new in last hour,
<b><?=$stats["created_24"]?></b> new in last day,
<b><?=$stats["created_168"]?></b> new in last week
<br>last fax sent <b><?=strftime('%e %b %Y, %H:%M', $stats["last_fax_time"])?></b>, 
last email sent <b><?=strftime('%e %b %Y, %H:%M', $stats["last_email_time"])?></b>
</p>
<h2>Messages in each state by type (created in last day)</h2>
<? $this->_display_state_table($stats, "day "); ?>
<h2>Messages in each state by type (created in last week)</h2>
<? $this->_display_state_table($stats, "week "); ?>
<h2>Messages in each state by type (created in last four weeks)</h2>
<? $this->_display_state_table($stats, "four "); ?>
<h2>Messages in each state by type (all time)</h2>
<? $this->_display_state_table($stats, "alltime "); ?>

<h2>Top referrers in last day</h2>
<table border=1>
<?
    foreach ($freq_referrers_day as $row) {
        if ($row[1] > 1 && $row[0] != "") {
            print "<tr><td>" . trim_url($row[0]) . "</td><td>$row[1]</td></tr>";
        }
    }
?>
</table>
<h2>Top referrers in last week</h2>
<table border=1>
<?
    foreach ($freq_referrers_week as $row) {
        if ($row[1] > 1 && $row[0] != "") {
            print "<tr><td>" . trim_url($row[0]) . "</td><td>$row[1]</td></tr>";
        }
    }
?>
</table>
<?
         } elseif ($rep_id) {
            $repinfo = dadem_get_representative_info($rep_id);
            dadem_check_error($repinfo);
            $sameperson = null;
            if ($repinfo['parlparse_person_id']) {
                $sameperson = dadem_get_same_person($repinfo['parlparse_person_id']);
                dadem_check_error($sameperson);
            }
            if (!$sameperson) 
                $sameperson = array($rep_id);
 
            $messages = array();
            $this->render_bar("rep_id", true, $id);
            $rep_ids = '';
            foreach ($sameperson as $this_rep_id) {
                $params = array('rep_id' => $this_rep_id);
                $new_messages = msg_admin_get_queue('rep_id', $params);
                if (msg_get_error($new_messages)) {
                    print "Error contacting queue:";
                    print_r($new_messages);
                    $new_messages = array();
                }
                $messages = array_merge($messages, $new_messages);
                $rep_ids = ' ' . $this_rep_id;
            }

            $by_year = array();
            foreach ($messages as $message) {
                if ($message['dispatched'])
                    $year = strftime('%Y', $message['dispatched']);
                else
                    $year = strftime('%Y', $message['created']);

                $by_year[$year][] = $message;
            }
            
            $years = array_keys($by_year);
            sort($years);
            foreach ($years as $year) {
                $year_array = $by_year[$year];
                print "<h2>Year $year for rep ids $rep_ids";
                print " (" . count($year_array) . " of them): </h2>";

                $q_by_email = array();
                $q_by_email_yes = array();
                $dispatched_by_email = array();
                $sent_by_email = array();
                $q_0_no = 0; $q_0_yes = 0;
                $q_1_no = 0; $q_1_yes = 0;
                $dispatched = 0;
                foreach ($year_array as $message) {
                    if (!array_key_exists($message['sender_email'], $q_by_email)) {
                        $q_by_email[$message['sender_email']] = 0;
                        $q_by_email_yes[$message['sender_email']] = 0;
                        $sent_by_email[$message['sender_email']] = 0;
                    }
                    $q_by_email[$message['sender_email']] += $message['questionnaire_0_no'];
                    $q_by_email[$message['sender_email']] += $message['questionnaire_0_yes'];
                    $q_by_email_yes[$message['sender_email']] += $message['questionnaire_0_yes'];
                    $q_0_no += $message['questionnaire_0_no'];
                    $q_0_yes += $message['questionnaire_0_yes'];
                    $q_1_no += $message['questionnaire_1_no'];
                    $q_1_yes += $message['questionnaire_1_yes'];
                    if ($message['dispatched'] && ($message['state'] == 'sent' || $message['state'] == 'finished')) {
                        $sent_by_email[$message['sender_email']] = $sent_by_email[$message['sender_email']] + 1;
                        $dispatched++;
                        $dispatched_by_email[$message['sender_email']] = true;
                    }
                }
                print "Dispatched: $dispatched (unique: " . count($dispatched_by_email) . ")";
                if ($q_0_yes + $q_0_no > 0) {
                    print " Responsiveness: $q_0_yes / " . ($q_0_no + $q_0_yes);
                }
                if ($q_1_yes + $q_1_no > 0) {
                    print " First time: $q_1_yes / " . ($q_1_no + $q_1_yes);
                }

                $html = '';
                foreach ($q_by_email as $email => $q_count) {
                    $sent_count = $sent_by_email[$email];
                    $q_count_yes = $q_by_email_yes[$email];
                    if ($q_count > 1 || $sent_count > 1) {
                        $html .= "<tr><td>$email</td><td>$sent_count</td><td>$q_count_yes / $q_count</td></tr>";
                    }
                }
                if ($html) {
                    print '<table border="1">';
                    print '<th>Multiple mailers</th><th>Message dispatched</th><th>Responses to first question</th>';
                    print $html;
                    print '</table>';
                } else {
                    print ' Nobody succesfully sent more than one message to this rep using same email.';
                }
                print '<p>';

                $this->print_messages($year_array, null);
            }
         } else {
            // Perform actions on checked items
            $sender_emails = array();
            $sender_full = array();
            foreach ($_POST as $k=>$v) {
                if (stristr($k, "check_")) {
                    $checkid = str_replace("check_", "", $k);
                    $this->do_actions($checkid);
                    $message = msg_admin_get_message($checkid);
                    msg_check_error($message);
                    array_push($sender_emails, $message['sender_email']);
                    array_push($sender_full, $message['sender_name'] . 
                            " &lt;" .  $message['sender_email'] . "&gt;");
                }
            }
            if (count($sender_emails) > 0) {
                print "<p><b>Email list for BCCing:</b><br>" .
                    implode(",", array_unique($sender_emails));
                print "<p><b>List of names and addresses:</b><br>" .
                    implode("<br>", array_unique($sender_full));
            }

            // Decide what message view to show
            $params = array();
            $reverse = false;
            if (stristr($view, "_rev")) {
                $view = str_replace("_rev", "", $view);
                $reverse = true;
            }
            if (get_http_var('search')) {
                $view = "search";
            }

            // Set up additional parameters for view if necessary.
            if ($view == "similarbody" || $view == 'similarbodysamerep') {
                $params['msgid'] = get_http_var('simto');
            } else if ($view == "search" || $view == "logsearch") {
                $params['query'] = get_http_var('query');
            }
            
            // Get details about view
            $messages = msg_admin_get_queue($view, $params);
            if (msg_get_error($messages)) {
                print "Error contacting queue:";
                print_r($messages);
                $messages = array();
            }

            // Navigation bar
            $this->render_bar($view, $reverse, $id);

            // Display messages
            print "<h2>Messages which";
            if ($view == "similarbody") {
                print " have similar bodies to " . make_ids_links(get_http_var('simto'));
            } elseif ($view == "similarbodysamerep") {
                print " are to the same representative and have similar bodies to " . make_ids_links(get_http_var('simto'));
            } elseif ($view == "search") {
                print " match search query '" . htmlspecialchars(get_http_var('query')) . "'";
            } elseif ($view == "logsearch") {
                print " whose log matches '" . htmlspecialchars(get_http_var('query')) . "'";
            } else {
                print " are $view";
            }
            print " (" . count($messages) . " messages): </h2>";
            if ($reverse) {
                $messages = array_reverse($messages);
            }
            $this->print_messages($messages, ($view == 'similarbody' || $view == 'similarbodysamerep') ? $params['msgid'] : null);
            if ($view == 'recentchanged' or $view == 'recentcreated')
                print "<p>..."; /* indicate that this isn't all the messages... */

            // Help
            ?>
            <h2>Help &mdash; what views/searches are there?</h2>
            <p>
            <b>Need Attention:</b> Message which are frozen, most likely
            due to possible abuse, or need bounce messages classifying.
            <br><b>Failing:</b> Messages for which delivery is failing, most like
            incorrect contact details.  Sorted by recipient.
            <br><b>Recently Created:</b> Most recent messages constituents have made.
            <br><b>Recently Changed:</b> Messages which something has happened to recently.
            <br><b>Similar to:</b> Shows messages with bodies similar to a given message.
            Click on "View similar messages" from a message page to get to this view.  Displays
            colourful diffs of the differences.
            <br><b>Contains:</b> Searches the sender details, recipient details and message
            body.  Enter multiple terms separate by spaces, all must be
            present to match.  If you query by state name ('pending') or
            representative type ('EUR') you must enter the whole word, case
            sensitive.  Otherwise queries are case insensitive.  Yes, you
            can query on the referrer URL.  If you have one, you can enter
            a confirmation or questionnaire token from an email, such as
            cqyv7yrisjugc5i5rfz4w75tmnxzi.  Examples: '<b>ready EUR</b>' - all messages to MEPs
            which are ready to be sent.  '<b>francis theyworkforyou</b>' - probably
            all messages written by someone called Francis who came to WTT via
            theyworkforyou.com.
            </p>
            <?
        }
        if ($view != "statistics") {
?>
<h2>Help &mdash; what do the buttons do?</h2>
<?
        if (!$id) {
?>
<p>They apply to all items you have checked.</p>
<?
        }
?>
<p>
<b>note</b> adds the text entered as a remark in the message's log
<br><b>freeze</b> stops delivery to representative, but other stuff
(such as confirmation message) still happens
<br><b>thaw</b> undoes a freeze, so message gets delivered.
<br><b>no questionnaire</b> makes the message one for which no questionnaire is sent.
<br><b>error with email</b> rejects a message, sending a "could not deliver" email to constituent.
<br><b>fail silently</b> rejects a message, with no email to the constituent.
<br><b>confirm</b> moves 'pending' to 'ready', the same as user clicking confirm link in email
<br><b>retry</b> moves a failed message back to 'ready', restarting the sending process
<br><b>view body</b> should only be done if you have good reason to believe it is an abuse of our service.
<br><b>edit contact details</b> by clicking on the recipient name
</p>
<p>To find out <b>state meanings</b>, point the mouse to find out what they are
</p>
<?
        if (!$id) {
        ?>
<h2>Help &mdash; what do the states mean?</h2>
<p>Here is a diagram of state changes:</p>
<p><img src="queue-state-machine.png"></p>

<p>Description of states in the normal lifetime of a message:</p>

<dl>
<dt>new</dt>
<dd>The message has been created by the user but it has not yet been sent to
them for confirmation.</dd>

<dt>pending</dt>
<dd>The message has been sent to the user but not confirmed yet. A reminder
copy of the message is sent if the user does not confirm it within a day.</dd>

<dt>ready</dt>
<dd>The message has been confirmed by the user but it has not yet been
successfully sent; <em>or</em> it has been sent by email but encountered a
fatal bounce for a transient error condition (such as the recipient's mailbox
being full).</dd>

<dt>bounce_wait <em>email only</em></dt>
<dd>The message has been sent, but we hang on to it for a little while in case
a bounce message arrives. Bounce messages are either automatically classified
(where they meet the RFC1892 standard for delivery status notifications) or
passed into the bounce_confirm state for manual classification.</dd>

<dt>sent</dt>
<dd>The message has been sent (and, in case of an email, no bounce message has
arrived within the set time). This is the state in which the questionnaire and
questionnaire reminder are sent.</dd>

<dt>finished</dt>
<dd>All our processing of the message has completed successfully.</dd>
</dl>

</dl>

        <?
        }
        }
    }
Example #2
0
 function display($self_link)
 {
     // Input data
     $rep_id = get_http_var('rep_id');
     $va_id = get_http_var('va_id');
     $ds_va_id = get_http_var('ds_va_id');
     $bad_contacts = get_http_var('bad_contacts');
     $user_corrections = get_http_var('user_corrections');
     // Make new rep in this voting area
     $new_in_va_id = get_http_var('new_in_va_id');
     if (!$rep_id && $ds_va_id) {
         // Democratic services
         $ds_vainfo = dadem_get_representatives($ds_va_id);
         dadem_check_error($ds_vainfo);
         if (isset($ds_vainfo[0])) {
             $rep_id = $ds_vainfo[0];
         } else {
             $new_in_va_id = $ds_va_id;
         }
     }
     // Postcode
     $pc = get_http_var('pc');
     // Search
     $search = null;
     if (get_http_var('gos')) {
         if (validate_postcode(get_http_var('search'))) {
             $pc = get_http_var('search');
             $rep_id = null;
         } else {
             $search = get_http_var('search');
             $rep_id = null;
         }
     }
     if (get_http_var('cancel') != "") {
         $rep_id = null;
     }
     if (get_http_var('done') != "") {
         if (get_http_var('token') != $this->get_token()) {
             print "<p><i>Token not found</i></p>";
         } else {
             $newdata['name'] = get_http_var('name');
             $newdata['party'] = get_http_var('party');
             $newdata['method'] = get_http_var('method');
             $newdata['email'] = get_http_var('email');
             $newdata['fax'] = get_http_var('fax');
             if (!$rep_id) {
                 // Making a new representative, put in type and id
                 $newdata['area_id'] = $new_in_va_id;
                 $vainfo = mapit_call('area', $new_in_va_id);
                 mapit_check_error($vainfo);
                 $newdata['area_type'] = $vainfo['type'];
             }
             $result = dadem_admin_edit_representative($rep_id, $newdata, http_auth_user(), get_http_var('note'));
             dadem_check_error($result);
             $rep_id = $result;
             $new_in_va_id = null;
             print "<p><i>Successfully updated representative " . htmlspecialchars($rep_id) . "</i></p>";
             if (get_http_var('nextbad')) {
                 $rep_id = get_http_var('nextbad');
                 $url = $self_link . "&nextbad=" . urlencode($this->get_next_bad_contact($rep_id)) . "&just_done_bad=1&rep_id=" . urlencode($rep_id);
                 header("Location: {$url}");
                 exit;
             } else {
                 $rep_id = null;
             }
         }
     }
     if (get_http_var('just_done_bad')) {
         print "<p><i>Moved on to next bad contact</i></p>";
     }
     if (get_http_var('delete') != "") {
         if (get_http_var('token') != $this->get_token()) {
             print "<p><i>Token not found</i></p>";
         } else {
             $result = dadem_admin_edit_representative($rep_id, null, http_auth_user(), get_http_var('note'));
             dadem_check_error($result);
             print "<p><i>Successfully deleted representative " . htmlspecialchars($rep_id) . "</i></p>";
             $rep_id = null;
         }
     }
     if (get_http_var('ucclose') != "") {
         $result = dadem_admin_done_user_correction(get_http_var('ucid'));
         dadem_check_error($result);
         print "<p><i>Successfully closed correction " . htmlspecialchars(get_http_var('ucid')) . "</i></p>";
     }
     if (get_http_var('vaupdate') != "") {
         $result = dadem_admin_set_area_status(get_http_var('va_id'), get_http_var('new_status'));
         dadem_check_error($result);
         print "<p><i>Successfully updated voting area status " . htmlspecialchars(get_http_var('va_id')) . " to " . htmlspecialchars(get_http_var('new_status')) . "</i></p>";
     }
     // Postcode and search box
     $form = new HTML_QuickForm('adminRepsSearchForm', 'get', $self_link);
     $form->addElement('header', '', 'Search');
     $buttons[] =& HTML_QuickForm::createElement('text', 'search', null, array('size' => 20, 'maxlength' => 255));
     $buttons[] =& HTML_QuickForm::createElement('submit', 'gos', 'postcode or query');
     $form->addElement('hidden', 'page', $this->id);
     $form->addGroup($buttons, 'stuff', null, '&nbsp', false);
     admin_render_form($form);
     // Conditional parts:
     if ($rep_id or $new_in_va_id) {
         $form = new HTML_QuickForm('adminRepsEditForm', 'post', $self_link);
         $form->addElement('hidden', 'page', $this->id);
         $form->addElement('hidden', 'token', $this->get_token());
         // Edit representative
         $sameperson = null;
         if ($rep_id) {
             $repinfo = dadem_get_representative_info($rep_id);
             dadem_check_error($repinfo);
             if ($repinfo['parlparse_person_id']) {
                 $sameperson = dadem_get_same_person($repinfo['parlparse_person_id']);
                 dadem_check_error($sameperson);
             }
         }
         $va_id = $rep_id ? $repinfo['voting_area'] : $new_in_va_id;
         $vainfo = mapit_call('area', $va_id);
         mapit_check_error($vainfo);
         if ($vainfo['parent_area']) {
             $parentinfo = mapit_call('area', $vainfo['parent_area']);
             mapit_check_error($parentinfo);
         } else {
             $parentinfo = null;
         }
         $rephistory = $rep_id ? dadem_get_representative_history($rep_id) : array();
         dadem_check_error($rephistory);
         // Reverse postcode lookup
         if (!$pc) {
             $pc = mapit_call('area/example_postcode', $va_id);
             if (!mapit_get_error($pc)) {
                 $form->addElement('static', 'note1', null, "Example postcode for testing: " . "<a href='" . OPTION_BASE_URL . '/who?pc=' . urlencode($pc) . "'>" . htmlentities($pc) . "</a> (<a href='?search=" . urlencode($pc) . "&amp;gos=postcode+or+query&amp;page=reps'>all reps here</a>)");
             } else {
                 $pc = '';
             }
         }
         if ($rep_id) {
             $form->setDefaults(array('name' => $repinfo['name'], 'party' => $repinfo['party'], 'method' => $repinfo['method'], 'email' => $repinfo['email'], 'fax' => $repinfo['fax']));
         }
         // Councillor types are not edited here, but in match.cgi interface
         global $va_council_child_types, $va_type_name, $va_rep_name;
         $editable_here = true;
         if (OPTION_ADMIN_SERVICES_CGI && in_array($vainfo['type'], $va_council_child_types)) {
             $editable_here = false;
         }
         $readonly = $editable_here ? null : "readonly";
         if ($rep_id) {
             $form->addElement('header', '', 'Edit Representative');
             if ($repinfo['deleted']) {
                 $form->addElement('static', 'notedeleted', null, "<strong style=\"color: red\">Deleted representative</strong>, click 'Done' to undelete");
             }
         } else {
             $form->addElement('header', '', 'New Representative');
         }
         if ($rep_id and $editable_here) {
             $form->addElement('static', 'note1', null, "\n                Edit only the values which you need to.  If a representative\n                has changed delete them and make a new one.  Do not just edit\n                their values, as this would ruin our reponsiveness stats.");
         }
         if ($rep_id && $sameperson) {
             $html = '';
             foreach ($sameperson as $samerep) {
                 if ($samerep == $rep_id) {
                     continue;
                 }
                 $html .= "<a href=\"{$self_link}&pc=" . urlencode(get_http_var('pc')) . "&rep_id=" . $samerep . "\">" . $samerep . "</a> \n";
             }
             if ($html) {
                 $html = '(Note that these other representatives are the same person: ' . trim($html) . ')';
                 $form->addElement('static', 'sameperson', null, $html);
             }
         }
         $rep_name = isset($va_rep_name[$vainfo['type']]) ? $va_rep_name[$vainfo['type']] : '';
         $form->addElement('static', 'office', 'Office:', htmlspecialchars($rep_name) . " for " . htmlspecialchars($vainfo['name']) . " " . htmlspecialchars($va_type_name[$vainfo['type']]) . ($parentinfo ? " in " . htmlspecialchars($parentinfo['name']) . " " . htmlspecialchars($va_type_name[$parentinfo['type']]) : ""));
         $form->addElement('text', 'name', "Full name:", array('size' => 60, $readonly => 1));
         $form->addElement('text', 'party', "Party:", array('size' => 60, $readonly => 1));
         $form->addElement('static', 'note2', null, "Make sure you update contact method when you change email or fax numbers.");
         $form->addElement('select', 'method', "Contact method:", array('fax' => 'Fax only', 'email' => 'Email only', 'shame' => "Shame! Doesn't want contacting", 'via' => 'Contact via electoral body (e.g. Democratic Services)', 'unknown' => "We don't know contact details"));
         $form->addElement('text', 'email', "Email:", array('size' => 60, $readonly => 1));
         $form->addElement('text', 'fax', "Fax:", array('size' => 60, $readonly => 1));
         $form->addElement('textarea', 'note', "Notes for log:", array('rows' => 3, 'cols' => 60, $readonly => 1));
         $form->addElement('hidden', 'pc', $pc);
         if (get_http_var('nextbad')) {
             $form->addElement('hidden', 'nextbad', get_http_var('nextbad'));
         }
         if ($rep_id) {
             $form->addElement('hidden', 'rep_id', $rep_id);
         } else {
             $form->addElement('hidden', 'new_in_va_id', $new_in_va_id);
         }
         if ($editable_here) {
             $finalgroup[] =& HTML_QuickForm::createElement('submit', 'done', 'Done');
             $finalgroup[] =& HTML_QuickForm::createElement('submit', 'cancel', 'Cancel');
             if ($rep_id) {
                 $finalgroup[] =& HTML_QuickForm::createElement('static', 'newlink', null, "<a href=\"{$self_link}&pc=" . urlencode(get_http_var('pc')) . "&new_in_va_id=" . $va_id . "\">" . "Make new " . htmlspecialchars($vainfo['name']) . " rep" . "</a> \n");
                 if ($repinfo['deleted']) {
                     $finalgroup[] =& HTML_QuickForm::createElement('static', 'staticspacer', null, '&nbsp; Deleted rep, no longer in office, just click done to undelete');
                 } else {
                     $finalgroup[] =& HTML_QuickForm::createElement('static', 'staticspacer', null, '&nbsp; No longer in office? --->');
                     $finalgroup[] =& HTML_QuickForm::createElement('submit', 'delete', 'Delete');
                 }
             }
             $form->addGroup($finalgroup, "finalgroup", "", ' ', false);
         } else {
             $form->addElement('static', 'note3', null, '<a href="' . OPTION_ADMIN_SERVICES_CGI . 'match.cgi?page=councilinfo;area_id=' . $vainfo['parent_area'] . '">To edit Councillors please use the match.cgi interface</a>' . '<br><a href="' . $self_link . '&ds_va_id=' . $vainfo['parent_area'] . '">... or edit Democratic Services for this council</a>');
             $finalgroup[] =& HTML_QuickForm::createElement('submit', 'done', 'Done');
             $finalgroup[] =& HTML_QuickForm::createElement('submit', 'cancel', 'Cancel');
             $form->addGroup($finalgroup, "finalgroup", "", ' ', false);
         }
         if ($rep_id) {
             $search_links = "Search for: ";
             $search_links .= "<a href=\"{$self_link}&page=fyrqueue&rep_id=" . $rep_id . "\">WriteToThem messages</a> | ";
             foreach (array("tel " . $repinfo['name'], "fax " . $repinfo['name'], "tel " . $repinfo['name'] . " " . $rep_name, "fax " . $repinfo['name'] . " " . $rep_name) as $searchq) {
                 $search_links .= "<a href=\"http://search.yahoo.com/search?p=" . htmlspecialchars($searchq) . "\"> " . htmlspecialchars($searchq) . "</a> | ";
             }
             $form->addElement('static', 'newlink', null, $search_links);
             if ($repinfo['parlparse_person_id']) {
                 $form->addElement('static', 'person', 'parlparse person_id:', $repinfo['parlparse_person_id']);
             }
         }
         $form->addElement('header', '', 'Historical Changes');
         $html = "<table border=1>";
         $html .= "<th>Order</th><th>Date</th><th>Editor</th><th>Note</th>\n                <th>Name</th> <th>Party</th> <th>Method</th> <th>Email</th>\n                <th>Fax</th><th>Active</th>";
         $previous_row = null;
         foreach ($rephistory as $row) {
             $html .= "<tr>";
             foreach (array('order_id', 'whenedited', 'editor', 'note', 'name', 'party', 'method', 'email', 'fax', 'deleted') as $field) {
                 if ($row['deleted'] && ($field == 'email' || $field == 'fax' || $field == 'method')) {
                     $display_value = 'deleted';
                     $html .= "<td>-</td>\n";
                     continue;
                 }
                 $value = $row[$field];
                 if ($field == 'note') {
                     $display_value = make_ids_links($value);
                 } elseif ($field == 'whenedited') {
                     $display_value = strftime('%Y-%m-%d %H:%M:%S', $value);
                 } elseif ($field == 'deleted') {
                     $display_value = $value ? 'deleted' : 'yes';
                 } else {
                     $display_value = $value;
                 }
                 if ($field != "order_id" && $field != "whenedited" && $field != "editor" && $field != "note" && $previous_row && $previous_row[$field] != $value) {
                     $display_value = "<strong>{$display_value}</strong>";
                 }
                 # Try and spot stupidity
                 if (preg_match('#parl(i|a)ment#', $display_value)) {
                     $display_value = "<span style='color:#00ff00'>{$display_value}</span>";
                 }
                 $html .= "<td>" . $display_value . "</td>\n";
             }
             $html .= "</tr>";
             $previous_row = $row;
         }
         $html .= "</table>";
         $form->addElement('static', 'bytype', null, $html);
         admin_render_form($form);
     } elseif ($va_id) {
         // One voting area
         $form = new HTML_QuickForm('adminVotingArea', 'get', $self_link);
         $area_info = mapit_call('area', $va_id);
         mapit_check_error($area_info);
         $reps = dadem_get_representatives($va_id);
         dadem_check_error($reps);
         $reps = array_values($reps);
         $html = $this->render_area($self_link, $va_id, $area_info, $pc);
         $html .= $this->render_reps($self_link, $reps);
         $form->addElement('static', 'bytype', null, $html);
         $form->addElement('hidden', 'page', $this->id);
         $form->addElement('hidden', 'token', $this->get_token());
         $form->addElement('hidden', 'va_id', $va_id);
         $select = $form->addElement('select', 'new_status', null, array('none' => 'No special status', 'pending_election' => 'Pending election, rep data not valid', 'recent_election' => 'Recent election, our rep data not yet updated', 'boundary_changes' => 'Recent election, had boundary changes'), array());
         $status = dadem_get_area_status($va_id);
         dadem_check_error($status);
         $select->setSelected($status);
         $form->addElement('submit', 'vaupdate', 'Update');
         admin_render_form($form);
     } elseif ($search) {
         $form = new HTML_QuickForm('adminRepsSearchResults', 'get', $self_link);
         $html = '';
         $areas = mapit_call('areas', $search);
         mapit_check_error($areas);
         global $va_inside;
         foreach (array_keys($areas) as $va_id) {
             $area_info = mapit_call('area', $va_id);
             mapit_check_error($area_info);
             $reps = dadem_get_representatives($va_id);
             dadem_check_error($reps);
             $reps = array_values($reps);
             $html .= $this->render_area($self_link, $va_id, $area_info, $pc, isset($va_inside[$area_info['type']]));
             $html .= $this->render_reps($self_link, $reps);
         }
         // Search reps
         $reps = dadem_search_representatives($search);
         dadem_check_error($reps);
         $html .= '<hr>' . $this->render_reps($self_link, $reps);
         $form->addElement('static', 'bytype', null, $html);
         admin_render_form($form);
     } elseif ($pc) {
         $form = new HTML_QuickForm('adminRepsSearchResults', 'get', $self_link);
         // Postcode search
         $voting_areas = mapit_call('postcode', $pc);
         mapit_check_error($voting_areas);
         $areas_info = $voting_areas['areas'];
         $html = "";
         // Display in order council, ward, council, ward...
         global $va_display_order, $va_inside;
         $our_order = array();
         foreach ($va_display_order as $row) {
             if (!is_array($row)) {
                 $row = array($row);
             }
             if (!in_array($va_inside[$row[0]], $our_order)) {
                 $our_order[] = $va_inside[$row[0]];
             }
             foreach ($row as $va_type) {
                 $our_order[] = $va_type;
             }
         }
         // Render everything in the order
         foreach ($our_order as $va_type) {
             foreach ($areas_info as $area => $area_info) {
                 if ($va_type != $area_info['type']) {
                     continue;
                 }
                 $va_id = $area;
                 // One voting area
                 $reps = dadem_get_representatives($va_id);
                 dadem_check_error($reps);
                 $reps = array_values($reps);
                 $html .= $this->render_area($self_link, $va_id, $area_info, $pc, isset($va_inside[$va_type]));
                 $html .= $this->render_reps($self_link, $reps);
             }
         }
         $form->addElement('static', 'bytype', null, $html);
         admin_render_form($form);
     } elseif ($bad_contacts) {
         // Bad contacts
         $form = new HTML_QuickForm('adminRepsBad', 'post', $self_link);
         $badcontacts = dadem_get_bad_contacts();
         dadem_check_error($badcontacts);
         $form->addElement('header', '', 'Bad Contacts ' . count($badcontacts));
         $html = $this->render_reps($self_link, $badcontacts, true);
         $form->addElement('static', 'badcontacts', null, $html);
         admin_render_form($form);
     } elseif ($user_corrections) {
         // User submitted corrections
         $form = new HTML_QuickForm('adminRepsCorrectionsHeader', 'post', $self_link);
         $corrections = dadem_get_user_corrections();
         dadem_check_error($corrections);
         $form->addElement('header', '', 'User Submitted Corrections ' . count($corrections));
         $form->addElement('hidden', 'token', $this->get_token());
         admin_render_form($form);
         // Get all the data for areas and their parents in as few call as possible
         $vaids = array();
         foreach ($corrections as $correction) {
             array_push($vaids, $correction['voting_area_id']);
         }
         $info1 = mapit_call('areas', $vaids);
         mapit_check_error($info1);
         $vaids = array();
         foreach ($info1 as $key => $value) {
             array_push($vaids, $value['parent_area']);
         }
         $info2 = mapit_call('areas', $vaids);
         foreach ($corrections as $correction) {
             $form = new HTML_QuickForm('adminRepsCorrections', 'post', $self_link);
             $html = "";
             $rep = $correction['representative_id'];
             $html .= "<p>";
             $html .= strftime('%Y-%m-%d %H:%M:%S', $correction['whenentered']) . " ";
             if ($correction['user_email']) {
                 $html .= " by " . htmlspecialchars($correction['user_email']);
             }
             $html .= "<br>";
             if ($correction['voting_area_id']) {
                 $wardinfo = $info1[$correction['voting_area_id']];
                 $vaid = $wardinfo['parent_area'];
                 $vainfo = $info2[$vaid];
                 // TODO: Make this councilinfo, and give a valid r= return URL
                 $html .= '<a href="' . OPTION_ADMIN_SERVICES_CGI . 'match.cgi?page=councilinfo;area_id=' . $vaid . '&r=' . '">' . htmlspecialchars($vainfo['name']) . "</a>, ";
                 $html .= htmlspecialchars($wardinfo['name']);
                 $html .= "<br>";
             }
             $html .= $correction['alteration'] . " ";
             if ($rep) {
                 $repinfo = dadem_get_representative_info($rep);
                 dadem_check_error($repinfo);
                 $html .= "<a href=\"{$self_link}&pc=" . urlencode(get_http_var('pc')) . "&rep_id=" . $rep . "\">" . htmlspecialchars($repinfo['name']) . " (" . htmlspecialchars($repinfo['party']) . ")</a> \n";
                 if ($correction['alteration'] != "delete") {
                     $html .= " to ";
                 }
             }
             if ($correction['alteration'] != "delete") {
                 $html .= htmlspecialchars($correction['name']) . " (" . htmlspecialchars($correction['party']) . ")";
             }
             if ($correction['user_notes']) {
                 $html .= "<br>Notes: " . htmlspecialchars($correction['user_notes']);
             }
             $usercorr = array();
             $usercorr[] =& HTML_QuickForm::createElement('static', 'usercorrections', null, $html);
             // You can't do this with element type "hidden" as it only allows one value in a
             // page for variable named ucid.  So once again I go to raw HTML.  Remind me not
             // to use HTML_QuickForm again...
             $usercorr[] =& HTML_QuickForm::createElement('html', '<input name="ucid" type="hidden" value="' . $correction['user_correction_id'] . '" />');
             $usercorr[] =& HTML_QuickForm::createElement('submit', 'ucclose', 'hide (done)');
             $form->addGroup($usercorr, 'stuff', null, '&nbsp', false);
             admin_render_form($form);
         }
     } else {
         print '<p><a href="?page=reps&bad_contacts=1">Bad contacts</a> (please fix these!)';
         // General info
         if (OPTION_ADMIN_SERVICES_CGI) {
             print '<br><a href="?page=reps&user_corrections=1">User corrections</a> (just for your interest, as sent automatically to GovEval)';
         }
     }
 }