public function get_comment_notification($item) { global $context; // build a tease notification for simple members // sanity check if (!isset($item['anchor']) || !($anchor = Anchors::get($item['anchor']))) { throw new Exception('no anchor for this comment'); } // headline $headline = sprintf(i18n::c('%s has replied'), Surfer::get_link()); $content = BR; // shape these $tease = Skin::build_mail_content($headline, $content); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . Comments::get_url($item['id'], 'view'); $menu[] = Skin::build_mail_button($link, i18n::c('View the reply'), TRUE); // link to the container $menu[] = Skin::build_mail_button($anchor->get_url(), $anchor->get_title(), FALSE); // finalize links $tease .= Skin::build_mail_menu($menu); // assemble all parts of the mail $mail = array(); $mail['subject'] = sprintf(i18n::c('%s: %s'), i18n::c('Reply in the discussion'), strip_tags($anchor->get_title())); $mail['notification'] = Comments::build_notification($item); // full notification $mail['tease'] = Mailer::build_notification($tease, 1); return $mail; }
$message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = Sections::get_permalink($item); if (!is_object($overlay) || !($label = $overlay->get_label('permalink_command', 'sections', FALSE))) { $label = i18n::c('View the section'); } $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to the container if (is_object($anchor)) { $link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), FALSE); } // finalize links $message .= Skin::build_mail_menu($menu); // provide a link that also authenticates surfers on click-through --see users/login.php $message = str_replace(array(Sections::get_permalink($item), str_replace('&', '&', Sections::get_permalink($item))), $context['url_to_root'] . Users::get_login_url('visit', 'section:' . $item['id'], $user['id'], $item['handle']), $message); // threads messages $headers = Mailer::set_thread('section:' . $item['id']); // get attachments from the overlay, if any $attachments = NULL; if (is_callable(array($overlay, 'get_invite_attachments'))) { $attachments = $overlay->get_invite_attachments('PUBLISH'); } // post it if (Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments)) { $actual_names[] = htmlspecialchars($recipient); } } Mailer::close();
/** * build a notification related to a section * * This function builds a mail message that displays: * - an image of the contributor (if possible) * - a headline mentioning the contribution * - the full content of the section * - a button linked to the section * - a link to the containing section, if any * * Note: this function returns legacy HTML, not modern XHTML, because this is what most * e-mail client software can afford. * * @param string either 'apply', 'create' or 'update' * @param array attributes of the item * @param object overlay of the item, if any * @return string text to be send by e-mail */ public static function build_notification($action, $item, $overlay = NULL) { global $context; // get the main anchor $anchor = Anchors::get($item['anchor']); // compute page title if (is_object($overlay)) { $title = Codes::beautify_title($overlay->get_text('title', $item)); } else { $title = Codes::beautify_title($item['title']); } // headline template switch ($action) { case 'apply': $template = i18n::c('%s is requesting access to %s'); break; case 'create': $template = i18n::c('%s has created section %s'); break; case 'update': $template = i18n::c('%s has updated section %s'); break; } // headline $headline = sprintf($template, Surfer::get_link(), '<a href="' . Sections::get_permalink($item) . '">' . $title . '</a>'); // panel content $content = ''; // signal restricted and private articles if ($item['active'] == 'N') { $title = PRIVATE_FLAG . $title; } elseif ($item['active'] == 'R') { $title = RESTRICTED_FLAG . $title; } // insert page title $content .= '<h3><span>' . $title . '</span></h3>'; // insert anchor prefix if (is_object($anchor)) { $content .= $anchor->get_prefix(); } // the introduction text, if any if (is_object($overlay)) { $content .= Skin::build_block($overlay->get_text('introduction', $item), 'introduction'); } elseif (isset($item['introduction']) && trim($item['introduction'])) { $content .= Skin::build_block($item['introduction'], 'introduction'); } // get text related to the overlay, if any if (is_object($overlay)) { $content .= $overlay->get_text('view', $item); } // filter description, if necessary if (is_object($overlay)) { $description = $overlay->get_text('description', $item); } else { $description = $item['description']; } // the beautified description, which is the actual page body if ($description) { // use adequate label if (is_object($overlay) && ($label = $overlay->get_label('description'))) { $content .= Skin::build_block($label, 'title'); } // beautify the target page $content .= Skin::build_block($description, 'description', '', $item['options']); } // attachment details $details = array(); // info on related sections if ($count = Sections::count_for_anchor('section:' . $item['id'])) { $details[] = sprintf(i18n::nc('%d section', '%d sections', $count), $count); } // info on related articles if ($count = Articles::count_for_anchor('section:' . $item['id'])) { $details[] = sprintf(i18n::nc('%d page', '%d pages', $count), $count); } // info on related files if ($count = Files::count_for_anchor('section:' . $item['id'], TRUE)) { // the actual list of files attached to this section if (preg_match('/\\bfiles_by_title\\b/i', $item['options'])) { $items = Files::list_by_title_for_anchor('section:' . $item['id'], 0, 300, 'compact'); } else { $items = Files::list_by_date_for_anchor('section:' . $item['id'], 0, 300, 'compact'); } // wrap it with some header if (is_array($items)) { $items = Skin::build_list($items); } if ($items) { $content .= '<h3><span>' . i18n::s('Files') . '</span></h3>' . $items; } // details to be displayed at page bottom $details[] = sprintf(i18n::nc('%d file', '%d files', $count), $count); } // info on related links include_once $context['path_to_root'] . 'links/links.php'; if ($count = Links::count_for_anchor('section:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::nc('%d link', '%d links', $count), $count); } // comments include_once $context['path_to_root'] . 'comments/comments.php'; if ($count = Comments::count_for_anchor('section:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::nc('%d comment', '%d comments', $count), $count); } // describe attachments if (count($details)) { $content .= '<hr align="left" size=1" width="150">' . '<p style="margin: 3px 0;">' . sprintf(i18n::c('This section has %s'), join(', ', $details)) . '</p>'; } // assemble main content of this message $text = Skin::build_mail_content($headline, $content); // a set of links $menu = array(); // request access to the item if ($action == 'apply') { // call for action $link = $context['url_to_home'] . $context['url_to_root'] . Sections::get_url($item['id'], 'invite', Surfer::get_id()); $label = sprintf(i18n::c('Invite %s to participate'), Surfer::get_name()); $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to user profile $link = Surfer::get_permalink(); $label = sprintf(i18n::c('View the profile of %s'), Surfer::get_name()); $menu[] = Skin::build_mail_button($link, $label, FALSE); // invite to visit the item } else { // call for action $link = Sections::get_permalink($item); if (!is_object($overlay) || !($label = $overlay->get_label('permalink_command', 'sections', FALSE))) { $label = i18n::c('View the section'); } $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to the container if (is_object($anchor)) { $link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), FALSE); } } // finalize links $text .= Skin::build_mail_menu($menu); // the full message return $text; }
/** * build a notification for a new comment * * This function builds a mail message that features: * - an image of the contributor (if possible) * - a headline mentioning the contribution * - the full content of the new comment * - a button linked to the reply page * - a link to the containing page * * Note: this function returns legacy HTML, not modern XHTML, because this is what most * e-mail client software can afford. * * @param array attributes of the new item * @return string text to be send by e-mail */ public static function build_notification($item) { global $context; // sanity check if (!isset($item['anchor']) || !($anchor = Anchors::get($item['anchor']))) { throw new Exception('no anchor for this comment'); } // headline $headline = sprintf(i18n::c('%s has contributed to %s'), Surfer::get_link(), '<a href="' . $anchor->get_url() . '">' . $anchor->get_title() . '</a>'); // content $content = Codes::beautify($item['description']); // this is an approval if ($item['type'] == 'approval') { $content = Skin::build_block(i18n::s('You have provided your approval'), 'note') . $content; } // shape these $text = Skin::build_mail_content($headline, $content); // a set of links $menu = array(); // flat thread of contributions if possible if (isset($item['previous_id']) && $item['previous_id']) { $previous_id = $item['previous_id']; } else { $previous_id = $item['id']; } // call for action $link = $context['url_to_home'] . $context['url_to_root'] . Comments::get_url($previous_id, 'reply'); $menu[] = Skin::build_mail_button($link, i18n::c('Reply'), TRUE); // link to the container $menu[] = Skin::build_mail_button($anchor->get_url(), $anchor->get_title(), FALSE); // finalize links $text .= Skin::build_mail_menu($menu); // the full message return $text; }
/** * remember an action once it's done * * To be overloaded into derived class * * @param string the action 'insert', 'update' or 'delete' * @param array the hosting record * @param string reference of the hosting record (e.g., 'article:123') * @return FALSE on error, TRUE otherwise */ function remember($action, $host, $reference) { global $context; // remember the id of the master record $id = $host['id']; // set default values for this editor Surfer::check_default_editor($this->attributes); // we use the existing back-end for dates include_once $context['path_to_root'] . 'dates/dates.php'; // build the update query switch ($action) { case 'delete': // no need to notify participants after the date planned for the event, nor if the event has been initiated if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp'] > gmstrftime('%Y-%m-%d %H:%M') && isset($this->attributes['status']) && $this->attributes['status'] != 'started' && $this->attributes['status'] != 'stopped') { // send a cancellation message to participants $query = "SELECT user_email FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "') AND (approved LIKE 'Y')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // message title $subject = sprintf('%s: %s', i18n::c('Cancellation'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('%s has cancelled %s'), Surfer::get_link(), $this->anchor->get_title()); // message to reader $message = $this->get_invite_default_message('CANCEL'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('CANCEL'); // post it Mailer::notify(Surfer::from(), $item['user_email'], $subject, $message, $headers, $attachments); } } // delete dates for this anchor Dates::delete_for_anchor($reference); // also delete related enrolment records $query = "DELETE FROM " . SQL::table_name('enrolments') . " WHERE anchor LIKE '" . $reference . "'"; SQL::query($query); break; case 'insert': // bind one date to this record if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp']) { $fields = array(); $fields['anchor'] = $reference; $fields['date_stamp'] = $this->attributes['date_stamp']; // update the database if (!($fields['id'] = Dates::post($fields))) { Logger::error(i18n::s('Impossible to add an item.')); return FALSE; } } // enroll page creator include_once $context['path_to_root'] . 'shared/enrolments.php'; enrolments::confirm($reference); // reload the anchor through the cache to reflect the update if ($reference) { $this->anchor = Anchors::get($reference, TRUE); } // send a confirmation message to event creator $query = "SELECT * FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // a user registered on this server if ($item['user_id'] && ($watcher = Users::get($item['user_id']))) { // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // use this email address if ($watcher['full_name']) { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['full_name']); } else { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['nick_name']); } // message title $subject = sprintf(i18n::c('Meeting: %s'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('you have arranged %s'), '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url() . '">' . $this->anchor->get_title() . '</a>'); // message to reader $message = $this->get_invite_default_message('PUBLISH'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url(); $menu[] = Skin::build_mail_button($link, i18n::c('View event details'), TRUE); // finalize links $message .= Skin::build_mail_menu($menu); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('PUBLISH'); // post it Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments); } } break; case 'update': // reload the anchor through the cache to reflect the update if ($reference) { $this->anchor = Anchors::get($reference, TRUE); } // no need to notify watchers after the date planned for the event, nor if the event has been initiated if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp'] > gmstrftime('%Y-%m-%d %H:%M') && isset($this->attributes['status']) && $this->attributes['status'] != 'started' && $this->attributes['status'] != 'stopped' && isset($_REQUEST['notify_watchers']) && $_REQUEST['notify_watchers'] == 'Y') { // send a confirmation message to participants $query = "SELECT * FROM " . SQL::table_name('enrolments') . " WHERE (anchor LIKE '" . $reference . "')"; $result = SQL::query($query); while ($item = SQL::fetch($result)) { // skip current surfer if (Surfer::get_id() && Surfer::get_id() == $item['user_id']) { continue; } // a user registered on this server if ($item['user_id'] && ($watcher = Users::get($item['user_id']))) { // skip banned users if ($watcher['capability'] == '?') { continue; } // ensure this surfer wants to be alerted if ($watcher['without_alerts'] == 'Y') { continue; } // sanity check if (!preg_match(VALID_RECIPIENT, $item['user_email'])) { continue; } // use this email address if ($watcher['full_name']) { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['full_name']); } else { $recipient = Mailer::encode_recipient($watcher['email'], $watcher['nick_name']); } // message title $subject = sprintf(i18n::c('Updated: %s'), strip_tags($this->anchor->get_title())); // headline $headline = sprintf(i18n::c('%s has updated %s'), Surfer::get_link(), '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url() . '">' . $this->anchor->get_title() . '</a>'); // message to reader $message = $this->get_invite_default_message('PUBLISH'); // assemble main content of this message $message = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // call for action $link = $context['url_to_home'] . $context['url_to_root'] . $this->anchor->get_url(); $menu[] = Skin::build_mail_button($link, i18n::c('View event details'), TRUE); // finalize links $message .= Skin::build_mail_menu($menu); // threads messages $headers = Mailer::set_thread($this->anchor->get_reference()); // get attachment from the overlay $attachments = $this->get_invite_attachments('PUBLISH'); // post it Mailer::notify(Surfer::from(), $recipient, $subject, $message, $headers, $attachments); } } } // bind one date to this record if (isset($this->attributes['date_stamp']) && $this->attributes['date_stamp']) { $fields = array(); $fields['anchor'] = $reference; $fields['date_stamp'] = $this->attributes['date_stamp']; // there is an existing record if ($date =& Dates::get_for_anchor($reference)) { // update the record $fields['id'] = $date['id']; if (!($id = Dates::post($fields))) { Logger::error(sprintf(i18n::s('Impossible to update date %s'), $this->attributes['date_stamp'])); return FALSE; } // create a record instead of raising an error, we are smart y'a'know } else { if (!($fields['id'] = Dates::post($fields))) { Logger::error(i18n::s('Impossible to add an item.')); return FALSE; } } } break; } // job done return TRUE; }
/** * build a notification for a new file upload * * If action is 'upload', this function builds a mail message that features: * - an image of the uploader (if possible) * - a headline mentioning the upload * - a button linked to the file page * - a link to the containing page * - the full history of all file modifications * * If action is 'multiple', then the function will use $item['message'] and * $item['anchor'] to shape the full notification message. * * Note: this function returns legacy HTML, not modern XHTML, because this is what most * e-mail client software can afford. * * @param string either 'upload' or 'multiple' * @param array attributes of the new item * @return string text to be send by e-mail */ public static function build_notification($action = 'upload', $item) { global $context; // are we processing one or several items? switch ($action) { case 'multiple': // several files have been uploaded at once // headline $headline = sprintf(i18n::c('Several files have been added by %s'), Surfer::get_link()); // the list of uploaded files is provided by caller $message = $item['message']; break; case 'upload': // one file has been uploaded // one file has been uploaded default: // headline $headline = sprintf(i18n::c('A file has been added by %s'), Surfer::get_link()); // several components in this message $details = array(); // make it visual if (isset($item['thumbnail_url']) && $item['thumbnail_url']) { $details[] = '<img src="' . $context['url_to_home'] . $item['thumbnail_url'] . '" />'; } else { $details[] = '<img src="' . $context['url_to_home'] . $context['url_to_root'] . Files::get_icon_url($item['file_name']) . '" />'; } // other details if ($item['title']) { $details[] = $item['title']; } if ($item['file_name']) { $details[] = $item['file_name']; } if ($item['file_size']) { $details[] = $item['file_size'] . ' bytes'; } if (is_array($details)) { $message = '<p>' . implode(BR, $details) . "</p>\n"; } break; } // shape the notification $text = Skin::build_mail_content($headline, $message); // a set of links $menu = array(); // link to the file if (isset($item['id'])) { $link = Files::get_permalink($item); $menu[] = Skin::build_mail_button($link, i18n::c('View file details'), TRUE); } // link to the container if (isset($item['anchor']) && ($anchor = Anchors::get($item['anchor']))) { $link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), $action == 'multiple'); } // finalize links $text .= Skin::build_mail_menu($menu); // file history if (isset($item['description']) && ($description = trim($item['description']))) { // finalize file history $text .= '<p> </p>' . '<table border="0" cellpadding="2" cellspacing="10">' . '<tr>' . '<td>' . '<font face="Helvetica, Arial, sans-serif" color="navy">' . sprintf(i18n::c('%s: %s'), i18n::c('History'), '') . '</font>' . '</td>' . '</tr>' . '<tr>' . '<td style="font-size: 10px">' . '<font face="Helvetica, Arial, sans-serif" color="navy">' . Codes::beautify($description) . '</font>' . '</td>' . '</tr>' . '</table>'; } // the full message return $text; }
/** * build a notification related to an article * * The action can be one of the following: * - 'apply' - surfer would like to get access to the page * - 'publish' - either a published page has been posted, or a draft page has been published * - 'submit' - a draft page has been posted * - 'update' - a page (draft or published) has been modified * * This function builds a mail message that displays: * - an image of the contributor (if possible) * - a headline mentioning the contribution * - the full content of the new comment * - a button linked to the reply page * - a link to the containing page * * Note: this function returns legacy HTML, not modern XHTML, because this is what most * e-mail client software can afford. * * @param string either 'apply', 'publish', 'submit' or 'update' * @param array attributes of the item * @param object overlay of the item, if any * @return string text to be send by e-mail */ public static function build_notification($action = 'publish', $item, $overlay = NULL) { global $context; // sanity check if (!isset($item['anchor']) || !($anchor = Anchors::get($item['anchor']))) { throw new Exception('no anchor for this article'); } // compute page title if (is_object($overlay)) { $title = Codes::beautify_title($overlay->get_text('title', $item)); } else { $title = Codes::beautify_title($item['title']); } // headline link to section $headline_link = '<a href="' . $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url() . '">' . $anchor->get_title() . '</a>'; // headline template switch ($action) { case 'apply': $template = i18n::c('%s is requesting access to %s'); $headline_link = '<a href="' . Articles::get_permalink($item) . '">' . $title . '</a>'; break; case 'publish': $template = i18n::c('%s has posted a page in %s'); break; case 'submit': $template = i18n::c('%s has submitted a page in %s'); break; case 'update': $template = i18n::c('%s has updated a page in %s'); break; } // headline $headline = sprintf($template, Surfer::get_link(), $headline_link); // panel content $content = ''; // more insight on this page $prefix = $suffix = ''; // signal articles to be published if (!isset($item['publish_date']) || $item['publish_date'] <= NULL_DATE || $item['publish_date'] > gmstrftime('%Y-%m-%d %H:%M:%S')) { $prefix .= DRAFT_FLAG; } // signal restricted and private articles if ($item['active'] == 'N') { $prefix .= PRIVATE_FLAG; } elseif ($item['active'] == 'R') { $prefix .= RESTRICTED_FLAG; } // flag expired articles if (isset($item['expiry_date']) && $item['expiry_date'] > NULL_DATE && $item['expiry_date'] <= $context['now']) { $prefix .= EXPIRED_FLAG . ' '; } // signal locked articles if (isset($item['locked']) && $item['locked'] == 'Y' && Articles::is_owned($item, $anchor)) { $suffix .= ' ' . LOCKED_FLAG; } // insert page title $content .= '<h3><span>' . $prefix . $title . $suffix . '</span></h3>'; // insert anchor prefix if (is_object($anchor)) { $content .= $anchor->get_prefix(); } // the introduction text, if any if (is_object($overlay)) { $content .= Skin::build_block($overlay->get_text('introduction', $item), 'introduction'); } elseif (isset($item['introduction']) && trim($item['introduction'])) { $content .= Skin::build_block($item['introduction'], 'introduction'); } // get text related to the overlay, if any if (is_object($overlay)) { $content .= $overlay->get_text('diff', $item); } // filter description, if necessary if (is_object($overlay)) { $description = $overlay->get_text('description', $item); } else { $description = $item['description']; } // the beautified description, which is the actual page body if ($description) { // use adequate label if (is_object($overlay) && ($label = $overlay->get_label('description'))) { $content .= Skin::build_block($label, 'title'); } // beautify the target page $content .= Skin::build_block($description, 'description', '', $item['options']); } // attachment details $details = array(); // avoid first file in list if mentioned in last comment $file_offset = 0; // comments include_once $context['path_to_root'] . 'comments/comments.php'; if ($count = Comments::count_for_anchor('article:' . $item['id'], TRUE)) { // get last contribution for this page if ($comment = Comments::get_newest_for_anchor('article:' . $item['id'])) { if (preg_match('/\\[(download|file)=/', $comment['description'])) { $file_offset++; } // bars around the last contribution $bottom_menu = array(); // last contributor $contributor = Users::get_link($comment['create_name'], $comment['create_address'], $comment['create_id']); $flag = ''; if ($comment['create_date'] >= $context['fresh']) { $flag = NEW_FLAG; } elseif ($comment['edit_date'] >= $context['fresh']) { $flag = UPDATED_FLAG; } $bottom_menu[] = sprintf(i18n::s('By %s'), $contributor) . ' ' . Skin::build_date($comment['create_date']) . $flag; // gather pieces $pieces = array(); // last contribution, and user signature $pieces[] = ucfirst(trim($comment['description'])) . Users::get_signature($comment['create_id']); // bottom if ($bottom_menu) { $pieces[] = '<div>' . ucfirst(trim(Skin::finalize_list($bottom_menu, 'menu'))) . '</div>'; } // put all pieces together $content .= '<div>' . "\n" . join("\n", $pieces) . '</div>' . "\n"; } // count comments $details[] = sprintf(i18n::nc('%d comment', '%d comments', $count), $count); } // info on related files if ($count = Files::count_for_anchor('article:' . $item['id'])) { // most recent files attached to this page if ($items = Files::list_by_date_for_anchor('article:' . $item['id'], $file_offset, 3, 'dates')) { // more files than listed $more = ''; if ($count > 3) { $more = '<span class="details">' . sprintf(i18n::s('%d files, including:'), $count) . '</span>'; } if (is_array($items)) { $items = Skin::build_list($items, 'compact'); } $items = '<div>' . $more . $items . '</div>'; } // wrap it with some header if ($items) { $content .= '<h3><span>' . i18n::c('Files') . '</span></h3>' . $items; } // count files $details[] = sprintf(i18n::nc('%d file', '%d files', $count), $count); } // info on related links include_once $context['path_to_root'] . 'links/links.php'; if ($count = Links::count_for_anchor('article:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::nc('%d link', '%d links', $count), $count); } // describe attachments if (count($details)) { $content .= '<hr align="left" size=1" width="150">' . '<p>' . sprintf(i18n::c('This page has %s'), join(', ', $details)) . '</p>'; } // assemble main content of this message $text = Skin::build_mail_content($headline, $content); // a set of links $menu = array(); // request access to the item if ($action == 'apply') { // call for action $link = $context['url_to_home'] . $context['url_to_root'] . Articles::get_url($item['id'], 'invite', Surfer::get_id()); $label = sprintf(i18n::c('Invite %s to participate'), Surfer::get_name()); $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to user profile $link = Surfer::get_permalink(); $label = sprintf(i18n::c('View the profile of %s'), Surfer::get_name()); $menu[] = Skin::build_mail_button($link, $label, FALSE); // invite to visit the item } else { // call for action $link = Articles::get_permalink($item); if (!is_object($overlay) || !($label = $overlay->get_label('permalink_command', 'articles', FALSE))) { $label = i18n::c('View the page'); } $menu[] = Skin::build_mail_button($link, $label, TRUE); // link to the container $link = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url(); $menu[] = Skin::build_mail_button($link, $anchor->get_title(), FALSE); } // finalize links $text .= Skin::build_mail_menu($menu); // the full message return $text; }