示例#1
0
// post an image, if upload is allowed
if (Images::allow_creation($item, $anchor, 'section')) {
    Skin::define_img('IMAGES_ADD_IMG', 'images/add.gif');
    $context['page_tools'][] = Skin::build_link('images/edit.php?anchor=' . urlencode('section:' . $item['id']), IMAGES_ADD_IMG . i18n::s('Add an image'), 'basic', i18n::s('You can upload a camera shot, a drawing, or another image file.'));
}
// ensure that the surfer can change content
if (Sections::allow_modification($item, $anchor)) {
    // modify this page
    Skin::define_img('SECTIONS_EDIT_IMG', 'sections/edit.gif');
    if (!is_object($overlay) || !($label = $overlay->get_label('edit_command', 'sections'))) {
        $label = i18n::s('Edit this section');
    }
    $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'edit'), SECTIONS_EDIT_IMG . $label, 'basic', i18n::s('Press [e] to edit'), FALSE, 'e');
}
// commands for section owners
if (Sections::is_owned($item, $anchor) || Surfer::is_associate()) {
    // access previous versions, if any
    if ($has_versions) {
        Skin::define_img('SECTIONS_VERSIONS_IMG', 'sections/versions.gif');
        $context['page_tools'][] = Skin::build_link(Versions::get_url('section:' . $item['id'], 'list'), SECTIONS_VERSIONS_IMG . i18n::s('Versions'), 'basic', i18n::s('Restore a previous version if necessary'));
    }
    // lock the page
    if (!isset($item['locked']) || $item['locked'] == 'N') {
        Skin::define_img('SECTIONS_LOCK_IMG', 'sections/lock.gif');
        $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'lock'), SECTIONS_LOCK_IMG . i18n::s('Lock'), 'basic');
    } else {
        Skin::define_img('SECTIONS_UNLOCK_IMG', 'sections/unlock.gif');
        $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'lock'), SECTIONS_UNLOCK_IMG . i18n::s('Unlock'), 'basic');
    }
    // delete the page
    Skin::define_img('SECTIONS_DELETE_IMG', 'sections/delete.gif');
