[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 3 4 namespace dokuwiki\Subscriptions; 5 6 7 use dokuwiki\ChangeLog\PageChangeLog; 8 use dokuwiki\Input\Input; 9 use DokuWiki_Auth_Plugin; 10 11 class BulkSubscriptionSender extends SubscriptionSender 12 { 13 14 /** 15 * Send digest and list subscriptions 16 * 17 * This sends mails to all subscribers that have a subscription for namespaces above 18 * the given page if the needed $conf['subscribe_time'] has passed already. 19 * 20 * This function is called form lib/exe/indexer.php 21 * 22 * @param string $page 23 * 24 * @return int number of sent mails 25 */ 26 public function sendBulk($page) 27 { 28 $subscriberManager = new SubscriberManager(); 29 if (!$subscriberManager->isenabled()) { 30 return 0; 31 } 32 33 /** @var DokuWiki_Auth_Plugin $auth */ 34 global $auth; 35 global $conf; 36 global $USERINFO; 37 /** @var Input $INPUT */ 38 global $INPUT; 39 $count = 0; 40 41 $subscriptions = $subscriberManager->subscribers($page, null, ['digest', 'list']); 42 43 // remember current user info 44 $olduinfo = $USERINFO; 45 $olduser = $INPUT->server->str('REMOTE_USER'); 46 47 foreach ($subscriptions as $target => $users) { 48 if (!$this->lock($target)) { 49 continue; 50 } 51 52 foreach ($users as $user => $info) { 53 list($style, $lastupdate) = $info; 54 55 $lastupdate = (int)$lastupdate; 56 if ($lastupdate + $conf['subscribe_time'] > time()) { 57 // Less than the configured time period passed since last 58 // update. 59 continue; 60 } 61 62 // Work as the user to make sure ACLs apply correctly 63 $USERINFO = $auth->getUserData($user); 64 $INPUT->server->set('REMOTE_USER', $user); 65 if ($USERINFO === false) { 66 continue; 67 } 68 if (!$USERINFO['mail']) { 69 continue; 70 } 71 72 if (substr($target, -1, 1) === ':') { 73 // subscription target is a namespace, get all changes within 74 $changes = getRecentsSince($lastupdate, null, getNS($target)); 75 } else { 76 // single page subscription, check ACL ourselves 77 if (auth_quickaclcheck($target) < AUTH_READ) { 78 continue; 79 } 80 $meta = p_get_metadata($target); 81 $changes = [$meta['last_change']]; 82 } 83 84 // Filter out pages only changed in small and own edits 85 $change_ids = []; 86 foreach ($changes as $rev) { 87 $n = 0; 88 $pagelog = new PageChangeLog($rev['id']); 89 while (!is_null($rev) && $rev['date'] >= $lastupdate && 90 ($INPUT->server->str('REMOTE_USER') === $rev['user'] || 91 $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) 92 ) { 93 $revisions = $pagelog->getRevisions($n++, 1); 94 $rev = (count($revisions) > 0) ? $pagelog->getRevisionInfo($revisions[0]) : null; 95 } 96 97 if (!is_null($rev) && $rev['date'] >= $lastupdate) { 98 // Some change was not a minor one and not by myself 99 $change_ids[] = $rev['id']; 100 } 101 } 102 103 // send it 104 if ($style === 'digest') { 105 foreach ($change_ids as $change_id) { 106 $this->sendDigest( 107 $USERINFO['mail'], 108 $change_id, 109 $lastupdate 110 ); 111 $count++; 112 } 113 } else { 114 if ($style === 'list') { 115 $this->sendList($USERINFO['mail'], $change_ids, $target); 116 $count++; 117 } 118 } 119 // TODO: Handle duplicate subscriptions. 120 121 // Update notification time. 122 $subscriberManager->add($target, $user, $style, time()); 123 } 124 $this->unlock($target); 125 } 126 127 // restore current user info 128 $USERINFO = $olduinfo; 129 $INPUT->server->set('REMOTE_USER', $olduser); 130 return $count; 131 } 132 133 /** 134 * Lock subscription info 135 * 136 * We don't use io_lock() her because we do not wait for the lock and use a larger stale time 137 * 138 * @param string $id The target page or namespace, specified by id; Namespaces 139 * are identified by appending a colon. 140 * 141 * @return bool true, if you got a succesful lock 142 * @author Adrian Lang <lang@cosmocode.de> 143 */ 144 protected function lock($id) 145 { 146 global $conf; 147 148 $lock = $conf['lockdir'] . '/_subscr_' . md5($id) . '.lock'; 149 150 if (is_dir($lock) && time() - @filemtime($lock) > 60 * 5) { 151 // looks like a stale lock - remove it 152 @rmdir($lock); 153 } 154 155 // try creating the lock directory 156 if (!@mkdir($lock)) { 157 return false; 158 } 159 160 if ($conf['dperm']) { 161 chmod($lock, $conf['dperm']); 162 } 163 return true; 164 } 165 166 /** 167 * Unlock subscription info 168 * 169 * @param string $id The target page or namespace, specified by id; Namespaces 170 * are identified by appending a colon. 171 * 172 * @return bool 173 * @author Adrian Lang <lang@cosmocode.de> 174 */ 175 protected function unlock($id) 176 { 177 global $conf; 178 $lock = $conf['lockdir'] . '/_subscr_' . md5($id) . '.lock'; 179 return @rmdir($lock); 180 } 181 182 /** 183 * Send a digest mail 184 * 185 * Sends a digest mail showing a bunch of changes of a single page. Basically the same as sendPageDiff() 186 * but determines the last known revision first 187 * 188 * @param string $subscriber_mail The target mail address 189 * @param string $id The ID 190 * @param int $lastupdate Time of the last notification 191 * 192 * @return bool 193 * @author Adrian Lang <lang@cosmocode.de> 194 * 195 */ 196 protected function sendDigest($subscriber_mail, $id, $lastupdate) 197 { 198 $pagelog = new PageChangeLog($id); 199 $n = 0; 200 do { 201 $rev = $pagelog->getRevisions($n++, 1); 202 $rev = (count($rev) > 0) ? $rev[0] : null; 203 } while (!is_null($rev) && $rev > $lastupdate); 204 205 // TODO I'm not happy with the following line and passing $this->mailer around. Not sure how to solve it better 206 $pageSubSender = new PageSubscriptionSender($this->mailer); 207 return $pageSubSender->sendPageDiff( 208 $subscriber_mail, 209 'subscr_digest', 210 $id, 211 $rev 212 ); 213 } 214 215 /** 216 * Send a list mail 217 * 218 * Sends a list mail showing a list of changed pages. 219 * 220 * @param string $subscriber_mail The target mail address 221 * @param array $ids Array of ids 222 * @param string $ns_id The id of the namespace 223 * 224 * @return bool true if a mail was sent 225 * @author Adrian Lang <lang@cosmocode.de> 226 * 227 */ 228 protected function sendList($subscriber_mail, $ids, $ns_id) 229 { 230 if (count($ids) === 0) { 231 return false; 232 } 233 234 $tlist = ''; 235 $hlist = '<ul>'; 236 foreach ($ids as $id) { 237 $link = wl($id, [], true); 238 $tlist .= '* ' . $link . NL; 239 $hlist .= '<li><a href="' . $link . '">' . hsc($id) . '</a></li>' . NL; 240 } 241 $hlist .= '</ul>'; 242 243 $id = prettyprint_id($ns_id); 244 $trep = [ 245 'DIFF' => rtrim($tlist), 246 'PAGE' => $id, 247 'SUBSCRIBE' => wl($id, ['do' => 'subscribe'], true, '&'), 248 ]; 249 $hrep = [ 250 'DIFF' => $hlist, 251 ]; 252 253 return $this->send( 254 $subscriber_mail, 255 'subscribe_list', 256 $ns_id, 257 'subscr_list', 258 $trep, 259 $hrep 260 ); 261 } 262 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body