die(i18n::s('You are not allowed to perform this operation.')); // a new contribution has been submitted } elseif (isset($_REQUEST['message']) && trim($_REQUEST['message'])) { // sanitize the message $_REQUEST['message'] = str_replace(array("\r\n", "\r"), "\n", trim($_REQUEST['message'])); // protect from hackers if (isset($_REQUEST['edit_name'])) { $_REQUEST['edit_name'] = preg_replace(FORBIDDEN_IN_NAMES, '_', $_REQUEST['edit_name']); } if (isset($_REQUEST['edit_address'])) { $_REQUEST['edit_address'] = encode_link($_REQUEST['edit_address']); } // append to previous comment during 10 minutes $continuity_limit = gmstrftime('%Y-%m-%d %H:%M:%S', time() - 600); // this is the first contribution to the thread if (!($item = Comments::get_newest_for_anchor($anchor->get_reference()))) { $fields = array(); $fields['anchor'] = $anchor->get_reference(); $fields['description'] = $_REQUEST['message']; // this is a continuated contribution from this authenticated surfer } elseif ($item['type'] != 'notification' && Surfer::get_id() && (isset($item['create_id']) && Surfer::get_id() == $item['create_id']) && $continuity_limit < $item['edit_date']) { $item['description'] .= BR . $_REQUEST['message']; $fields = $item; // else process the contribution as a new comment } else { $fields = array(); $fields['anchor'] = $anchor->get_reference(); $fields['description'] = $_REQUEST['message']; } // actual database update if (!($fields['id'] = Comments::post($fields))) {
/** * remember the last action for this article * * This function is called by related items. What does it do? * - On image creation, the adequate code is added to the description field to let the image be displayed inline * - On icon selection, the icon field is updated * - On thumbnail image selection, the thumbnail image field is updated * - On location creation, some code is inserted in the description field to display location name inline * - On table creation, some code is inserted in the description field to display the table inline * * @see articles/article.php * @see articles/edit.php * @see shared/anchor.php * * @param string one of the pre-defined action code * @param string the id of the item related to this update * @param boolean TRUE to not change the edit date of this anchor, default is FALSE */ function touch($action, $origin = NULL, $silently = FALSE) { global $context; // we make extensive use of comments below include_once $context['path_to_root'] . 'comments/comments.php'; // don't go further on import if (preg_match('/import$/i', $action)) { return; } // no article bound if (!isset($this->item['id'])) { return; } // delegate to overlay if (is_object($this->overlay) && $this->overlay->touch($action, $origin, $silently) === false) { return; // stop on false } // clear floating objects if ($action == 'clear') { $this->item['description'] .= ' [clear]'; $query = "UPDATE " . SQL::table_name('articles') . " SET description='" . SQL::escape($this->item['description']) . "'" . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query); return; } // get the related overlay, if any if (!isset($this->overlay)) { $this->overlay = NULL; if (isset($this->item['overlay'])) { $this->overlay = Overlay::load($this->item, 'article:' . $this->item['id']); } } // components of the query $query = array(); // a new comment has been posted if ($action == 'comment:create') { // purge oldest comments Comments::purge_for_anchor('article:' . $this->item['id']); // file upload } elseif ($action == 'file:create' || $action == 'file:upload') { // actually, several files have been added $label = ''; if (!$origin) { // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { // remember this as an automatic notification $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = i18n::s('Several files have been added'); $fields['type'] = 'notification'; Comments::post($fields); } // one file has been added } elseif (!Codes::check_embedded($this->item['description'], 'embed', $origin) && ($item = Files::get($origin, TRUE))) { // this file is eligible for being embedded in the page if (isset($item['file_name']) && Files::is_embeddable($item['file_name'])) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { $label = '[embed=' . $origin . ']'; } // else add a comment to take note of the upload } else { // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { // remember this as an automatic notification $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; if ($action == 'file:create') { $fields['description'] = '[file=' . $item['id'] . ',' . $item['file_name'] . ']'; } else { $fields['description'] = '[download=' . $item['id'] . ',' . $item['file_name'] . ']'; } Comments::post($fields); } } } // we are in some interactive thread if ($origin && $this->has_option('view_as_chat')) { // default is to download the file if (!$label) { $label = '[download=' . $origin . ']'; } // this is the first contribution to the thread if (!($comment = Comments::get_newest_for_anchor('article:' . $this->item['id']))) { $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = $label; // this is a continuated contribution from this authenticated surfer } elseif ($comment['type'] != 'notification' && Surfer::get_id() && (isset($comment['create_id']) && Surfer::get_id() == $comment['create_id'])) { $comment['description'] .= BR . $label; $fields = $comment; // else process the contribution as a new comment } else { $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = $label; } // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { Comments::post($fields); } // include flash videos in a regular page } elseif ($origin && $label) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' ' . $label) . "'"; } // suppress references to a deleted file } elseif ($action == 'file:delete' && $origin) { // suppress reference in main description field $text = Codes::delete_embedded($this->item['description'], 'download', $origin); $text = Codes::delete_embedded($text, 'embed', $origin); $text = Codes::delete_embedded($text, 'file', $origin); // save changes $query[] = "description = '" . SQL::escape($text) . "'"; // append a reference to a new image to the description } elseif ($action == 'image:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { // list has already started if (preg_match('/\\[image=[^\\]]+?\\]\\s*$/', $this->item['description'])) { $this->item['description'] .= ' [image=' . $origin . ']'; } else { $this->item['description'] .= "\n\n" . '[image=' . $origin . ']'; } $query[] = "description = '" . SQL::escape($this->item['description']) . "'"; } } // also use it as thumnail if none has been defined yet if (!isset($this->item['thumbnail_url']) || !trim($this->item['thumbnail_url'])) { include_once $context['path_to_root'] . 'images/images.php'; if (($image = Images::get($origin)) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // refresh stamp only if image update occurs within 6 hours after last edition if (SQL::strtotime($this->item['edit_date']) + 6 * 60 * 60 < time()) { $silently = TRUE; } // suppress a reference to an image that has been deleted } elseif ($action == 'image:delete' && $origin) { // suppress reference in main description field $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'image', $origin)) . "'"; // suppress references as icon and thumbnail as well include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } if ($url = Images::get_thumbnail_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } } // set an existing image as the article icon } elseif ($action == 'image:set_as_icon' && $origin) { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { $query[] = "icon_url = '" . SQL::escape($url) . "'"; } // also use it as thumnail if none has been defined yet if (!(isset($this->item['thumbnail_url']) && trim($this->item['thumbnail_url'])) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // set an existing image as the article thumbnail } elseif ($action == 'image:set_as_thumbnail' && $origin) { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // append a new image, and set it as the article thumbnail } elseif ($action == 'image:set_as_both' && $origin) { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // add a reference to a location in the article description } elseif ($action == 'location:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'location', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [location=' . $origin . ']') . "'"; } // suppress a reference to a location that has been deleted } elseif ($action == 'location:delete' && $origin) { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'location', $origin)) . "'"; // add a reference to a new table in the article description } elseif ($action == 'table:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'table', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . "\n" . '[table=' . $origin . ']' . "\n") . "'"; } // suppress a reference to a table that has been deleted } elseif ($action == 'table:delete' && $origin) { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'table', $origin)) . "'"; } // stamp the update if (!$silently) { $query[] = "edit_name='" . SQL::escape(Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(Surfer::get_id()) . "," . "edit_address='" . SQL::escape(Surfer::get_email_address()) . "'," . "edit_action='" . SQL::escape($action) . "'," . "edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; } // update the database if (count($query)) { $query = "UPDATE " . SQL::table_name('articles') . " SET " . implode(', ', $query) . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query); } // add this page to the watch list of the contributor, on any action if (Surfer::get_id()) { Members::assign('article:' . $this->item['id'], 'user:'******'article:' . $this->item['id'], $this->item['active']); // always clear the cache, even on no update Articles::clear($this->item); // get the parent if (!$this->anchor) { $this->anchor = Anchors::get($this->item['anchor']); } // propagate the touch upwards if (is_object($this->anchor)) { $this->anchor->touch('article:update', $this->item['id'], TRUE); } }
/** * 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; }
/** * list articles as topics in a forum * * @param resource the SQL result * @return string the rendered text **/ function layout($result) { global $context; // we return some text $text = ''; // empty list if (!SQL::count($result)) { return $text; } // allow for complete styling $text = '<div class="last_articles">'; // build a list of articles include_once $context['path_to_root'] . 'comments/comments.php'; include_once $context['path_to_root'] . 'links/links.php'; while ($item = SQL::fetch($result)) { // get the related overlay $overlay = Overlay::load($item, 'article:' . $item['id']); // get the anchor $anchor = Anchors::get($item['anchor']); // the url to view this item $url = Articles::get_permalink($item); // build a title if (is_object($overlay)) { $title = Codes::beautify_title($overlay->get_text('title', $item)); } else { $title = Codes::beautify_title($item['title']); } // reset everything $prefix = $label = $suffix = $icon = ''; // 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 ($item['expiry_date'] > NULL_DATE && $item['expiry_date'] <= $context['now']) { $prefix .= EXPIRED_FLAG . ' '; } elseif ($item['create_date'] >= $context['fresh']) { $suffix .= NEW_FLAG; } elseif ($item['edit_date'] >= $context['fresh']) { $suffix .= UPDATED_FLAG; } // signal locked articles if (isset($item['locked']) && $item['locked'] == 'Y' && Articles::is_owned($item, $anchor)) { $suffix .= ' ' . LOCKED_FLAG; } // rating if ($item['rating_count'] && !(is_object($anchor) && $anchor->has_option('without_rating'))) { $suffix .= ' ' . Skin::build_link(Articles::get_url($item['id'], 'like'), Skin::build_rating_img((int) round($item['rating_sum'] / $item['rating_count'])), 'basic'); } // indicate the id in the hovering popup $hover = i18n::s('View the page'); if (Surfer::is_member()) { $hover .= ' [article=' . $item['id'] . ']'; } // one box per update $text .= '<div class="last_article" >'; // use the title as a link to the page $text .= Skin::build_block($prefix . ucfirst($title) . $suffix, 'header1'); // some details about this page $details = array(); // page starter and date if ($item['create_name']) { $details[] = sprintf(i18n::s('Started by %s'), Users::get_link($item['create_name'], $item['create_address'], $item['create_id'])) . ' ' . Skin::build_date($item['create_date']); } // page last modification if ($item['edit_date'] && $item['edit_action'] == 'article:update' && $item['edit_name']) { $details[] = Anchors::get_action_label($item['edit_action']) . ' ' . sprintf(i18n::s('by %s'), Users::get_link($item['edit_name'], $item['edit_address'], $item['edit_id'])) . ' ' . Skin::build_date($item['edit_date']); } // friends if ($friends =& Members::list_users_by_posts_for_anchor('article:' . $item['id'], 0, USERS_LIST_SIZE, 'comma5', $item['create_id'])) { $details[] = sprintf(i18n::s('with %s'), $friends); } // people details if ($details) { $text .= '<p class="details">' . join(', ', $details) . "</p>\n"; } // the introductory text $introduction = ''; if (is_object($overlay)) { $introduction = $overlay->get_text('introduction', $item); } elseif ($item['introduction']) { $introduction = $item['introduction']; } if ($introduction) { $text .= '<div style="margin: 1em 0;">' . Codes::beautify_introduction($introduction) . '</div>'; } // insert overlay data, if any if (is_object($overlay)) { $text .= $overlay->get_text('list', $item); } // info on related comments if (($count = Comments::count_for_anchor('article:' . $item['id'])) > 1) { $text .= '<div style="margin-top: 1em;"><p class="details">' . sprintf(i18n::s('%d contributions, including:'), $count) . '</p></div>'; } // avoid first file if mentioned in last contribution $file_offset = 0; // 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; // offer to reply if (Comments::allow_creation($item, $anchor)) { $link = Comments::get_url($comment['id'], 'reply'); $bottom_menu[] = Skin::build_link($link, i18n::s('Reply'), 'basic'); } // 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 style="margin-top: 1em;">' . ucfirst(trim(Skin::finalize_list($bottom_menu, 'menu'))) . '</div>'; } // put all pieces together $text .= '<div class="last_comment">' . "\n" . join("\n", $pieces) . '</div>' . "\n"; } // list more recent files if ($items = Files::list_by_date_for_anchor('article:' . $item['id'], $file_offset, 3, 'dates')) { // more files than listed $more = ''; if (($count = Files::count_for_anchor('article:' . $item['id'])) > 3) { $more = '<span class="details">' . sprintf(i18n::s('%d files, including:'), $count) . '</span>'; } if (is_array($items)) { $items = Skin::build_list($items, 'compact'); } $text .= '<div style="margin: 1em 0;">' . $more . $items . '</div>'; } // display all tags if ($item['tags']) { $text .= ' <p class="tags">' . Skin::build_tags($item['tags'], 'article:' . $item['id']) . '</p>'; } // navigation links $menu = array(); // permalink $menu[] = Skin::build_link($url, i18n::s('View the page'), 'span'); // info on related links if ($count = Links::count_for_anchor('article:' . $item['id'], TRUE)) { $menu[] = sprintf(i18n::ns('%d link', '%d links', $count), $count); } // the main anchor link if (is_object($anchor) && (!isset($this->focus) || $item['anchor'] != $this->focus)) { $menu[] = Skin::build_link($anchor->get_url(), sprintf(i18n::s('in %s'), ucfirst($anchor->get_title())), 'span', i18n::s('View the section')); } // actually insert details $text .= Skin::finalize_list($menu, 'menu_bar'); // bottom of the box $text .= '</div>'; } // close the list of articles $text .= '</div>'; // beautify everything at once $text = Codes::beautify($text); // end of processing SQL::free($result); // done return $text; }
if (isset($_REQUEST['edit_name'])) { $_REQUEST['edit_name'] = preg_replace(FORBIDDEN_IN_NAMES, '_', $_REQUEST['edit_name']); } if (isset($_REQUEST['edit_address'])) { $_REQUEST['edit_address'] = encode_link($_REQUEST['edit_address']); } // track anonymous surfers Surfer::track($_REQUEST); // remove default string, if any $_REQUEST['description'] = preg_replace('/^' . preg_quote(i18n::s('Contribute to this page!'), '/') . '/', '', ltrim($_REQUEST['description'])); // hardcode line breaks if no WYSIWYG editor if (!isset($_REQUEST['editor'])) { $_REQUEST['description'] = str_replace("\n", BR, $_REQUEST['description']); } // append to previous comment during 10 secondes if (!isset($item['id']) && ($newest = Comments::get_newest_for_anchor($anchor->get_reference())) && $newest['type'] != 'notification' && Surfer::get_id() && (isset($newest['create_id']) && Surfer::get_id() == $newest['create_id']) && $newest['edit_date'] > gmstrftime('%Y-%m-%d %H:%M:%S', time() - 10)) { // copy from previous comment record $_REQUEST['id'] = $newest['id']; $_REQUEST['create_address'] = $newest['create_address']; $_REQUEST['create_date'] = $newest['create_date']; $_REQUEST['create_id'] = $newest['create_id']; $_REQUEST['create_name'] = $newest['create_name']; $_REQUEST['description'] = $newest['description'] . BR . $_REQUEST['description']; $_REQUEST['previous_id'] = $newest['previous_id']; $_REQUEST['type'] = $newest['type']; } // attach some file $file_path = Files::get_path($anchor->get_reference()); if (isset($_FILES['upload']) && ($uploaded = Files::upload($_FILES['upload'], $file_path, $anchor->get_reference()))) { // sanity check if (!$_REQUEST['description']) {