示例#2
0
文件: links.php 项目: rair/yacs
 /**
  * check if new links can be added
  *
  * This function returns TRUE if links can be added to some place,
  * and FALSE otherwise.
  *
  * @param object an instance of the Anchor interface, if any
  * @param array a set of item attributes, if any
  * @param string the type of item, e.g., 'section'
  * @return boolean TRUE or FALSE
  */
 public static function allow_creation($item = NULL, $anchor = NULL, $variant = NULL)
 {
     global $context;
     // backward compatibility, reverse parameters :
     // $anchor is always a object and $item a array
     if (is_object($item) || is_array($anchor)) {
         $permute = $anchor;
         $anchor = $item;
         $item = $permute;
     }
     // guess the variant
     if (!$variant) {
         // most frequent case
         if (isset($item['id'])) {
             $variant = 'article';
         } elseif (is_object($anchor)) {
             $variant = $anchor->get_type();
         } else {
             return FALSE;
         }
     }
     // only in articles
     if ($variant == 'article') {
         // 'no_links' option
         if (Articles::has_option('no_links', $anchor, $item)) {
             return FALSE;
         }
         // other containers
     } else {
         // links have to be activated
         if (isset($item['options']) && is_string($item['options']) && preg_match('/\\bwith_links\\b/i', $item['options'])) {
         } elseif (!isset($item['id']) && is_object($anchor) && $anchor->has_option('with_links', FALSE)) {
         } else {
             return FALSE;
         }
     }
     // surfer is an associate
     if (Surfer::is_associate()) {
         return TRUE;
     }
     // submissions have been disallowed
     if (isset($context['users_without_submission']) && $context['users_without_submission'] == 'Y') {
         return FALSE;
     }
     // only in articles
     if ($variant == 'article') {
         // surfer owns this item, or the anchor
         if (Articles::is_owned($item, $anchor)) {
             return TRUE;
         }
         // surfer is an editor, and the page is not private
         if (isset($item['active']) && $item['active'] != 'N' && Articles::is_assigned($item['id'])) {
             return TRUE;
         }
         // only in sections
     } elseif ($variant == 'section') {
         // surfer owns this item, or the anchor
         if (Sections::is_owned($item, $anchor, TRUE)) {
             return TRUE;
         }
         // surfer is an editor, and the section is not private
         if (isset($item['active']) && $item['active'] != 'N' && Sections::is_assigned($item['id'])) {
             return TRUE;
         }
     }
     // surfer is an editor, and container is not private
     if (isset($item['active']) && $item['active'] != 'N' && is_object($anchor) && $anchor->is_assigned()) {
         return TRUE;
     }
     if (!isset($item['id']) && is_object($anchor) && !$anchor->is_hidden() && $anchor->is_assigned()) {
         return TRUE;
     }
     // item has been locked
     if (isset($item['locked']) && $item['locked'] == 'Y') {
         return FALSE;
     }
     // anchor has been locked --only used when there is no item provided
     if (!isset($item['id']) && is_object($anchor) && $anchor->has_option('locked')) {
         return FALSE;
     }
     // surfer is an editor (and item has not been locked)
     if ($variant == 'article' && isset($item['id']) && Articles::is_assigned($item['id'])) {
         return TRUE;
     }
     if ($variant == 'section' && isset($item['id']) && Sections::is_assigned($item['id'])) {
         return TRUE;
     }
     if (is_object($anchor) && $anchor->is_assigned()) {
         return TRUE;
     }
     // container is hidden
     if (isset($item['active']) && $item['active'] == 'N') {
         return FALSE;
     }
     if (is_object($anchor) && $anchor->is_hidden()) {
         return FALSE;
     }
     // authenticated members and subscribers are allowed to add links
     if (Surfer::is_logged()) {
         return TRUE;
     }
     // container is restricted
     if (isset($item['active']) && $item['active'] == 'R') {
         return FALSE;
     }
     if (is_object($anchor) && !$anchor->is_public()) {
         return FALSE;
     }
     // anonymous contributions are allowed for articles
     if ($variant == 'article') {
         if (isset($item['options']) && preg_match('/\\banonymous_edit\\b/i', $item['options'])) {
             return TRUE;
         }
         if (is_object($anchor) && $anchor->has_option('anonymous_edit')) {
             return TRUE;
         }
     }
     // the default is to not allow for new links
     return FALSE;
 }
示例#3
0
文件: sections.php 项目: rair/yacs
 /**
  * document modification dates for this item
  *
  * @param object anchor of the section
  * @param array the section to be documented
  * @return array strings detailed labels
  */
 public static function &build_dates($anchor, $item)
 {
     global $context;
     // we return an array of strings
     $details = array();
     // we do want details for this page
     if (strpos($item['options'], 'with_details') !== FALSE) {
     } elseif (isset($context['content_without_details']) && $context['content_without_details'] == 'Y' && !Sections::is_owned($item, $anchor)) {
         return $details;
     }
     // last modification
     if ($item['edit_action']) {
         $action = Anchors::get_action_label($item['edit_action']) . ' ';
     } else {
         $action = i18n::s('edited');
     }
     if ($item['edit_name']) {
         $details[] = sprintf(i18n::s('%s by %s %s'), $action, Users::get_link($item['edit_name'], $item['edit_address'], $item['edit_id']), Skin::build_date($item['edit_date']));
     } else {
         $details[] = $action . ' ' . Skin::build_date($item['edit_date']);
     }
     // post date and author
     if ($item['create_date']) {
         // creation and last modification happen on same day by the same person
         if (!strcmp(substr($item['create_date'], 0, 10), substr($item['edit_date'], 0, 10)) && $item['create_id'] == $item['edit_id']) {
         } elseif ($item['create_name']) {
             $details[] = sprintf(i18n::s('posted by %s %s'), Users::get_link($item['create_name'], $item['create_address'], $item['create_id']), Skin::build_date($item['create_date']));
         } else {
             $details[] = Skin::build_date($item['create_date']);
         }
     }
     // job done
     return $details;
 }
