drop_table_if_exists($tables); $GLOBALS['SITE_DB']->query_delete('group_category_access', ['module_the_name' => 'news']); $GLOBALS['SITE_DB']->query_delete('trackbacks', ['trackback_for_type' => 'news']); $GLOBALS['SITE_DB']->query_delete('rating', ['rating_for_type' => 'news']); delete_attachments('news'); $privileges = [ 'autocomplete_keyword_news', 'autocomplete_title_news', ]; delete_privilege($privileges); } /** * Install the module. * * @param ?integer $upgrade_from What version we're upgrading from (null: new install) * @param ?integer $upgrade_from_hack What hack version we're upgrading from (null: new-install/not-upgrading-from-a-hacked-version) */ public function install(?int $upgrade_from = null, ?int $upgrade_from_hack = null) { if ($upgrade_from === null) { $GLOBALS['SITE_DB']->create_table('news', [ 'id' => '*AUTO', //'news_guid' => 'BGUID', // TODO: does not work yet: "data too long" 'date_and_time' => 'TIME', 'title' => 'SHORT_TRANS__COMCODE', 'news' => 'LONG_TRANS__COMCODE', 'news_article' => 'LONG_TRANS__COMCODE', 'allow_rating' => 'BINARY', 'allow_comments' => 'SHORT_INTEGER', 'allow_trackbacks' => 'BINARY', 'notes' => 'LONG_TEXT', 'author' => 'ID_TEXT', 'submitter' => 'MEMBER', 'validated' => 'BINARY', 'validation_time' => '?TIME', 'edit_date' => '?TIME', 'news_category' => 'AUTO_LINK', 'news_views' => 'INTEGER', 'news_image_url' => 'URLPATH', ]); $GLOBALS['SITE_DB']->create_index('news', 'news_views', ['news_views']); $GLOBALS['SITE_DB']->create_index('news', 'findnewscat', ['news_category']); $GLOBALS['SITE_DB']->create_index('news', 'newsauthor', ['author']); $GLOBALS['SITE_DB']->create_index('news', 'nes', ['submitter']); $GLOBALS['SITE_DB']->create_index('news', 'headlines', ['date_and_time', 'id']); $GLOBALS['SITE_DB']->create_index('news', 'nvalidated', ['validated']); $GLOBALS['SITE_DB']->create_table('news_categories', [ 'id' => '*AUTO', 'nc_title' => 'SHORT_TRANS', 'nc_owner' => '?MEMBER', 'nc_img' => 'SHORT_TEXT', 'notes' => 'LONG_TEXT', ]); $GLOBALS['SITE_DB']->create_index('news_categories', 'ncs', ['nc_owner']); require_code('lang3'); $default_categories = ['general']; require_lang('news'); foreach ($default_categories as $category) { $map = [ 'notes' => '', 'nc_img' => 'icons/news/' . $category, 'nc_owner' => null, ]; $map += lang_code_to_default_content('nc_title', 'NC_' . $category); $GLOBALS['SITE_DB']->query_insert('news_categories', $map); } require_code('content2'); install_predefined_content('news'); $GLOBALS['SITE_DB']->create_table('news_rss_cloud', [ 'id' => '*AUTO', 'rem_procedure' => 'ID_TEXT', 'rem_port' => 'INTEGER', 'rem_path' => 'SHORT_TEXT', 'rem_protocol' => 'ID_TEXT', 'rem_ip_address' => 'IP', 'watch_channel_url' => 'URLPATH', 'register_time' => 'TIME', ]); $GLOBALS['SITE_DB']->create_table('news_category_entries', [ 'news_entry' => '*AUTO_LINK', 'news_entry_category' => '*AUTO_LINK', ]); $GLOBALS['SITE_DB']->create_index('news_category_entries', 'news_entry_category', ['news_entry_category']); $categories = $GLOBALS['SITE_DB']->query_select('news_categories', ['id']); foreach ($categories as $_id) { require_code('permissions2'); set_global_category_access('news', $_id['id']); } $GLOBALS['SITE_DB']->create_index('news', 'ftjoin_ititle', ['title']); $GLOBALS['SITE_DB']->create_index('news', 'ftjoin_nnews', ['news']); $GLOBALS['SITE_DB']->create_index('news', 'ftjoin_nnewsa', ['news_article']); } if (($upgrade_from === null) || ($upgrade_from < 7)) { $GLOBALS['SITE_DB']->create_index('news', '#news_search__combined', ['title', 'news', 'news_article']); add_privilege('SEARCH', 'autocomplete_keyword_news', false); add_privilege('SEARCH', 'autocomplete_title_news', false); } if (($upgrade_from !== null) && ($upgrade_from < 8)) { // LEGACY $GLOBALS['SITE_DB']->alter_table_field('news_categories', 'nc_img', 'SHORT_TEXT'); $icons = [ 'art', 'business', 'community', 'difficulties', 'entertainment', 'general', 'technology', ]; foreach ($icons as $icon) { $GLOBALS['SITE_DB']->query_update('news_categories', ['nc_img' => 'icons/news/' . $icon], ['nc_img' => 'newscats/' . $icon]); } } if (($upgrade_from !== null) && ($upgrade_from < 9)) { // LEGACY: 11.beta1 // Database consistency fixes $GLOBALS['SITE_DB']->alter_table_field('news', 'news_image', 'URLPATH', 'news_image_url'); $GLOBALS['SITE_DB']->alter_table_field('news_rss_cloud', 'rem_ip', 'IP', 'rem_ip_address'); $GLOBALS['SITE_DB']->alter_table_field('news_rss_cloud', 'watching_channel', 'URLPATH', 'watch_channel_url'); } // TODO: does not work yet: "data too long" (make sure to update the $upgrade_from and move this block accordingly) /* if (($upgrade_from !== null) && ($upgrade_from < 10)) { // LEGACY: 11.beta6 $GLOBALS['SITE_DB']->add_table_field('news', 'news_guid', 'BGUID'); // Create a time-based GUID for existing records require_code('crypt'); $start = 0; $max = 100; do { $rows = $GLOBALS['SITE_DB']->query_select('news', ['id', 'date_and_time'], [], '', $max, $start); foreach ($rows as $row) { $guid = hex2bin(str_replace('-', '', get_secure_v1_guid(floatval($row['date_and_time'])))); $GLOBALS['SITE_DB']->query_update('news', ['news_guid' => $guid], ['id' => $row['id']]); } $start += $max; } while (count($rows) > 0); } */ if (($upgrade_from !== null) && ($upgrade_from < 10)) { // LEGACY: 11.beta7 $GLOBALS['SITE_DB']->add_table_field('news', 'validation_time', '?TIME'); // Migrate old publication time code to our new validation time if (addon_installed('calendar')) { require_code('calendar2'); require_code('temporal'); // Gather our calendar events $sql = 'SELECT e.id,e.e_content FROM ' . get_table_prefix() . 'calendar_events e WHERE ' . $GLOBALS['SITE_DB']->translate_field_ref('e_content') . ' LIKE \'' . db_encode_like('run_scheduled_action publish_news%') . '\''; $rows = $GLOBALS['SITE_DB']->query($sql, null, 0, false, true, ['e_content' => 'LONG_TRANS__COMCODE']); foreach ($rows as $row) { $content = get_translated_text($row['e_content']); $matches = []; if (preg_match('/run_scheduled_action publish_news "(\d+)"/', $content, $matches) != 0) { $news_id = $matches[1]; // Get the time of publication $_time = get_schedule_code_event_time('publish_news', $news_id); if ($_time !== null) { list($minute, $hour, $month, $day, $year) = $_time; $time = cms_mktime($hour, $minute, 0, $month, $day, $year); // Set publication time into our new validation time field $GLOBALS['SITE_DB']->query_update('news', ['validation_time' => $time], ['id' => intval($news_id)]); } // Un-schedule the event from the calendar unschedule_code('publish_news', $news_id); } } } } if (($upgrade_from === null) || ($upgrade_from < 11)) { // 11.beta9 $GLOBALS['SITE_DB']->create_foreign_key('news', 'news_category', 'news_categories', 'id'); $GLOBALS['SITE_DB']->create_foreign_key('news_category_entries', 'news_entry', 'news', 'id'); $GLOBALS['SITE_DB']->create_foreign_key('news_category_entries', 'news_entry_category', 'news_categories', 'id'); } } /** * Find entry-points available within this module. * * @param boolean $check_perms Whether to check permissions * @param ?MEMBER $member_id The member to check permissions as (null: current user) * @param boolean $support_crosslinks Whether to allow cross links to other modules (identifiable via a full-page-link rather than a screen-name) * @param boolean $be_deferential Whether to avoid any entry-point (or even return null to disable the page in the Sitemap) if we know another module, or page_group, is going to link to that entry-point. Note that "!" and "browse" entry points are automatically merged with container page nodes (likely called by page-groupings) as appropriate. * @return ?array A map of entry points (screen-name=>language-code/string or screen-name=>[language-code/string, icon-theme-image]) (null: disabled) */ public function get_entry_points(bool $check_perms = true, ?int $member_id = null, bool $support_crosslinks = true, bool $be_deferential = false) : ?array { if (!addon_installed('news')) { return null; } $has_blogs = ($GLOBALS['SITE_DB']->query_value_if_there('SELECT COUNT(*) FROM ' . get_table_prefix() . 'news_categories WHERE nc_owner IS NOT NULL') > 0); $ret = [ 'browse' => ['NEWS_ARCHIVE', 'menu/rich_content/news'], ]; if ($has_blogs) { $ret['cat_select'] = ['JUST_NEWS_CATEGORIES', 'admin/view_archive']; $ret['blog_select'] = ['BLOGS', 'menu/cms/blog']; $ret['select'] = ['NEWS_CATEGORIES', 'menu/rich_content/news']; } else { $ret['cat_select'] = ['JUST_NEWS_CATEGORIES', 'menu/rich_content/news']; } return $ret; } public $title; public $id; public $blog; public $select; public $select_and; public $myrow; public $_title; public $title_to_use; public $img; public $news_full; public $category; /** * Module pre-run function. Allows us to know metadata for before we start streaming output. * * @return ?Tempcode Tempcode indicating some kind of exceptional output (null: none) */ public function pre_run() : ?object { $error_msg = new Tempcode(); if (!addon_installed__messaged('news', $error_msg)) { return $error_msg; } if (!addon_installed__messaged('news_shared', $error_msg)) { return $error_msg; } $type = get_param_string('type', 'browse'); require_lang('news'); require_code('news'); $select = get_param_string('select', '0'); if ((!is_numeric($select)) || ($type != 'browse')) { inform_non_canonical_parameter('select'); } inform_non_canonical_parameter('select_and'); inform_non_canonical_parameter('blog'); inform_non_canonical_parameter('filter'); if ($type == 'cat_select') { $this->title = get_screen_title('JUST_NEWS_CATEGORIES'); } if ($type == 'blog_select') { $this->title = get_screen_title('BLOGS'); } if ($type == 'select') { $this->title = get_screen_title('NEWS_CATEGORIES'); } if ($type == 'browse') { $blog = get_param_integer('blog', null); $_select = get_param_string('id', null); if ($_select !== null) { $select = $_select . '*'; } else { $select = get_param_string('select', '*', INPUT_FILTER_GET_COMPLEX); } $select_and = get_param_string('select_and', '*', INPUT_FILTER_GET_COMPLEX); $news_cat_id = null; $news_cat_rows = []; $matches = []; if (preg_match('#^(\d+)\*$#', $select, $matches) != 0) { $news_cat_rows = $GLOBALS['SITE_DB']->query_select('news_categories', ['*'], ['id' => intval($matches[1])], '', 1); if (array_key_exists(0, $news_cat_rows)) { $news_cat_id = intval($matches[1]); } } // Title if ($blog === 1) { $this->title = get_screen_title('BLOG_NEWS_ARCHIVE'); } elseif ($news_cat_id !== null) { $news_cat_rows[0]['_nc_title'] = get_translated_text($news_cat_rows[0]['nc_title']); $this->title = get_screen_title(make_fractionable_editable('news_category', $select, $news_cat_rows[0]['_nc_title']), false); } else { $this->title = get_screen_title('NEWS_ARCHIVE'); } // Metadata if ($news_cat_id !== null) { set_extra_request_metadata([ 'identifier' => '_SEARCH:news:browse:' . strval($news_cat_id), ], $news_cat_rows[0], 'news_category', strval($news_cat_id)); } // Breadcrumbs if ($blog === 1) { $first_bc = ['_SELF:_SELF:blog_select', do_lang_tempcode('BLOGS')]; } elseif ($blog === 0) { $first_bc = ['_SELF:_SELF:cat_select', do_lang_tempcode('JUST_NEWS_CATEGORIES')]; } else { $first_bc = ['_SELF:_SELF:select', do_lang_tempcode('NEWS_CATEGORIES')]; } breadcrumb_set_parents([$first_bc]); $this->blog = $blog; $this->select = $select; $this->select_and = $select_and; } if ($type == 'view') { $id = get_param_integer('id'); if (addon_installed('content_privacy')) { require_code('content_privacy'); check_privacy('news', strval($id)); } $blog = get_param_integer('blog', null); $select = get_param_string('select', '*', INPUT_FILTER_GET_COMPLEX); $select_and = get_param_string('select_and', '*', INPUT_FILTER_GET_COMPLEX); // Load from database $rows = $GLOBALS['SITE_DB']->query_select('news', ['*'], ['id' => $id], '', 1); if (!array_key_exists(0, $rows)) { return warn_screen(get_screen_title('NEWS'), do_lang_tempcode('MISSING_RESOURCE', 'news')); } $myrow = $rows[0]; // Breadcrumbs if ($blog === 1) { $first_bc = ['_SELF:_SELF:blog_select', do_lang_tempcode('BLOGS')]; } elseif ($blog === 0) { $first_bc = ['_SELF:_SELF:cat_select', do_lang_tempcode('JUST_NEWS_CATEGORIES')]; } else { $first_bc = ['_SELF:_SELF:select', do_lang_tempcode('NEWS_CATEGORIES')]; } $is_selecting_single_cat = false; $news_cat = $myrow['news_category']; $matches = []; if (preg_match('#^(\d+)[*\#]$#', $select, $matches) != 0) { $news_cat = intval($matches[1]); $is_selecting_single_cat = true; } if ($blog === 1) { $parent_title = do_lang_tempcode('BLOG_NEWS_ARCHIVE'); } else { $news_cat_rows = $GLOBALS['SITE_DB']->query_select('news_categories', ['nc_title'], ['id' => $news_cat], '', 1); if (array_key_exists(0, $news_cat_rows)) { $news_cat_rows[0]['_nc_title'] = get_translated_text($news_cat_rows[0]['nc_title']); $parent_title = protect_from_escaping(escape_html($news_cat_rows[0]['_nc_title'])); } else { $parent_title = do_lang_tempcode('NEWS_ARCHIVE'); } } $breadcrumb_pagelink = '_SELF:_SELF:browse'; $breadcrumb_pagelink .= (($blog === 1) ? ':blog=1' : (($blog === 0) ? ':blog=0' : '')); if (($is_selecting_single_cat) || ($select == '*')) { $breadcrumb_pagelink .= ':id=' . strval($news_cat); } else { $breadcrumb_pagelink .= ':select=' . $select; } $breadcrumb_pagelink .= (($select_and == '*') ? '' : (':select_and=' . $select_and)); $breadcrumb_pagelink .= propagate_filtercode_page_link(); breadcrumb_set_parents([$first_bc, [$breadcrumb_pagelink, $parent_title]]); breadcrumb_set_self(protect_from_escaping(get_translated_tempcode('news', $myrow, 'title'))); // Permissions if (!has_category_access(get_member(), 'news', strval($myrow['news_category']))) { access_denied('CATEGORY_ACCESS'); } // Title if ((get_value('disable_awards_in_titles') !== '1') && (addon_installed('awards'))) { require_code('awards'); $awards = find_awards_for('news', strval($id)); } else { $awards = []; } $_title = get_translated_tempcode('news', $myrow, 'title'); $title_to_use = do_lang_tempcode(($blog === 1) ? 'BLOG__NEWS' : '_NEWS', make_fractionable_editable('news', $id, $_title)); $this->title = get_screen_title($title_to_use, false, [], null, $awards); // SEO seo_meta_load_for('news', strval($id), do_lang(($blog === 1) ? 'BLOG__NEWS' : '_NEWS', get_translated_text($myrow['title']))); // Category membership load_news_cat_rows('nc_owner IS NULL OR id=' . strval($myrow['news_category'])); $news_cat_row = get_news_cat_row($myrow['news_category']); $category = get_translated_text($news_cat_row['nc_title']); $news_full = get_translated_tempcode('news', $myrow, 'news_article'); $news_summary = get_translated_tempcode('news', $myrow, 'news'); if ($news_full->is_empty()) { $news_full = $news_summary; } // Metadata set_extra_request_metadata([ 'identifier' => '_SEARCH:news:view:' . strval($id), 'category' => $category, ], $myrow, 'news', strval($id)); $this->id = $id; $this->blog = $blog; $this->select = $select; $this->select_and = $select_and; $this->myrow = $myrow; $this->_title = $_title; $this->title_to_use = $title_to_use; $this->news_full = $news_full; $this->category = $category; } return null; } /** * Execute the module. * * @return Tempcode The result of execution */ public function run() : object { require_code('feedback'); require_css('news'); $type = get_param_string('type', 'browse'); if ($type == 'view') { return $this->view_news(); } if ($type == 'browse') { return $this->news_archive(); } if ($type == 'cat_select') { return $this->news_cat_select(0); } if ($type == 'blog_select') { return $this->news_cat_select(1); } if ($type == 'select') { return $this->news_cat_select(null); } return new Tempcode(); } /** * The UI to select a news category to view news within. * * @param ?integer $blogs What to show (null: news and blogs, 0: news, 1: blogs) * @return Tempcode The UI */ public function news_cat_select(?int $blogs) : object { $start = get_param_integer('news_categories_start', 0); $max = get_param_integer('news_categories_max', intval(get_option('news_categories_per_page'))); $select = get_param_string('select', '*', INPUT_FILTER_GET_COMPLEX); if ($select == '*') { $where = '1=1'; } else { require_code('selectcode'); $where = selectcode_to_sqlfragment($select, 'r.news_category', 'news_categories', null, 'r.news_category', 'id'); // Note that the parameters are fiddled here so that category-set and record-set are the same, yet SQL is returned to deal in an entirely different record-set (entries' record-set) } if ($blogs === null) { $map = []; $categories = $GLOBALS['SITE_DB']->query_select('news_categories', ['*'], $map, 'ORDER BY nc_owner,' . $GLOBALS['SITE_DB']->translate_field_ref('nc_title'), $max, $start); // Ordered to show non-blogs first (nc_owner=NULL) $max_rows = $GLOBALS['SITE_DB']->get_table_count_approx('news_categories'); } elseif ($blogs == 1) { $categories = $GLOBALS['SITE_DB']->query('SELECT c.* FROM ' . get_table_prefix() . 'news_categories c WHERE nc_owner IS NOT NULL ORDER BY nc_owner DESC,' . $GLOBALS['SITE_DB']->translate_field_ref('nc_title'), $max, $start, false, false, ['nc_title' => 'SHORT_TRANS']); // Ordered to show newest blogs first $max_rows = $GLOBALS['SITE_DB']->query_value_if_there('SELECT COUNT(*) FROM ' . get_table_prefix() . 'news_categories WHERE nc_owner IS NOT NULL', false, false, ['nc_title' => 'SHORT_TRANS']); } else { $map = ['nc_owner' => null]; $categories = $GLOBALS['SITE_DB']->query_select('news_categories', ['*'], $map, 'ORDER BY ' . $GLOBALS['SITE_DB']->translate_field_ref('nc_title'), $max, $start); // Ordered by title (can do efficiently as limited numbers of non-blogs) $max_rows = $GLOBALS['SITE_DB']->query_select_value('news_categories', 'COUNT(*)', $map); } $content = new Tempcode(); $join = ' LEFT JOIN ' . get_table_prefix() . 'news_category_entries d ON d.news_entry=r.id'; if ($blogs === 1) { $where .= ' AND c.nc_owner IS NOT NULL'; $join .= ' LEFT JOIN ' . get_table_prefix() . 'news_categories c ON c.id=r.news_category'; } elseif ($blogs === 0) { $where .= ' AND c.nc_owner IS NULL AND c.id IS NOT NULL'; $join .= ' LEFT JOIN ' . get_table_prefix() . 'news_categories c ON c.id=r.news_category'; } $_content = []; foreach ($categories as $category) { if (has_category_access(get_member(), 'news', strval($category['id']))) { $query = 'SELECT COUNT(*) FROM ' . get_table_prefix() . 'news r' . $join . ' WHERE ' . (((addon_installed('validation')) && (!has_privilege(get_member(), 'see_not_validated'))) ? 'validated=1 AND ' : '') . ' (news_entry_category=' . strval($category['id']) . ' OR news_category=' . strval($category['id']) . ') AND ' . $where; $count = $GLOBALS['SITE_DB']->query_value_if_there($query); if ($count > 0) { $_content[] = render_news_category_box($category, '_SELF', false, true, $blogs); } } } foreach ($_content as $c) { // To allow code overrides to easily shuffle it $content->attach($c); } if ($content->is_empty()) { inform_exit(do_lang_tempcode('NO_ENTRIES', 'news_category')); } if ((($blogs !== 1) || (has_privilege(get_member(), 'have_personal_category', 'cms_news'))) && (has_actual_page_access(null, ($blogs === 1) ? 'cms_blogs' : 'cms_news', null, null)) && (has_submit_permission(($blogs === 1) ? 'mid' : 'high', get_member(), get_ip_address(), 'cms_news'))) { $map = ['page' => ($blogs === 1) ? 'cms_blogs' : 'cms_news', 'type' => 'add']; if (is_numeric($select)) { $map['cat'] = $select; } $submit_url = build_url($map, get_module_zone($map['page'])); } else { $submit_url = new Tempcode(); } require_code('templates_pagination'); $pagination = pagination(do_lang_tempcode('NEWS_CATEGORIES'), $start, 'news_categories_start', $max, 'news_categories_max', $max_rows); $tpl = do_template('PAGINATION_SCREEN', [ '_GUID' => 'c61c945e0453c2145a819ca60e8faf09', 'TITLE' => $this->title, 'SUBMIT_URL' => $submit_url, 'CONTENT' => $content, 'PAGINATION' => $pagination, ]); require_code('templates_internalise_screen'); return internalise_own_screen($tpl); } /** * The UI to view the news archive. * * @return Tempcode The UI */ public function news_archive() : object { $blog = $this->blog; $select = $this->select; $select_and = $this->select_and; $max = get_param_integer('module_max', intval(get_option('news_entries_per_page'))); // Get category contents $inline = get_param_integer('inline', 0) == 1; $filter = either_param_string('active_filter', '', INPUT_FILTER_NONE); // Management links if ((($blog !== 1) || (has_privilege(get_member(), 'have_personal_category', 'cms_news'))) && (has_actual_page_access(null, ($blog === 1) ? 'cms_blogs' : 'cms_news', null, null)) && (has_submit_permission(($blog === 1) ? 'mid' : 'high', get_member(), get_ip_address(), 'cms_news'))) { $map = ['page' => ($blog === 1) ? 'cms_blogs' : 'cms_news', 'type' => 'add']; if (is_numeric($select)) { $map['cat'] = $select; } $submit_url = build_url($map, get_module_zone($map['page'])); } else { $submit_url = new Tempcode(); } $edit_cat_url = new Tempcode(); if (is_numeric($select)) { if (has_actual_page_access(null, 'cms_news', null, ['news', $select], 'edit_cat_midrange_content')) { $edit_cat_url = build_url(['page' => 'cms_news', 'type' => '_edit_category', 'id' => $select], get_module_zone('cms_news')); } } // Render return do_template('NEWS_ARCHIVE_SCREEN', [ '_GUID' => '228918169ab1db445ee0c2d71f85983c', 'TITLE' => $this->title, 'CAT' => is_numeric($select) ? $select : null, 'SUBMIT_URL' => $submit_url, 'EDIT_CAT_URL' => $edit_cat_url, 'BLOG' => $blog === 1, 'BLOGS' => ($blog === null) ? '-1' : strval($blog), 'FILTER' => $filter, 'SELECT' => $select, 'SELECT_AND' => $select_and, 'MAX' => strval($max), 'INLINE' => $inline, ]); } /** * The UI to view a news entry. * * @return Tempcode The UI */ public function view_news() : object { $id = $this->id; $blog = $this->blog; $select = $this->select; $select_and = $this->select_and; $myrow = $this->myrow; $_title = $this->_title; $news_full = $this->news_full; $category = $this->category; // Rating and comments $self_url_map = ['page' => '_SELF', 'type' => 'view', 'id' => $id]; /*if ($select != '*') $self_url_map['select'] = $select; Potentially makes URL too long for content topic to store, and we probably don't want to store this assumptive context anyway if (($select_and != '*') && ($select_and != '')) $self_url_map['select_and'] = $filter_and;*/ if ($blog !== null) { $self_url_map['blog'] = $blog; } list($rating_details, $comment_details, $trackback_details) = embed_feedback_systems( get_page_name(), strval($id), $myrow['allow_rating'], $myrow['allow_comments'], $myrow['allow_trackbacks'], $myrow['validated'], $myrow['submitter'], build_url($self_url_map, '_SELF', [], false, false, true), get_translated_text($myrow['title']), find_overridden_comment_forum('news', strval($myrow['news_category'])), $myrow['date_and_time'] ); // Load details $date = get_timezoned_date_time($myrow['date_and_time']); $author_url = addon_installed('authors') ? build_url(['page' => 'authors', 'type' => 'browse', 'id' => $myrow['author']], get_module_zone('authors')) : new Tempcode(); $author = $myrow['author']; $news_full_plain = get_translated_text($myrow['news_article']); if ($news_full->is_empty()) { $news_full_plain = get_translated_text($myrow['news']); } // Validation if (($myrow['validated'] == 0) && (addon_installed('validation'))) { require_code('validation'); check_jump_to_not_validated('news', strval($id), get_member(), [$myrow['submitter']]); $warning_details = do_template('WARNING_BOX', [ '_GUID' => '5fd82328dc2ac9695dc25646237065b0', 'WARNING' => do_lang_tempcode((get_param_integer('redirected', 0) == 1) ? 'NOT_VALIDATED_TEXT_NON_DIRECT' : 'NOT_VALIDATED_TEXT', 'news'), ]); } else { $warning_details = new Tempcode(); } // Views cms_register_shutdown_function_safe(function () use ($myrow, $id) { $increment = statistical_update_model('news', $myrow['news_views']); if ($increment != 0) { $GLOBALS['SITE_DB']->query('UPDATE ' . get_table_prefix() . 'news SET news_views=news_views+' . strval($increment) . ' WHERE id=' . strval($id), 1, 0, true); // Errors suppressed in case DB write access broken } }); // Management links if ((has_actual_page_access(null, ($blog === 1) ? 'cms_blogs' : 'cms_news', null, null)) && (has_edit_permission(($blog === 1) ? 'mid' : 'high', get_member(), $myrow['submitter'], ($blog === 1) ? 'cms_blogs' : 'cms_news', ['news', $myrow['news_category']]))) { $edit_url = build_url(['page' => ($blog === 1) ? 'cms_blogs' : 'cms_news', 'type' => '_edit', 'id' => $id], get_module_zone(($blog === 1) ? 'cms_blogs' : 'cms_news')); } else { $edit_url = new Tempcode(); } $tmp = ['page' => '_SELF', 'type' => 'browse']; if ($select != '*') { $tmp[is_numeric($select) ? 'id' : 'select'] = $select; } if (($select_and != '*') && ($select_and != '')) { $tmp['select_and'] = $select_and; } if ($blog !== null) { $tmp['blog'] = $blog; } $archive_url = build_url($tmp + propagate_filtercode(), '_SELF'); if ((($blog !== 1) || (has_privilege(get_member(), 'have_personal_category', 'cms_news'))) && (has_actual_page_access(null, ($blog === 1) ? 'cms_blogs' : 'cms_news', null, null)) && (has_submit_permission(($blog === 1) ? 'mid' : 'high', get_member(), get_ip_address(), 'cms_news', ['news', $myrow['news_category']]))) { $map = ['page' => ($blog === 1) ? 'cms_blogs' : 'cms_news', 'type' => 'add']; if (is_numeric($select)) { $map['cat'] = $select; } $submit_url = build_url($map, get_module_zone($map['page'])); } else { $submit_url = new Tempcode(); } $categories = [strval($myrow['news_category']) => $category]; $all_categories_for_this = $GLOBALS['SITE_DB']->query_select('news_category_entries', ['*'], ['news_entry' => $id]); foreach ($all_categories_for_this as $category_for_this) { $news_cat_row = get_news_cat_row($category_for_this['news_entry_category'], true); if ($news_cat_row !== null) { $categories[strval($category_for_this['news_entry_category'])] = get_translated_text($news_cat_row['nc_title']); } } $news_cat_row = get_news_cat_row($myrow['news_category']); // Newsletter tie-in $newsletter_url = new Tempcode(); if (addon_installed('newsletter')) { require_lang('newsletter'); if (has_actual_page_access(get_member(), 'admin_newsletter')) { $newsletter_url = build_url(['page' => 'admin_newsletter', 'type' => 'new', 'from_news' => $id], get_module_zone('admin_newsletter')); } } $show_comment_count = '0'; if ((get_option('is_on_comments') == '1') && (!has_no_forum()) && ($myrow['allow_comments'] >= 1)) { $show_comment_count = '1'; } $rep_image_url = get_news_category_image_url($news_cat_row['nc_img']); $prev_article_url = null; $prev_article_title = null; $next_article_url = null; $next_article_title = null; // Find a previous article (not reliable for articles published at the same time) $where_map = ['news_category' => $myrow['news_category']]; // $extra_where = ' AND ' . db_encode_binary_compare('news_guid', '<', $myrow['news_guid']); // TODO: does not work yet: "data too long" $extra_where = ' AND date_and_time<' . strval($myrow['date_and_time']); if (addon_installed('validation')) { if ((!has_privilege(get_member(), 'see_not_validated')) || (is_guest())) { $extra_where .= ' AND (validated=1'; if (!is_guest()) { $extra_where .= ' OR submitter=' . strval(get_member()); } $extra_where .= ')'; } } $extra_where .= ' ORDER BY date_and_time DESC'; $prev_articles = $GLOBALS['SITE_DB']->query_select('news', ['*'], $where_map, $extra_where, 1); if (array_key_exists(0, $prev_articles)) { $prev_article = $prev_articles[0]; $_prev_article_title = $prev_article['title']; if (!cms_empty_safe($_prev_article_title) && ($id != $prev_article['id'])) { $prev_article_title = get_translated_text($_prev_article_title); $prev_article_url = build_url(['page' => '_SELF', 'type' => 'view', 'id' => $prev_article['id']], '_SELF'); } } // Find a next article (not reliable for articles published at the same time) $where_map = ['news_category' => $myrow['news_category']]; //$extra_where = ' AND ' . db_encode_binary_compare('news_guid', '>', $myrow['news_guid']); // TODO: does not work yet: "data too long" $extra_where = ' AND date_and_time>' . strval($myrow['date_and_time']); if (addon_installed('validation')) { if ((!has_privilege(get_member(), 'see_not_validated')) || (is_guest())) { $extra_where .= ' AND (validated=1'; if (!is_guest()) { $extra_where .= ' OR submitter=' . strval(get_member()); } $extra_where .= ')'; } } $extra_where .= ' ORDER BY date_and_time ASC'; $next_articles = $GLOBALS['SITE_DB']->query_select('news', ['*'], $where_map, $extra_where, 1); if (array_key_exists(0, $next_articles)) { $next_article = $next_articles[0]; $_next_article_title = $next_article['title']; if (!cms_empty_safe($_next_article_title) && ($id != $next_article['id'])) { $next_article_title = get_translated_text($_next_article_title); $next_article_url = build_url(['page' => '_SELF', 'type' => 'view', 'id' => $next_article['id']], '_SELF'); } } $author_entry_url = ''; $author_entry_member_id = null; $author_entry_description = new Tempcode(); $author_entry_skills = new Tempcode(); if (addon_installed('authors')) { $author_rows = $GLOBALS['SITE_DB']->query_select('authors', ['*'], ['author' => $author], '', 1); if (array_key_exists(0, $author_rows)) { $author_row = $author_rows[0]; $author_entry_url = $author_row['url']; $author_entry_member_id = strval($author_row['member_id']); $author_entry_description = get_translated_tempcode('authors', $author_row, 'the_description'); $author_entry_skills = get_translated_tempcode('authors', $author_row, 'skills'); } } // Render return do_template('NEWS_ENTRY_SCREEN', [ '_GUID' => '7686b23934e22c493d4ac10ba6c475c4', 'TITLE' => $this->title, 'ID' => strval($id), 'CATEGORY_ID' => strval($myrow['news_category']), 'BLOG' => $blog === 1, '_TITLE' => $_title, 'TAGS' => get_loaded_tags('news'), 'CATEGORIES' => $categories, 'NEWSLETTER_URL' => $newsletter_url, 'ADD_DATE_RAW' => strval($myrow['date_and_time']), 'EDIT_DATE_RAW' => ($myrow['edit_date'] === null) ? '' : strval($myrow['edit_date']), 'SUBMITTER' => strval($myrow['submitter']), 'CATEGORY' => $category, 'REP_IMAGE_URL' => $rep_image_url, '_VIEWS' => strval($myrow['news_views']), 'VIEWS' => integer_format($myrow['news_views'], 0), 'COMMENT_DETAILS' => $comment_details, 'RATING_DETAILS' => $rating_details, 'TRACKBACK_DETAILS' => $trackback_details, 'DATE' => $date, 'AUTHOR' => $author, 'AUTHOR_URL' => $author_url, 'AUTHOR_ENTRY_URL' => $author_entry_url, 'AUTHOR_ENTRY_MEMBER_ID' => $author_entry_member_id, 'AUTHOR_ENTRY_DESCRIPTION' => $author_entry_description, 'AUTHOR_ENTRY_SKILLS' => $author_entry_skills, 'NEWS_FULL' => $news_full, 'NEWS_FULL_PLAIN' => $news_full_plain, 'EDIT_URL' => $edit_url, 'ARCHIVE_URL' => $archive_url, 'SUBMIT_URL' => $submit_url, 'WARNING_DETAILS' => $warning_details, 'COMMENT_COUNT' => $show_comment_count, 'PREV_ARTICLE_TITLE' => $prev_article_title, 'PREV_ARTICLE_URL' => $prev_article_url, 'NEXT_ARTICLE_TITLE' => $next_article_title, 'NEXT_ARTICLE_URL' => $next_article_url, ]); } }