Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added tests for member() function, now xpath driven + tweaks

  • Loading branch information...
commit c855b249c488f5c1a69ba858cc7298dd8fbbb702 1 parent 7c7ff39
@hm2k hm2k authored
View
54 Services/Mailman.php
@@ -222,9 +222,6 @@ protected function fetch($url)
public function lists($assoc = true)
{
$html = $this->fetch($this->adminURL);
- if (!$html) {
- return false;
- }
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
@@ -237,7 +234,8 @@ public function lists($assoc = true)
if (!$count) {
throw new Services_Mailman_Exception('Failed to parse HTML.');
}
- for ($i=0;$i <= $count;$i++) {
+ $a = array();
+ for ($i=0;$i < $count;$i++) {
if ($paths->item($i)) {
$a[$i][0]=$paths->item($i)?basename($paths->item($i)->nodeValue):'';
$a[$i][1]=$names->item($i)?$names->item($i)->nodeValue:'';
@@ -254,22 +252,28 @@ public function lists($assoc = true)
}
/**
- * List a member
+ * Find a member
*
* (ie: <domain.com>/mailman/admin/<listname>/members?findmember=<email-address>
* &setmemberopts_btn&adminpw=<adminpassword>)
*
- * @param string $email A valid email address of a member to lookup
+ * @param string $string A search string for member
*
* @return string Returns unparsed HTML
*
* @throws {@link Services_Mailman_Exception}
*/
- public function member($email)
+ public function member($string)
{
+ if (!is_string($string)) {
+ throw new Services_Mailman_Exception(
+ 'member() expects parameter 1 to be string, ' .
+ gettype($string) . ' given'
+ );
+ }
$path = '/' . $this->list . '/members';
$query = array(
- 'findmember' => $email,
+ 'findmember' => $string,
'setmemberopts_btn' => null,
'adminpw' => $this->adminPW
);
@@ -277,11 +281,35 @@ public function member($email)
$query = http_build_query($query, '', '&');
$url = $this->adminURL . $path . '?' . $query;
$html = $this->fetch($url);
- if (!$html) {
- throw new Services_Mailman_Exception('Unable to fetch HTML.');
+ libxml_use_internal_errors(true);
+ $doc = new DOMDocument();
+ $doc->preserveWhiteSpace = false;
+ $doc->loadHTML($html);
+ $xpath = new DOMXPath($doc);
+ $queries = array();
+ $queries['address'] = $xpath->query('/html/body/form/center/table/tr/td[2]/a');
+ $queries['realname'] = $xpath->query('/html/body/form/center/table/tr/td[2]/input[type=TEXT]/@value');
+ $queries['mod'] = $xpath->query('/html/body/form/center/table/tr/td[3]/center/input/@value');
+ $queries['hide'] = $xpath->query('/html/body/form/center/table/tr/td[4]/center/input/@value');
+ $queries['nomail'] = $xpath->query('/html/body/form/center/table/tr/td[5]/center/input/@value');
+ $queries['ack'] = $xpath->query('/html/body/form/center/table/tr/td[6]/center/input/@value');
+ $queries['notmetoo'] = $xpath->query('/html/body/form/center/table/tr/td[7]/center/input/@value');
+ $queries['nodupes'] = $xpath->query('/html/body/form/center/table/tr/td[8]/center/input/@value');
+ $queries['digest'] = $xpath->query('/html/body/form/center/table/tr/td[9]/center/input/@value');
+ $queries['plain'] = $xpath->query('/html/body/form/center/table/tr/td[10]/center/input/@value');
+ $queries['language'] = $xpath->query('/html/body/form/center/table/tr/td[11]/center/select/option[@selected]/@value');
+ libxml_clear_errors();
+ $count = $queries['address']->length;
+ if (!$count) {
+ throw new Services_Mailman_Exception('No match.');
}
- //TODO:parse html
- return $html;
+ $a = array();
+ for ($i=0;$i < $count;$i++) {
+ foreach ($queries as $key => $query) {
+ $a[$i][$key]=$query->item($i)?$query->item($i)->nodeValue:'';
+ }
+ }
+ return $a;
}
/**
@@ -537,7 +565,7 @@ public function members()
$emails = $xpath->query('/html/body/form/center[1]/table/tr/td[2]/a');
$names = $xpath->query('/html/body/form/center[1]/table/tr/td[2]/input[1]/@value');
$count = $emails->length;
- for ($i=0;$i <= $count;$i++) {
+ for ($i=0;$i < $count;$i++) {
if ($emails->item($i)) { $members[0][]=$emails->item($i)->nodeValue; }
if ($names->item($i)) { $members[1][]=$names->item($i)->nodeValue; }
}
View
142 tests/findmember-fail.html
@@ -0,0 +1,142 @@
+
+
+<HTML>
+<HEAD>
+<LINK REL="SHORTCUT ICON" HREF="/img-sys/mm-icon.png">
+<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<TITLE>Test Administration (Membership&nbsp;Management...)</TITLE>
+</HEAD>
+<BODY bgcolor="white"
+dir="ltr">
+<center><h2>Test mailing list administration<br>Membership&nbsp;Management... Section</h2></center><hr>
+<FORM action="../../../admin/test_example.co.uk/members/list" method="POST" enctype="multipart/form-data">
+
+ <table WIDTH="100%">
+ <tr>
+ <td><center><strong>Configuration Categories</strong></center></td>
+ <td><center><strong>Other Administrative Activities</strong></center></td>
+ </tr>
+ <tr>
+ <td>
+ <table>
+ <tr VALIGN="top">
+ <td>
+ <ul>
+ <li><a href="../../../admin/test_example.co.uk/general">General Options</a>
+ <li><a href="../../../admin/test_example.co.uk/passwords">Passwords</a>
+ <li><a href="../../../admin/test_example.co.uk/language">Language&nbsp;options</a>
+ <li><strong>Membership&nbsp;Management...</strong>
+<ul>
+<li><a href="../../../admin/test_example.co.uk/members/list"><strong>[Membership&nbsp;List]</strong></a>
+<li><a href="../../../admin/test_example.co.uk/members/add">Mass&nbsp;Subscription</a>
+<li><a href="../../../admin/test_example.co.uk/members/remove">Mass&nbsp;Removal</a>
+</ul>
+
+ <li><a href="../../../admin/test_example.co.uk/nondigest">Non-digest&nbsp;options</a>
+ <li><a href="../../../admin/test_example.co.uk/digest">Digest options</a>
+ </ul>
+</td>
+ <td>
+ <ul>
+ <li><a href="../../../admin/test_example.co.uk/privacy">Privacy options...</a>
+ <li><a href="../../../admin/test_example.co.uk/bounce">Bounce processing</a>
+ <li><a href="../../../admin/test_example.co.uk/archive">Archiving Options</a>
+ <li><a href="../../../admin/test_example.co.uk/gateway">Mail&lt;-&gt;News&nbsp;gateways</a>
+ <li><a href="../../../admin/test_example.co.uk/autoreply">Auto-responder</a>
+ <li><a href="../../../admin/test_example.co.uk/contentfilter">Content&nbsp;filtering</a>
+ <li><a href="../../../admin/test_example.co.uk/topics">Topics</a>
+ </ul>
+</td>
+ </tr>
+ </table>
+</td>
+ <td>
+ <ul>
+ <li><a href="../../../admindb/test_example.co.uk">Tend to pending moderator requests</a>
+ <li><a href="../../../listinfo/test_example.co.uk">Go to the general list information page</a>
+ <li><a href="../../../edithtml/test_example.co.uk">Edit the public HTML pages and text files</a>
+ <li><a href="http://example.co.uk/pipermail/test_example.co.uk/">Go to list archives</a><br>&nbsp;<br>
+ <li><a href="../../../admin/test_example.co.uk/logout"><FONT SIZE="+2"><b>Logout</b></FONT></a>
+ </ul>
+</td>
+ </tr>
+ </table>
+<hr>Make your changes in the following section, then submit them
+ using the <em>Submit Your Changes</em> button below.<p>
+ <table WIDTH="100%">
+ <tr>
+ <td COLSPAN="2" BGCOLOR="#99ccff"><center><h2>Membership List</h2></center></td>
+ </tr>
+ </table>
+
+ <table WIDTH="100%">
+ <tr>
+ <td><div align="right">Find member <a href="http://docs.python.org/library/re.html#regular-expression-syntax">(help)</a>:</div></td>
+ <td><INPUT name="findmember" type="TEXT" value="fail" size="40" ></td>
+ <td><INPUT name="findmember_btn" type="SUBMIT" value="Search..." ></td>
+ </tr>
+ </table>
+<hr><p><a href="http://example.co.uk/mailman/admin/test_example.co.uk/members/list?legend=yes">Click here to include the legend for this table.</a><center>
+ <table WIDTH="90%" BORDER="2">
+ <tr>
+ <td COLSPAN="11" BGCOLOR="#dddddd"><center><em>0 members total</em></center></td>
+ </tr>
+ <tr>
+ <td BGCOLOR="#dddddd"><center>unsub</center></td>
+ <td BGCOLOR="#dddddd"><center>member address<br>member name</center></td>
+ <td BGCOLOR="#dddddd"><center>mod</center></td>
+ <td BGCOLOR="#dddddd"><center>hide</center></td>
+ <td BGCOLOR="#dddddd"><center>nomail<br>[reason]</center></td>
+ <td BGCOLOR="#dddddd"><center>ack</center></td>
+ <td BGCOLOR="#dddddd"><center>not metoo</center></td>
+ <td BGCOLOR="#dddddd"><center>nodupes</center></td>
+ <td BGCOLOR="#dddddd"><center>digest</center></td>
+ <td BGCOLOR="#dddddd"><center>plain</center></td>
+ <td BGCOLOR="#dddddd"><center>language</center></td>
+ </tr>
+ </table>
+</center><center>
+ <table CELLPADDING="2" CELLSPACING="0" BORDER="0">
+ <tr>
+ <td ALIGN="middle"><strong><INPUT name="setmemberopts_btn" type="SUBMIT" value="Submit Your Changes" ></strong></td>
+ </tr>
+ </table>
+</center><hr>
+
+ <table WIDTH="100%">
+ <tr>
+ <td COLSPAN="2" BGCOLOR="#99ccff"><center><h2>Additional Member Tasks</h2></center></td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td COLSPAN="2"><li>Set everyone's moderation bit, including
+ those members not currently visible</td>
+ </tr>
+ <tr>
+ <td>
+ <table CELLSPACING="5">
+ <tr>
+ <td><INPUT name="allmodbit_val" type="RADIO" value="0" CHECKED >Off</td>
+ <td><INPUT name="allmodbit_val" type="RADIO" value="1" >On</td>
+ </tr>
+ </table>
+</td>
+ <td><INPUT name="allmodbit_btn" type="SUBMIT" value="Set" ></td>
+ </tr>
+ </table>
+
+</FORM>
+<hr><address><a href="../../../listinfo/test_example.co.uk">Test</a> list run by <a href="mailto:test-owner@example.co.uk">admin at example.co.uk</a><br><a href="../../../admin/test_example.co.uk">Test administrative interface</a> (requires authorization)<br><a href="../../../listinfo">Overview of all example.co.uk mailing lists</a><p>
+<table WIDTH="100%" BORDER="0">
+ <tr>
+ <td><img src="/img-sys/mailman.jpg" alt="Delivered by Mailman" border=0><br>version 2.1.14-1</td>
+ <td><img src="/img-sys/PythonPowered.png" alt="Python Powered" border=0></td>
+ <td><img src="/img-sys/gnu-head-tiny.jpg" alt="GNU's Not Unix" border=0></td>
+ </tr>
+</table>
+</address>
+</BODY>
+</HTML>
View
173 tests/findmember-james.html
@@ -0,0 +1,173 @@
+
+<HTML>
+<HEAD>
+<LINK REL="SHORTCUT ICON" HREF="/img-sys/mm-icon.png">
+<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<TITLE>Test Administration (Membership&nbsp;Management...)</TITLE>
+</HEAD>
+<BODY bgcolor="white"
+dir="ltr">
+<center><h2>Test mailing list administration<br>Membership&nbsp;Management... Section</h2></center><hr>
+<FORM action="../../../admin/test_example.co.uk/members/list" method="POST" enctype="multipart/form-data">
+
+ <table WIDTH="100%">
+ <tr>
+ <td><center><strong>Configuration Categories</strong></center></td>
+ <td><center><strong>Other Administrative Activities</strong></center></td>
+ </tr>
+ <tr>
+ <td>
+ <table>
+ <tr VALIGN="top">
+ <td>
+ <ul>
+ <li><a href="../../../admin/test_example.co.uk/general">General Options</a>
+ <li><a href="../../../admin/test_example.co.uk/passwords">Passwords</a>
+ <li><a href="../../../admin/test_example.co.uk/language">Language&nbsp;options</a>
+ <li><strong>Membership&nbsp;Management...</strong>
+<ul>
+<li><a href="../../../admin/test_example.co.uk/members/list"><strong>[Membership&nbsp;List]</strong></a>
+<li><a href="../../../admin/test_example.co.uk/members/add">Mass&nbsp;Subscription</a>
+<li><a href="../../../admin/test_example.co.uk/members/remove">Mass&nbsp;Removal</a>
+</ul>
+
+ <li><a href="../../../admin/test_example.co.uk/nondigest">Non-digest&nbsp;options</a>
+ <li><a href="../../../admin/test_example.co.uk/digest">Digest options</a>
+ </ul>
+</td>
+ <td>
+ <ul>
+ <li><a href="../../../admin/test_example.co.uk/privacy">Privacy options...</a>
+ <li><a href="../../../admin/test_example.co.uk/bounce">Bounce processing</a>
+ <li><a href="../../../admin/test_example.co.uk/archive">Archiving Options</a>
+ <li><a href="../../../admin/test_example.co.uk/gateway">Mail&lt;-&gt;News&nbsp;gateways</a>
+ <li><a href="../../../admin/test_example.co.uk/autoreply">Auto-responder</a>
+ <li><a href="../../../admin/test_example.co.uk/contentfilter">Content&nbsp;filtering</a>
+ <li><a href="../../../admin/test_example.co.uk/topics">Topics</a>
+ </ul>
+</td>
+ </tr>
+ </table>
+</td>
+ <td>
+ <ul>
+ <li><a href="../../../admindb/test_example.co.uk">Tend to pending moderator requests</a>
+ <li><a href="../../../listinfo/test_example.co.uk">Go to the general list information page</a>
+ <li><a href="../../../edithtml/test_example.co.uk">Edit the public HTML pages and text files</a>
+ <li><a href="http://example.co.uk/pipermail/test_example.co.uk/">Go to list archives</a><br>&nbsp;<br>
+ <li><a href="../../../admin/test_example.co.uk/logout"><FONT SIZE="+2"><b>Logout</b></FONT></a>
+ </ul>
+</td>
+ </tr>
+ </table>
+<hr>Make your changes in the following section, then submit them
+ using the <em>Submit Your Changes</em> button below.<p>
+ <table WIDTH="100%">
+ <tr>
+ <td COLSPAN="2" BGCOLOR="#99ccff"><center><h2>Membership List</h2></center></td>
+ </tr>
+ </table>
+
+ <table WIDTH="100%">
+ <tr>
+ <td><div align="right">Find member <a href="http://docs.python.org/library/re.html#regular-expression-syntax">(help)</a>:</div></td>
+ <td><INPUT name="findmember" type="TEXT" value="james" size="40" ></td>
+ <td><INPUT name="findmember_btn" type="SUBMIT" value="Search..." ></td>
+ </tr>
+ </table>
+<hr><p><a href="http://example.co.uk/mailman/admin/test_example.co.uk/members/list?legend=yes">Click here to include the legend for this table.</a><center>
+ <table WIDTH="90%" BORDER="2">
+ <tr>
+ <td COLSPAN="11" BGCOLOR="#dddddd"><center><em>2 members total</em></center></td>
+ </tr>
+ <tr>
+ <td BGCOLOR="#dddddd"><center>unsub</center></td>
+ <td BGCOLOR="#dddddd"><center>member address<br>member name</center></td>
+ <td BGCOLOR="#dddddd"><center>mod</center></td>
+ <td BGCOLOR="#dddddd"><center>hide</center></td>
+ <td BGCOLOR="#dddddd"><center>nomail<br>[reason]</center></td>
+ <td BGCOLOR="#dddddd"><center>ack</center></td>
+ <td BGCOLOR="#dddddd"><center>not metoo</center></td>
+ <td BGCOLOR="#dddddd"><center>nodupes</center></td>
+ <td BGCOLOR="#dddddd"><center>digest</center></td>
+ <td BGCOLOR="#dddddd"><center>plain</center></td>
+ <td BGCOLOR="#dddddd"><center>language</center></td>
+ </tr>
+ <tr>
+ <td><center><INPUT name="james.smith%40example.co.uk_unsub" type="CHECKBOX" value="off" ></center></td>
+ <td><a href="../../../options/test_example.co.uk/james.smith--at--example.co.uk">james.smith@example.co.uk</a><br><INPUT name="james.smith%40example.co.uk_realname" type="TEXT" value="" size="24" ><INPUT name="user" type="HIDDEN" value="james.smith%40example.co.uk" ></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_mod" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_hide" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_nomail" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_ack" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_notmetoo" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_nodupes" type="CHECKBOX" value="on" CHECKED ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_digest" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.smith%40example.co.uk_plain" type="CHECKBOX" value="on" CHECKED ></center></td>
+ <td><center>
+<Select name="james.smith%40example.co.uk_language">
+ <option value="en" Selected> English (USA) </option>
+</Select></center></td>
+ </tr>
+ <tr>
+ <td><center><INPUT name="james.jones%40example.co.uk_unsub" type="CHECKBOX" value="off" ></center></td>
+ <td><a href="../../../options/test_example.co.uk/james.jones--at--example.co.uk">james.jones@example.co.uk</a><br><INPUT name="james.jones%40example.co.uk_realname" type="TEXT" value="" size="24" ><INPUT name="user" type="HIDDEN" value="james.jones%40example.co.uk" ></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_mod" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_hide" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_nomail" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_ack" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_notmetoo" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_nodupes" type="CHECKBOX" value="off" ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_digest" type="CHECKBOX" value="on" CHECKED ></center></td>
+ <td><center><INPUT name="james.jones%40example.co.uk_plain" type="CHECKBOX" value="off" ></center></td>
+ <td><center>
+<Select name="james.jones%40example.co.uk_language">
+ <option value="en" Selected> English (USA) </option>
+</Select></center></td>
+ </tr>
+ </table>
+</center><center>
+ <table CELLPADDING="2" CELLSPACING="0" BORDER="0">
+ <tr>
+ <td ALIGN="middle"><strong><INPUT name="setmemberopts_btn" type="SUBMIT" value="Submit Your Changes" ></strong></td>
+ </tr>
+ </table>
+</center><hr>
+
+ <table WIDTH="100%">
+ <tr>
+ <td COLSPAN="2" BGCOLOR="#99ccff"><center><h2>Additional Member Tasks</h2></center></td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td COLSPAN="2"><li>Set everyone's moderation bit, including
+ those members not currently visible</td>
+ </tr>
+ <tr>
+ <td>
+ <table CELLSPACING="5">
+ <tr>
+ <td><INPUT name="allmodbit_val" type="RADIO" value="0" CHECKED >Off</td>
+ <td><INPUT name="allmodbit_val" type="RADIO" value="1" >On</td>
+ </tr>
+ </table>
+</td>
+ <td><INPUT name="allmodbit_btn" type="SUBMIT" value="Set" ></td>
+ </tr>
+ </table>
+
+</FORM>
+<hr><address><a href="../../../listinfo/test_example.co.uk">Test</a> list run by <a href="mailto:test-owner@example.co.uk">admin at example.co.uk</a><br><a href="../../../admin/test_example.co.uk">Test administrative interface</a> (requires authorization)<br><a href="../../../listinfo">Overview of all example.co.uk mailing lists</a><p>
+<table WIDTH="100%" BORDER="0">
+ <tr>
+ <td><img src="/img-sys/mailman.jpg" alt="Delivered by Mailman" border=0><br>version 2.1.14-1</td>
+ <td><img src="/img-sys/PythonPowered.png" alt="Python Powered" border=0></td>
+ <td><img src="/img-sys/gnu-head-tiny.jpg" alt="GNU's Not Unix" border=0></td>
+ </tr>
+</table>
+</address>
+</BODY>
+</HTML>
View
51 tests/test_member.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Test for Services_Mailman unsubscribe member
+--FILE--
+<?php
+
+//settings
+$testURL = 'http://example.co.uk/mailman/admin';
+$testList = 'test_example.co.uk';
+$testPW = 'password';
+
+//get html
+$html_success = file_get_contents('findmember-james.html');
+$len_success = strlen($html_success);
+$html_fail = file_get_contents('findmember-fail.html');
+$len_fail = strlen($html_fail);
+
+//set mailman
+require_once 'Services/Mailman.php';
+$mailman = new Services_Mailman($testURL,$testList,$testPW);
+
+//set mock
+require_once 'HTTP/Request2/Adapter/Mock.php';
+$mock = new HTTP_Request2_Adapter_Mock();
+$response = "HTTP/1.1 200 OK\r\n" .
+ "Content-Length: %s\r\n" .
+ "Connection: close\r\n" .
+ "\r\n%s";
+$mock->addResponse(sprintf($response,$len_success,$html_success));
+$mock->addResponse(sprintf($response,$len_fail,$html_fail));
+
+//set mock adapter
+$mailman->request->setAdapter($mock);
+
+// success
+try {
+ $mailman->member('james');
+} catch (Services_Mailman_Exception $e) {
+ echo 'Caught exception: ', $e->getMessage(), "\n";
+}
+
+// fail
+try {
+ $mailman->member('fail');
+} catch (Services_Mailman_Exception $e) {
+ echo 'Caught exception: ', $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+
+Caught exception: No match.
Please sign in to comment.
Something went wrong with that request. Please try again.