示例#4
0
文件: invite.php 项目: rair/yacs
     $hint = i18n::s('Let us a chance to know who you are');
     $fields[] = array($label, $input, $hint);
     // the address, if any
     $label = i18n::s('Your e-mail address');
     $input = '<input type="text" name="edit_address" size="45" maxlength="128" accesskey="a" value="' . encode_field(Surfer::get_email_address()) . '" />';
     $hint = i18n::s('Put your e-mail address to receive feed-back');
     $fields[] = array($label, $input, $hint);
     // stop robots
     if ($field = Surfer::get_robot_stopper()) {
         $fields[] = $field;
     }
 }
 // recipients
 $label = i18n::s('Invite participants');
 $input = '';
 if (Sections::is_owned($item, $anchor, TRUE)) {
     // roles are defined as per invitation settings
     if (is_callable(array($overlay, 'get_invite_roles'))) {
         $input .= $overlay->get_invite_roles();
     } elseif ($item['active'] != 'N') {
         $input .= '<p><input type="radio" name="provide_credentials" value="N" checked="checked" /> ' . i18n::s('to review public content (watchers)') . BR . '<input type="radio" name="provide_credentials" value="Y" /> ' . i18n::s('to manage public and private content (editors)') . '</p>' . '<hr/>';
     }
 }
 // get a customized layout
 $layout = Layouts::new_('mail', 'user');
 // avoid links to this page
 if (is_object($layout) && is_callable(array($layout, 'set_variant'))) {
     $layout->set_variant('unchecked');
 }
 // pre-invite someone
 $invited = '';
