diff options
-rw-r--r-- | _test/tests/inc/subscription.test.php | 121 | ||||
-rw-r--r-- | inc/load.php | 1 | ||||
-rw-r--r-- | inc/subscription.php | 724 |
3 files changed, 497 insertions, 349 deletions
diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php new file mode 100644 index 000000000..77bf3e830 --- /dev/null +++ b/_test/tests/inc/subscription.test.php @@ -0,0 +1,121 @@ +<?php + +class subscription_test extends DokuWikiTest { + + function test_regexp(){ + // data to test against + $data = array( + "casper every\n", + "Andreas digest 1344689733", + "Cold%20Fusion every", + "zioth list 1344691369\n", + "nlights digest", + "rikblok\tdigest \t 1344716803", + ); + + // user, style, data, expected number of results + $tests = array( + array('Cold Fusion', null, null, 1), + array('casper', null, null, 1), + array('nope', null, null, 0), + array('lights', null, null, 0), + array(array('Cold Fusion','casper','nope'), null, null, 2), + array(null, 'list', null, 1), + array(null, 'every', null, 2), + array(null, 'digest', null, 3), + array(null, array('list', 'every'), null, 3), + array('casper', 'digest', null, 0), + array('casper', array('digest','every'), null, 1), + array('zioth', 'list', '1344691369', 1), + array('zioth', null, '1344691369', 1), + array('zioth', 'digest', '1344691369', 0), + ); + + $sub = new MockupSubscription(); + + $row = 0; + foreach($tests as $test){ + $re = $sub->buildregex($test[0], $test[1], $test[2]); + $this->assertFalse(empty($re), "test line $row"); + $result = preg_grep($re, $data); + $this->assertEquals($test[3], count($result), "test line $row. $re got\n".print_r($result, true)); + + $row++; + } + } + + function test_addremove(){ + $sub = new MockupSubscription(); + + // no subscriptions + $this->assertArrayNotHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // add page subscription + $sub->add('wiki:dokuwiki', 'testuser', 'every'); + + // one subscription + $this->assertArrayHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // remove page subscription + $sub->remove('wiki:dokuwiki', 'testuser'); + + // no subscription + $this->assertArrayNotHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // add namespace subscription + $sub->add('wiki:', 'testuser', 'every'); + + // one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // remove (non existing) page subscription + $sub->remove('wiki:dokuwiki', 'testuser'); + + // still one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // change namespace subscription + $sub->add('wiki:', 'testuser', 'digest', '1234567'); + + // still one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // check contents + $this->assertEquals( + array('wiki:' => array('testuser' => array('digest', '1234567'))), + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + } + + + +} + +/** + * makes protected methods visible for testing + */ +class MockupSubscription extends Subscription { + public function buildregex($user = null, $style = null, $data = null) { + return parent::buildregex($user, $style, $data); + } +} + +//Setup VIM: ex: et ts=4 : diff --git a/inc/load.php b/inc/load.php index b676518e7..bd6d39814 100644 --- a/inc/load.php +++ b/inc/load.php @@ -81,6 +81,7 @@ function load_autoload($name){ 'Mailer' => DOKU_INC.'inc/Mailer.class.php', 'RemoteAPI' => DOKU_INC.'inc/remote.php', 'RemoteAPICore' => DOKU_INC.'inc/RemoteAPICore.php', + 'Subscription' => DOKU_INC.'inc/subscription.php', 'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php', 'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php', diff --git a/inc/subscription.php b/inc/subscription.php index 1f1aedfa4..856836cd5 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -12,399 +12,425 @@ * - subscription_lock * - subscription_unlock * + * @fixme handle $conf['subscribers'] and disable actions + * * @author Adrian Lang <lang@cosmocode.de> + * @author Andreas Gohr <andi@splitbrain.org> * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ -/** - * Get the name of the metafile tracking subscriptions to target page or - * namespace - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_filename($id) { - $meta_fname = '.mlist'; - if ((substr($id, -1, 1) === ':')) { - $meta_froot = getNS($id); - $meta_fname = '/' . $meta_fname; - } else { - $meta_froot = $id; +class Subscription { + + /** + * Return the subscription meta file for the given ID + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return string + */ + protected function file($id) { + $meta_fname = '.mlist'; + if((substr($id, -1, 1) === ':')) { + $meta_froot = getNS($id); + $meta_fname = '/'.$meta_fname; + } else { + $meta_froot = $id; + } + return metaFN((string) $meta_froot, $meta_fname); } - return metaFN((string) $meta_froot, $meta_fname); -} -/** - * Lock subscription info for an ID - * - * @author Adrian Lang <lang@cosmocode.de> - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_lock_filename ($id){ - global $conf; - return $conf['lockdir'].'/_subscr_' . md5($id) . '.lock'; -} + /** + * Lock subscription info + * + * We don't use io_lock() her because we do not wait for the lock and use a larger stale time + * + * @author Adrian Lang <lang@cosmocode.de> + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool true, if you got a succesful lock + */ + protected function lock($id) { + global $conf; -/** - * Creates a lock file for writing subscription data - * - * @todo add lock time parameter to io_lock() and use this instead - * @param $id - * @return bool - */ -function subscription_lock($id) { - global $conf; - $lock = subscription_lock_filename($id); + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; - if (is_dir($lock) && time()-@filemtime($lock) > 60*5) { - // looks like a stale lock - remove it - @rmdir($lock); + if(is_dir($lock) && time() - @filemtime($lock) > 60 * 5) { + // looks like a stale lock - remove it + @rmdir($lock); + } + + // try creating the lock directory + if(!@mkdir($lock, $conf['dmode'])) { + return false; + } + + if($conf['dperm']) chmod($lock, $conf['dperm']); + return true; } - // try creating the lock directory - if (!@mkdir($lock,$conf['dmode'])) { - return false; + /** + * Unlock subscription info + * + * @author Adrian Lang <lang@cosmocode.de> + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool + */ + protected function unlock($id) { + global $conf; + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; + return @rmdir($lock); } - if($conf['dperm']) chmod($lock, $conf['dperm']); - return true; -} + /** + * Construct a regular expression for parsing a subscription definition line + * + * @author Andreas Gohr <andi@splitbrain.org> + * + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return string complete regexp including delimiters + * @throws Exception when no data is passed + */ + protected function buildregex($user = null, $style = null, $data = null) { + // always work with arrays + $user = (array) $user; + $style = (array) $style; + $data = (array) $data; -/** - * Unlock subscription info for an ID - * - * @author Adrian Lang <lang@cosmocode.de> - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return bool - */ -function subscription_unlock($id) { - $lockf = subscription_lock_filename($id); - return @rmdir($lockf); -} + // clean + $user = array_filter(array_map('trim', $user)); + $style = array_filter(array_map('trim', $style)); + $data = array_filter(array_map('trim', $data)); -/** - * Set subscription information - * - * Allows to set subscription information for permanent storage in meta files. - * Subscriptions consist of a target object, a subscribing user, a subscribe - * style and optional data. - * A subscription may be deleted by specifying an empty subscribe style. - * Only one subscription per target and user is allowed. - * The function returns false on error, otherwise true. Note that no error is - * returned if a subscription should be deleted but the user is not subscribed - * and the subscription meta file exists. - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param string $user The subscriber or unsubscriber - * @param string $page The target object (page or namespace), specified by - * id; Namespaces are identified by a trailing colon. - * @param string $style The subscribe style; DokuWiki currently implements - * “every”, “digest”, and “list”. - * @param string $data An optional data blob - * @param bool $overwrite Whether an existing subscription may be overwritten - * @return bool - */ -function subscription_set($user, $page, $style, $data = null, - $overwrite = false) { - global $lang; - if (is_null($style)) { - // Delete subscription. - $file = subscription_filename($page); - if (!@file_exists($file)) { - msg(sprintf($lang['subscr_not_subscribed'], $user, - prettyprint_id($page)), -1); - return false; - } + // user names are encoded + $user = array_map('auth_nameencode', $user); - // io_deleteFromFile does not return false if no line matched. - return io_deleteFromFile($file, - subscription_regex(array('user' => auth_nameencode($user))), - true); - } + // quote + $user = array_map('preg_quote_cb', $user); + $style = array_map('preg_quote_cb', $style); + $data = array_map('preg_quote_cb', $data); - // Delete subscription if one exists and $overwrite is true. If $overwrite - // is false, fail. - $subs = subscription_find($page, array('user' => $user)); - if (count($subs) > 0 && array_pop(array_keys($subs)) === $page) { - if (!$overwrite) { - msg(sprintf($lang['subscr_already_subscribed'], $user, - prettyprint_id($page)), -1); - return false; + // join + $user = join('|', $user); + $style = join('|', $style); + $data = join('|', $data); + + // any data at all? + if($user.$style.$data === '') throw new Exception('no data passed'); + + // replace empty values, set which ones are optional + $sopt = ''; + $dopt = ''; + if($user === '') { + $user = '\S+'; } - // Fail if deletion failed, else continue. - if (!subscription_set($user, $page, null)) { - return false; + if($style === '') { + $style = '\S+'; + $sopt = '?'; + } + if($data === '') { + $data = '\S+'; + $dopt = '?'; } - } - $file = subscription_filename($page); - $content = auth_nameencode($user) . ' ' . $style; - if (!is_null($data)) { - $content .= ' ' . $data; + // assemble + return "/^($user)(?:\\s+($style))$sopt(?:\\s+($data))$dopt$/"; } - return io_saveFile($file, $content . "\n", true); -} -/** - * Recursively search for matching subscriptions - * - * This function searches all relevant subscription files for a page or - * namespace. - * - * @author Adrian Lang <lang@cosmocode.de> - * @see function subscription_regex for $pre documentation - * - * @param string $page The target object’s (namespace or page) id - * @param array $pre A hash of predefined values - * @return array - */ -function subscription_find($page, $pre) { - // Construct list of files which may contain relevant subscriptions. - $filenames = array(':' => subscription_filename(':')); - do { - $filenames[$page] = subscription_filename($page); - $page = getNS(rtrim($page, ':')) . ':'; - } while ($page !== ':'); - - // Handle files. - $matches = array(); - foreach ($filenames as $cur_page => $filename) { - if (!@file_exists($filename)) { - continue; - } - $subscriptions = file($filename); - foreach ($subscriptions as $subscription) { - if (strpos($subscription, ' ') === false) { - // This is an old subscription file. - $subscription = trim($subscription) . " every\n"; - } + /** + * Recursively search for matching subscriptions + * + * This function searches all relevant subscription files for a page or + * namespace. + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param string $page The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return array + */ + public function subscribers($page, $user = null, $style = null, $data = null) { + // Construct list of files which may contain relevant subscriptions. + $files = array(':' => $this->file(':')); + do { + $files[$page] = $this->file($page); + $page = getNS(rtrim($page, ':')).':'; + } while($page !== ':'); - list($user, $rest) = explode(' ', $subscription, 2); - $subscription = rawurldecode($user) . " " . $rest; + $re = $this->buildregex($user, $style, $data); - if (preg_match(subscription_regex($pre), $subscription, - $line_matches) === 0) { - continue; - } - $match = array_slice($line_matches, 1); - if (!isset($matches[$cur_page])) { - $matches[$cur_page] = array(); + // Handle files. + $result = array(); + foreach($files as $target => $file) { + if(!@file_exists($file)) continue; + + $lines = file($file); + foreach($lines as $line) { + // fix old style subscription files + if(strpos($line, ' ') === false) $line = trim($line)." every\n"; + + // check for matching entries + if(!preg_match($re, $line, $m)) continue; + + $u = rawurldecode($m[1]); // decode the user name + if(!isset($result[$target])) $result[$target] = array(); + $result[$target][$u] = array($m[2], $m[3]); // add to result } - $matches[$cur_page][] = $match; } + return array_reverse($result); } - return array_reverse($matches); -} -/** - * Get data for $INFO['subscribed'] - * - * $INFO['subscribed'] is either false if no subscription for the current page - * and user is in effect. Else it contains an array of arrays with the fields - * “target”, “style”, and optionally “data”. - * - * @author Adrian Lang <lang@cosmocode.de> - */ -function get_info_subscribed() { - global $ID; - global $conf; - if (!$conf['subscribers']) { - return false; - } + /** + * Adds a new subscription for the given page or namespace + * + * This will automatically overwrite any existent subscription for the given user on this + * *exact* page or namespace. It will *not* modify any subscription that may exist in higher namespaces. + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @param string $user + * @param string $style + * @param string $data + * @throws Exception when user or style is empty + * @return bool + */ + public function add($id, $user, $style, $data = '') { + // delete any existing subscription + $this->remove($id, $user); - $subs = subscription_find($ID, array('user' => $_SERVER['REMOTE_USER'])); - if (count($subs) === 0) { - return false; - } + $user = auth_nameencode(trim($user)); + $style = trim($style); + $data = trim($data); - $_ret = array(); - foreach ($subs as $target => $subs_data) { - $new = array('target' => $target, - 'style' => $subs_data[0][0]); - if (count($subs_data[0]) > 1) { - $new['data'] = $subs_data[0][1]; - } - $_ret[] = $new; + if(!$user) throw new Exception('no subscription user given'); + if(!$style) throw new Exception('no subscription style given'); + + $line = "$user $style"; + if($data) $line .= " $data"; + $line .= "\n"; + + $file = $this->file($id); + + return io_saveFile($file, $line, true); } - return $_ret; -} + /** + * Removes a subscription for the given page or namespace + * + * This removes all subscriptions matching the given criteria on the given page or + * namespace. It will *not* modify any subscriptions that may exist in higher + * namespaces. + * + * @param string $id The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return bool + */ + public function remove($id, $user = null, $style = null, $data = null) { + $file = $this->file($id); + if(!file_exists($file)) return true; -/** - * Construct a regular expression parsing a subscription definition line - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param array $pre A hash of predefined values; “user”, “style”, and - * “data” may be set to limit the results to - * subscriptions matching these parameters. If - * “escaped” is true, these fields are inserted into the - * regular expression without escaping. - * - * @return string complete regexp including delimiters - */ -function subscription_regex($pre = array()) { - if (!isset($pre['escaped']) || $pre['escaped'] === false) { - $pre = array_map('preg_quote_cb', $pre); + $re = $this->buildregex($user, $style, $data); + return io_deleteFromFile($file, $re, true); } - foreach (array('user', 'style', 'data') as $key) { - if (!isset($pre[$key])) { - $pre[$key] = '(\S+)'; + + /** + * Get data for $INFO['subscribed'] + * + * $INFO['subscribed'] is either false if no subscription for the current page + * and user is in effect. Else it contains an array of arrays with the fields + * “target”, “style”, and optionally “data”. + * + * @param string $id Page ID, defaults to global $ID + * @param string $user User, defaults to $_SERVER['REMOTE_USER'] + * @return array + * @author Adrian Lang <lang@cosmocode.de> + */ + function user_subscription($id='', $user='') { + global $ID; + global $conf; + if(!$conf['subscribers']) return false; + + if(!$id) $id = $ID; + if(!$user) $user = $_SERVER['REMOTE_USER']; + + + $subs = $this->subscribers($id, $user); + if(!count($subs)) return false; + + $result = array(); + foreach($subs as $target => $data) { + $result[] = array( + 'target' => $target, + 'style' => $data[$user][0], + 'data' => $data[$user][1] + ); } + + return $result; } - return '/^' . $pre['user'] . '(?: ' . $pre['style'] . - '(?: ' . $pre['data'] . ')?)?$/'; -} -/** - * Return a string with the email addresses of all the - * users subscribed to a page - * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. - * - * @author Steven Danz <steven-danz@kc.rr.com> - * @author Adrian Lang <lang@cosmocode.de> - * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) - * @return string - */ -function subscription_addresslist(&$data){ - global $conf; - /** @var auth_basic $auth */ - global $auth; + /** + * Return a string with the email addresses of all the + * users subscribed to a page + * + * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * + * @author Steven Danz <steven-danz@kc.rr.com> + * @author Adrian Lang <lang@cosmocode.de> + * + * @todo this does NOT return a string but uses a reference to write back, either fix function or docs + * @param array $data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) + * @return string + */ + function subscription_addresslist(&$data) { + global $conf; + /** @var auth_basic $auth */ + global $auth; - $id = $data['id']; - $self = $data['self']; - $addresslist = $data['addresslist']; + $id = $data['id']; + $self = $data['self']; + $addresslist = $data['addresslist']; - if (!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if (!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!' . preg_quote_cb($_SERVER['REMOTE_USER']) . - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach ($subs as $by_targets) { - foreach ($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if ($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); - if ($level >= AUTH_READ) { - if (strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + if(!$conf['subscribers'] || $auth === null) { + return ''; + } + $pres = array('style' => 'every', 'escaped' => true); + if(!$self && isset($_SERVER['REMOTE_USER'])) { + $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). + '(?: |$))\S+)'; + } + $subs = subscription_find($id, $pres); + $emails = array(); + foreach($subs as $by_targets) { + foreach($by_targets as $sub) { + $info = $auth->getUserData($sub[0]); + if($info === false) continue; + $level = auth_aclcheck($id, $sub[0], $info['grps']); + if($level >= AUTH_READ) { + if(strcasecmp($info['mail'], $conf['notify']) != 0) { + $emails[$sub[0]] = $info['mail']; + } } } } + $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); } - $data['addresslist'] = trim($addresslist . ',' . implode(',', $emails), ','); -} -/** - * Send a digest mail - * - * Sends a digest mail showing a bunch of changes. - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param string $subscriber_mail The target mail address - * @param array $id The ID - * @param int $lastupdate Time of the last notification - */ -function subscription_send_digest($subscriber_mail, $id, $lastupdate) { - $n = 0; - do { - $rev = getRevisions($id, $n++, 1); - $rev = (count($rev) > 0) ? $rev[0] : null; - } while (!is_null($rev) && $rev > $lastupdate); - - $replaces = array('NEWPAGE' => wl($id, '', true, '&'), - 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&')); - if (!is_null($rev)) { - $subject = 'changed'; - $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $replaces['DIFF'] = $dformat->format($df); - } else { - $subject = 'newpage'; - $replaces['OLDPAGE'] = 'none'; - $replaces['DIFF'] = rawWiki($id); + /** + * Send a digest mail + * + * Sends a digest mail showing a bunch of changes. + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param string $subscriber_mail The target mail address + * @param array $id The ID + * @param int $lastupdate Time of the last notification + */ + function subscription_send_digest($subscriber_mail, $id, $lastupdate) { + $n = 0; + do { + $rev = getRevisions($id, $n++, 1); + $rev = (count($rev) > 0) ? $rev[0] : null; + } while(!is_null($rev) && $rev > $lastupdate); + + $replaces = array( + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + if(!is_null($rev)) { + $subject = 'changed'; + $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $replaces['DIFF'] = $dformat->format($df); + } else { + $subject = 'newpage'; + $replaces['OLDPAGE'] = 'none'; + $replaces['DIFF'] = rawWiki($id); + } + subscription_send( + $subscriber_mail, $replaces, $subject, $id, + 'subscr_digest' + ); } - subscription_send($subscriber_mail, $replaces, $subject, $id, - 'subscr_digest'); -} -/** - * Send a list mail - * - * Sends a list mail showing a list of changed pages. - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param string $subscriber_mail The target mail address - * @param array $ids Array of ids - * @param string $ns_id The id of the namespace - */ -function subscription_send_list($subscriber_mail, $ids, $ns_id) { - if (count($ids) === 0) return; - global $conf; - $list = ''; - foreach ($ids as $id) { - $list .= '* ' . wl($id, array(), true) . NL; + /** + * Send a list mail + * + * Sends a list mail showing a list of changed pages. + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param string $subscriber_mail The target mail address + * @param array $ids Array of ids + * @param string $ns_id The id of the namespace + */ + function subscription_send_list($subscriber_mail, $ids, $ns_id) { + if(count($ids) === 0) return; + global $conf; + $list = ''; + foreach($ids as $id) { + $list .= '* '.wl($id, array(), true).NL; + } + subscription_send( + $subscriber_mail, + array( + 'DIFF' => rtrim($list), + 'SUBSCRIBE' => wl( + $ns_id.$conf['start'], + array('do' => 'subscribe'), + true, '&' + ) + ), + 'subscribe_list', + prettyprint_id($ns_id), + 'subscr_list' + ); } - subscription_send($subscriber_mail, - array('DIFF' => rtrim($list), - 'SUBSCRIBE' => wl($ns_id . $conf['start'], - array('do' => 'subscribe'), - true, '&')), - 'subscribe_list', - prettyprint_id($ns_id), - 'subscr_list'); -} -/** - * Helper function for sending a mail - * - * @author Adrian Lang <lang@cosmocode.de> - * - * @param string $subscriber_mail The target mail address - * @param array $replaces Predefined parameters used to parse the - * template - * @param string $subject The lang id of the mail subject (without the - * prefix “mail_”) - * @param string $id The page or namespace id - * @param string $template The name of the mail template - * @return bool - */ -function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { - global $lang; - - $text = rawLocale($template); - $trep = array_merge($replaces, array('PAGE' => $id)); - - $subject = $lang['mail_' . $subject] . ' ' . $id; - $mail = new Mailer(); - $mail->bcc($subscriber_mail); - $mail->subject($subject); - $mail->setBody($text,$trep); - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id,array('do'=>'subscribe'),true,'&').'>', - false - ); - return $mail->send(); -} + /** + * Helper function for sending a mail + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param string $subscriber_mail The target mail address + * @param array $replaces Predefined parameters used to parse the + * template + * @param string $subject The lang id of the mail subject (without the + * prefix “mail_”) + * @param string $id The page or namespace id + * @param string $template The name of the mail template + * @return bool + */ + function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { + global $lang; + + $text = rawLocale($template); + $trep = array_merge($replaces, array('PAGE' => $id)); + + $subject = $lang['mail_'.$subject].' '.$id; + $mail = new Mailer(); + $mail->bcc($subscriber_mail); + $mail->subject($subject); + $mail->setBody($text, $trep); + $mail->setHeader( + 'List-Unsubscribe', + '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', + false + ); + return $mail->send(); + } + +}
\ No newline at end of file |