示例#5
0
文件: view.php 项目: rair/yacs
        } else {
            Skin::define_img('SECTIONS_UNLOCK_IMG', 'sections/unlock.gif');
            $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'lock'), SECTIONS_UNLOCK_IMG . i18n::s('Unlock'), 'basic');
        }
        // delete the page
        if ($cur_section->allows('deletion')) {
            Skin::define_img('SECTIONS_DELETE_IMG', 'sections/delete.gif');
            if (!is_object($overlay) || !($label = $overlay->get_label('delete_command', 'sections'))) {
                $label = i18n::s('Delete this section');
            }
            $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'delete'), SECTIONS_DELETE_IMG . $label, 'basic');
        }
        // manage content
        if ($has_content) {
            Skin::define_img('SECTIONS_MANAGE_IMG', 'sections/manage.gif');
            $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'manage'), SECTIONS_MANAGE_IMG . i18n::s('Manage content'), 'basic', i18n::s('Bulk operations'));
        }
        // duplicate command provided to container owners
        if (Sections::is_owned(NULL, $anchor) || Surfer::is_associate()) {
            Skin::define_img('SECTIONS_DUPLICATE_IMG', 'sections/duplicate.gif');
            $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'duplicate'), SECTIONS_DUPLICATE_IMG . i18n::s('Duplicate this section'));
        }
    }
    // commands for associates
    if (Surfer::is_associate()) {
        Skin::define_img('SECTIONS_DUPLICATE_IMG', 'sections/duplicate.gif');
        $context['page_tools'][] = Skin::build_link(Sections::get_url($item['id'], 'export'), SECTIONS_DUPLICATE_IMG . i18n::s('Export this section'));
    }
}
// render the skin
render_skin();
示例#6
0
文件: view.php 项目: rair/yacs
    $id = $_REQUEST['id'];
} elseif (isset($context['arguments'][0])) {
    $id = $context['arguments'][0];
}
$id = strip_tags($id);
// get the item from the database
$item = Versions::get($id);
// get the related anchor, if any
$anchor = NULL;
if (isset($item['anchor']) && $item['anchor']) {
    $anchor = Anchors::get($item['anchor']);
}
// you have to own the object to handle versions
if (is_object($anchor) && $anchor->is_owned()) {
    $permitted = TRUE;
} elseif (is_object($anchor) && $anchor->get_type() == 'section' && Sections::is_owned(NULL, $anchor)) {
    $permitted = TRUE;
} else {
    $permitted = FALSE;
}
// load the skin, maybe with a variant
load_skin('versions', $anchor);
// clear the tab we are in, if any
if (is_object($anchor)) {
    $context['current_focus'] = $anchor->get_focus();
}
// current item
if (isset($item['id'])) {
    $context['current_item'] = 'version:' . $item['id'];
}
// the path to this page
示例#7
0
文件: files.php 项目: rair/yacs
 /**
  * check if new files can be added
  *
  * This function returns TRUE if files can be added to some place,
  * and FALSE otherwise.
  *
  * @param array a set of item attributes, if any
  * @param object an instance of the Anchor interface, if any
  * @param string the type of item, e.g., 'article' or 'section'
  * @return boolean TRUE or FALSE
  */
 public static function allow_creation($item = NULL, $anchor = NULL, $variant = NULL)
 {
     global $context;
     // guess the variant
     if (!$variant) {
         // most frequent case
         if (isset($item['id'])) {
             $variant = 'article';
         } elseif (is_object($anchor)) {
             $variant = $anchor->get_type();
         } else {
             return FALSE;
         }
     }
     // attach a file to an article
     if ($variant == 'article') {
         // 'no initial upload' option
         if (!isset($item['id']) && Articles::has_option('no_initial_upload', $anchor, $item)) {
             return FALSE;
         }
         // 'no files' option
         if (Articles::has_option('no_files', $anchor, $item)) {
             return FALSE;
         }
         // attach a file to a user profile
     } elseif ($variant == 'user') {
         // associates can always proceed
         if (Surfer::is_associate()) {
         } elseif (!is_object($anchor) || !Surfer::get_id()) {
             return FALSE;
         } elseif ($anchor->get_reference() != 'user:'******'options']) && is_string($item['options']) && preg_match('/\\bwith_files\\b/i', $item['options'])) {
         } elseif (!isset($item['id']) && is_object($anchor) && $anchor->has_option('with_files', FALSE)) {
         } else {
             return FALSE;
         }
     }
     // surfer is not allowed to upload a file
     if (!Surfer::may_upload()) {
         return FALSE;
     }
     // surfer is an associate
     if (Surfer::is_associate()) {
         return TRUE;
     }
     // submissions have been disallowed
     if (isset($context['users_without_submission']) && $context['users_without_submission'] == 'Y') {
         return FALSE;
     }
     // only in articles
     if ($variant == 'article') {
         // surfer owns this item, or the anchor
         if (Articles::is_owned($item, $anchor)) {
             return TRUE;
         }
         // surfer is an editor, and the page is not private
         if (isset($item['active']) && $item['active'] != 'N' && Articles::is_assigned($item['id'])) {
             return TRUE;
         }
         // only in sections
     } elseif ($variant == 'section') {
         // surfer owns this item, or the anchor
         if (Sections::is_owned($item, $anchor, TRUE)) {
             return TRUE;
         }
         // surfer is an editor, and the section is not private
         if (isset($item['active']) && $item['active'] != 'N' && Sections::is_assigned($item['id'])) {
             return TRUE;
         }
     }
     // surfer is an editor, and container is not private
     if (isset($item['active']) && $item['active'] != 'N' && is_object($anchor) && $anchor->is_assigned()) {
         return TRUE;
     }
     if (!isset($item['id']) && is_object($anchor) && !$anchor->is_hidden() && $anchor->is_assigned()) {
         return TRUE;
     }
     // item has been locked
     if (isset($item['locked']) && $item['locked'] == 'Y') {
         return FALSE;
     }
     // anchor has been locked --only used when there is no item provided
     if (!isset($item['id']) && is_object($anchor) && $anchor->has_option('locked')) {
         return FALSE;
     }
     // surfer is an editor (and item has not been locked)
     if ($variant == 'article' && isset($item['id']) && Articles::is_assigned($item['id'])) {
         return TRUE;
     }
     if ($variant == 'section' && isset($item['id']) && Sections::is_assigned($item['id'])) {
         return TRUE;
     }
     if (is_object($anchor) && $anchor->is_assigned()) {
         return TRUE;
     }
     // container is hidden
     if (isset($item['active']) && $item['active'] == 'N') {
         return FALSE;
     }
     if (is_object($anchor) && $anchor->is_hidden()) {
         return FALSE;
     }
     // authenticated members and subscribers are allowed to add files
     if (Surfer::is_logged()) {
         return TRUE;
     }
     // container is restricted
     if (isset($item['active']) && $item['active'] == 'R') {
         return FALSE;
     }
     if (is_object($anchor) && !$anchor->is_public()) {
         return FALSE;
     }
     // anonymous contributions are allowed for articles and for sections
     if ($variant == 'article' || $variant == 'section') {
         if (isset($item['options']) && preg_match('/\\banonymous_edit\\b/i', $item['options'])) {
             return TRUE;
         }
         if (is_object($anchor) && $anchor->has_option('anonymous_edit')) {
             return TRUE;
         }
     }
     // the default is to not allow for new files
     return FALSE;
 }
示例#8
0
文件: articles.php 项目: rair/yacs
 /**
  * check if new articles can be added
  *
  * This function returns TRUE if articles can be added to some place,
  * and FALSE otherwise.
  *
  * @param array a set of item attributes, if any --always a section
  * @param object an instance of the Anchor interface, if any
  * @return boolean TRUE or FALSE
  */
 public static function allow_creation($item, $anchor = NULL)
 {
     global $context;
     // articles are prevented in item, through layout
     if (isset($item['articles_layout']) && $item['articles_layout'] == 'none') {
         return FALSE;
     }
     // surfer is an associate
     if (Surfer::is_associate()) {
         return TRUE;
     }
     // submissions have been disallowed
     if (isset($context['users_without_submission']) && $context['users_without_submission'] == 'Y') {
         return FALSE;
     }
     // surfer owns this item, or the anchor
     if (Sections::is_owned($item, $anchor, TRUE)) {
         return TRUE;
     }
     // not for subscribers
     if (Surfer::is_member()) {
         // surfer is an editor, and the section is not private
         if (isset($item['active']) && $item['active'] != 'N' && Sections::is_assigned($item['id'])) {
             return TRUE;
         }
         if (isset($item['active']) && $item['active'] != 'N' && is_object($anchor) && $anchor->is_assigned()) {
             return TRUE;
         }
         if (!isset($item['id']) && is_object($anchor) && !$anchor->is_hidden() && $anchor->is_assigned()) {
             return TRUE;
         }
     }
     // container has been locked
     if (isset($item['locked']) && $item['locked'] == 'Y') {
         return FALSE;
     }
     // anchor has been locked
     if (!isset($item['id']) && is_object($anchor) && $anchor->has_option('locked')) {
         return FALSE;
     }
     // anonymous contributions are allowed for articles
     if (isset($item['options']) && preg_match('/\\banonymous_edit\\b/i', $item['options'])) {
         return TRUE;
     }
     if (is_object($anchor) && $anchor->has_option('anonymous_edit')) {
         return TRUE;
     }
     // subscribers can contribute too
     if (Surfer::is_logged() && isset($item['options']) && preg_match('/\\bmembers_edit\\b/i', $item['options'])) {
         return TRUE;
     }
     if (Surfer::is_logged() && is_object($anchor) && $anchor->has_option('members_edit')) {
         return TRUE;
     }
     // not for subscribers
     if (Surfer::is_member()) {
         // surfer is an editor (and item has not been locked)
         if (isset($item['id']) && Sections::is_assigned($item['id'])) {
             return TRUE;
         }
         if (is_object($anchor) && $anchor->is_assigned()) {
             return TRUE;
         }
     }
     // container is hidden
     if (isset($item['active']) && $item['active'] == 'N') {
         return FALSE;
     }
     if (is_object($anchor) && $anchor->is_hidden()) {
         return FALSE;
     }
     // surfer is a member
     if (Surfer::is_member()) {
         return TRUE;
     }
     // the default is to not allow for new articles
     return FALSE;
 }
示例#9
0
文件: lock.php 项目: rair/yacs
    $context['path_bar'] = array('sections/' => i18n::s('Site map'));
}
if (isset($item['id']) && isset($item['title'])) {
    $context['path_bar'] = array_merge($context['path_bar'], array(Sections::get_permalink($item) => $item['title']));
}
// the title of the page
$context['page_title'] = i18n::s('Lock');
// stop crawlers
if (Surfer::is_crawler()) {
    Safe::header('Status: 401 Unauthorized', TRUE, 401);
    Logger::error(i18n::s('You are not allowed to perform this operation.'));
    // not found
} elseif (!isset($item['id'])) {
    include '../error.php';
    // permission denied
} elseif (!Sections::is_owned($item, $anchor) && !Surfer::is_associate()) {
    // anonymous users are invited to log in or to register
    if (!Surfer::is_logged()) {
        Safe::redirect($context['url_to_home'] . $context['url_to_root'] . 'users/login.php?url=' . urlencode(Sections::get_url($item['id'], 'lock')));
    }
    // permission denied to authenticated user
    Safe::header('Status: 401 Unauthorized', TRUE, 401);
    Logger::error(i18n::s('You are not allowed to perform this operation.'));
    // an error occured
} elseif (count($context['error'])) {
} elseif (Sections::lock($item['id'], $item['locked'])) {
    // clear the cache
    Sections::clear($item);
    // redirect to the page
    Safe::redirect(Sections::get_permalink($item));
    // failed operation
示例#10
0
文件: duplicate.php 项目: rair/yacs
    $context['current_focus'] = $anchor->get_focus();
}
// path to this page
$context['path_bar'] = Surfer::get_path_bar($anchor);
if (isset($item['id'])) {
    $context['path_bar'] = array_merge($context['path_bar'], array(sections::get_permalink($item) => $item['title']));
}
// page title
if (isset($item['id'])) {
    $context['page_title'] = sprintf(i18n::s('%s: %s'), i18n::s('Duplicate'), $item['title']);
}
// not found
if (!isset($item['id'])) {
    include '../error.php';
    // permission denied
} elseif (!Sections::is_owned($item, $anchor)) {
    Safe::header('Status: 401 Unauthorized', TRUE, 401);
    Logger::error(i18n::s('You are not allowed to perform this operation.'));
    // action is confirmed
} elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'duplicate') {
    // to duplicate related items
    $original_anchor = 'section:' . $item['id'];
    // we will get a new id and a new handle
    unset($item['id']);
    unset($item['handle']);
    // the duplicator becomes the author
    unset($item['create_address']);
    unset($item['create_date']);
    unset($item['create_id']);
    unset($item['create_name']);
    unset($item['edit_address']);
示例#11
0
 /**
  * list sections as rows in a table
  *
  * @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;
     }
     // we list pages for one surfer
     // sanity check
     if (!isset($this->focus)) {
         $this->focus = Surfer::get_id();
     }
     // build a list of sections
     Skin::define_img('CHECKED_IMG', 'ajax/accept.png', '*');
     $rows = array();
     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, 'section:' . $item['id']);
         // get the anchor
         $anchor = Anchors::get($item['anchor']);
         // the url to view this item
         $url = sections::get_permalink($item);
         // reset everything
         $summary = $update = $owner = $editor = $watcher = '';
         if ($item['activation_date'] >= $context['now']) {
             $summary .= DRAFT_FLAG;
         } elseif ($item['expiry_date'] > NULL_DATE && $item['expiry_date'] <= $context['now']) {
             $summary .= EXPIRED_FLAG;
         }
         // signal restricted and private sections
         if ($item['active'] == 'N') {
             $summary .= PRIVATE_FLAG;
         } elseif ($item['active'] == 'R') {
             $summary .= RESTRICTED_FLAG;
         }
         // indicate the id in the hovering popup
         $hover = i18n::s('View the page');
         if (Surfer::is_member()) {
             $hover .= ' [section=' . $item['id'] . ']';
         }
         // use the title to label the link
         if (is_object($overlay)) {
             $label = Codes::beautify_title($overlay->get_text('title', $item));
         } else {
             $label = Codes::beautify_title($item['title']);
         }
         // use the title as a link to the page
         $summary .= Skin::build_link($url, $label, 'basic', $hover);
         // signal locked sections
         if (isset($item['locked']) && $item['locked'] == 'Y' && Sections::is_owned($item, $anchor)) {
             $summary .= ' ' . LOCKED_FLAG;
         }
         // flag sections updated recently
         if ($item['expiry_date'] > NULL_DATE && $item['expiry_date'] <= $context['now']) {
             $summary .= ' ' . EXPIRED_FLAG;
         } elseif ($item['create_date'] >= $context['fresh']) {
             $summary .= ' ' . NEW_FLAG;
         } elseif ($item['edit_date'] >= $context['fresh']) {
             $summary .= ' ' . UPDATED_FLAG;
         }
         // insert overlay data, if any
         if (is_object($overlay)) {
             $summary .= $overlay->get_text('list', $item);
         }
         // attachment details
         $details = array();
         // info on related sections
         if ($count = Sections::count_for_anchor('section:' . $item['id'])) {
             $details[] = sprintf(i18n::ns('%d section', '%d sections', $count), $count);
         }
         // info on related articles
         if ($count = Articles::count_for_anchor('section:' . $item['id'])) {
             $details[] = sprintf(i18n::ns('%d page', '%d pages', $count), $count);
         }
         // info on related files
         if ($count = Files::count_for_anchor('section:' . $item['id'], TRUE)) {
             $details[] = sprintf(i18n::ns('%d file', '%d files', $count), $count);
         }
         // info on related links
         if ($count = Links::count_for_anchor('section:' . $item['id'], TRUE)) {
             $details[] = sprintf(i18n::ns('%d link', '%d links', $count), $count);
         }
         // comments
         if ($count = Comments::count_for_anchor('section:' . $item['id'], TRUE)) {
             $details[] = sprintf(i18n::ns('%d comment', '%d comments', $count), $count);
         }
         // the main anchor link
         if (is_object($anchor) && (!isset($this->focus) || $item['anchor'] != $this->focus)) {
             $details[] = sprintf(i18n::s('in %s'), Skin::build_link($anchor->get_url(), ucfirst($anchor->get_title()), 'basic'));
         }
         // combine in-line details
         if (count($details)) {
             $summary .= BR . '<span class="details">' . trim(implode(' &middot; ', $details)) . '</span>';
         }
         // display all tags
         if ($item['tags']) {
             $summary .= BR . '<span class="tags">' . Skin::build_tags($item['tags'], 'section:' . $item['id']) . '</span>';
         }
         // watcher
         if (Sections::is_watched($item['id'], $this->focus)) {
             $watcher = CHECKED_IMG;
         }
         // editor
         if (Sections::is_editable($anchor, $item, $this->focus, TRUE)) {
             $editor = CHECKED_IMG;
         }
         // owner
         if (Sections::is_owned($item, NULL, TRUE, $this->focus)) {
             $owner = CHECKED_IMG;
         }
         // this is another row of the output
         $cells = array($summary, $watcher, $editor, $owner);
         // append this row
         $rows[] = $cells;
     }
     // end of processing
     SQL::free($result);
     // headers
     $headers = array(i18n::s('Section'), i18n::s('Watcher'), i18n::s('Editor'), i18n::s('Owner'));
     // return a sortable table
     $text .= Skin::table($headers, $rows, 'yc-grid');
     return $text;
 }