/** * Main function executed automatically by the controller * * @param object $registry Registry object * @return @e void */ public function doExecute(ipsRegistry $registry) { /* From App */ $app = trim($this->request['f_app']); $area = trim($this->request['f_area']); $relid = intval($this->request['f_relid']); if (!$app or !$area or empty($relid)) { trigger_error("Missing data in " . __FILE__ . ' ' . __LINE__); } /* Init some data */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $this->_like = classes_like::bootstrap($app, $area); $this->registry->getClass('class_localization')->loadLanguageFile(array('public_like'), 'core'); /* What to do? */ switch ($this->request['do']) { case 'setDialogue': $this->_setDialogue($app, $area, $relid); break; case 'save': $this->_save($relid); break; case 'unset': $this->_unset($relid); break; case 'more': $this->_more($relid); break; } }
/** * Save the 'like' preferences for a single object * * @return @e void */ protected function saveFollow() { //----------------------------------------- // Get like helper class //----------------------------------------- $bootstraps = array(); require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_bootstrap = classes_like::bootstrap($this->request['searchApp'], $this->request['contentType']); $_likeKey = classes_like_registry::getKey($this->request['id'], $this->memberData['member_id']); $_frequencies = $_bootstrap->allowedFrequencies(); //----------------------------------------- // What action to take? //----------------------------------------- switch ($this->request['modaction']) { case 'delete': $_bootstrap->remove($this->request['id'], $this->memberData['member_id']); break; case 'change-donotify': $this->DB->update('core_like', array('like_notify_do' => 1, 'like_notify_freq' => 'immediate'), "like_id='" . addslashes($_likeKey) . "'"); break; case 'change-donotnotify': $this->DB->update('core_like', array('like_notify_do' => 0), "like_id='" . addslashes($_likeKey) . "'"); break; case 'change-immediate': if (in_array('immediate', $_frequencies)) { $this->DB->update('core_like', array('like_notify_do' => 1, 'like_notify_freq' => 'immediate'), "like_id='" . addslashes($_likeKey) . "'"); } break; case 'change-offline': if (in_array('offline', $_frequencies)) { $this->DB->update('core_like', array('like_notify_do' => 1, 'like_notify_freq' => 'offline'), "like_id='" . addslashes($_likeKey) . "'"); } break; case 'change-daily': if (in_array('daily', $_frequencies)) { $this->DB->update('core_like', array('like_notify_do' => 1, 'like_notify_freq' => 'daily'), "like_id='" . addslashes($_likeKey) . "'"); } break; case 'change-weekly': if (in_array('weekly', $_frequencies)) { $this->DB->update('core_like', array('like_notify_do' => 1, 'like_notify_freq' => 'weekly'), "like_id='" . addslashes($_likeKey) . "'"); } break; case 'change-anon': $this->DB->update('core_like', array('like_is_anon' => 1), "like_id='" . addslashes($_likeKey) . "'"); break; case 'change-noanon': $this->DB->update('core_like', array('like_is_anon' => 0), "like_id='" . addslashes($_likeKey) . "'"); break; default: $this->returnJsonError("follow_no_action"); break; } $_data = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'core_like', 'where' => "like_id='" . addslashes($_likeKey) . "'")); $this->returnJsonArray(array('html' => $this->registry->output->getTemplate('search')->followData($_data))); }
/** * Run this task * * @return @e void */ public function runTask() { $this->registry->getClass('class_localization')->loadLanguageFile(array('public_global'), 'core'); //----------------------------------------- // Send daily digests... //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $_like->sendDigestNotifications('daily', 500); $_like = classes_like::bootstrap('forums', 'forums'); $_like->sendDigestNotifications('daily', 500); //----------------------------------------- // Log to log table - modify but dont delete //----------------------------------------- $this->class->appendTaskLog($this->task, $this->lang->words['task_dailydigest']); //----------------------------------------- // Unlock Task: DO NOT MODIFY! //----------------------------------------- $this->class->unlockTask($this->task); }
/** * Convert Follow * * @access private * @return void */ public function convertFollow($info) { if (!$info['like_app']) { $this->logError($info['like_id'], 'No Application Provided.'); return false; } if (!$info['like_area']) { $this->logError($info['like_id'], 'No Area provided.'); return false; } if (!$info['like_rel_id']) { $this->logError($info['like_id'], 'No Relative ID provided.'); return false; } if (!$info['like_member_id']) { // Seems to always error, so commented it out for now as its scaring people. //$this->logError( $info['like_id'] . ': No Member ID provided, possibly deleted.' ); return false; } // Set up like class. require_once IPS_ROOT_PATH . '/sources/classes/like/composite.php'; $_like = classes_like::bootstrap($info['like_app'], $info['like_area']); $_like->add($info['like_rel_id'], $info['like_member_id'], array('like_notify_do' => 1, 'like_notify_meta' => $info['like_notify_meta'], 'like_notify_freq' => $info['like_notify_freq'])); return true; }
/** * Perform the viewNewContent search * Populates $this->_count and $this->_results * * @access public * @return array */ public function viewNewContent() { //----------------------------------------- // Init //----------------------------------------- IPSSearchRegistry::set('in.search_sort_by', 'date'); IPSSearchRegistry::set('in.search_sort_order', 'desc'); IPSSearchRegistry::set('opt.searchType', 'titles'); IPSSearchRegistry::set('opt.noPostPreview', true); //----------------------------------------- // Set time limit //----------------------------------------- if (IPSSearchRegistry::get('in.period_in_seconds') !== false) { $this->search_begin_timestamp = IPS_UNIX_TIME_NOW - IPSSearchRegistry::get('in.period_in_seconds'); } else { $this->search_begin_timestamp = intval($this->memberData['last_visit']) ? intval($this->memberData['last_visit']) : IPS_UNIX_TIME_NOW; } //----------------------------------------- // Only content we are following? //----------------------------------------- if (IPSSearchRegistry::get('in.vncFollowFilterOn') and $this->memberData['member_id']) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $like = classes_like::bootstrap('calendar', 'events'); $followedEvents = $like->getDataByMemberIdAndArea($this->memberData['member_id']); $followedEvents = $followedEvents === null ? array() : array_keys($followedEvents); if (!count($followedEvents)) { return array('count' => 0, 'resultSet' => array()); } else { $this->whereConditions['AND'][] = "c.event_id IN(" . implode(',', $followedEvents) . ")"; } } //----------------------------------------- // Only content we have participated in? //----------------------------------------- if (IPSSearchRegistry::get('in.userMode')) { switch (IPSSearchRegistry::get('in.userMode')) { default: case 'all': $_eventIds = $this->_getEventIdsFromComments(); if (count($_eventIds)) { $this->whereConditions['AND'][] = "(c.event_member_id=" . $this->memberData['member_id'] . " OR c.event_id IN(" . implode(',', $_eventIds) . "))"; } else { $this->whereConditions['AND'][] = "c.event_member_id=" . $this->memberData['member_id']; } break; case 'title': $this->whereConditions['AND'][] = "c.event_member_id=" . $this->memberData['member_id']; break; } } return $this->search(); }
/** * Builds the html for an event * * @param array Array of event data * @param bool Parse the data and return the parsed array, instead of the formatted HTML * @return string Parsed event HTML */ public function calendarMakeEventHTML($event, $returnAsArray = false) { //----------------------------------------- // Caching //----------------------------------------- static $cachedEvents = array(); if (isset($cachedEvents[$event['event_id']])) { if ($returnAsArray) { return $cachedEvents[$event['event_id']]; } else { return $this->registry->output->getTemplate('calendar')->showEvent($cachedEvents[$event['event_id']]['event'], $cachedEvents[$event['event_id']]['member'], array('type' => $cachedEvents[$event['event_id']]['info']['type'], 'ends' => $cachedEvents[$event['event_id']]['info']['ends'], 'calendars' => $this->functions->getCalendars(), 'calendar' => $this->calendar, 'chosen_date' => $this->chosen_date)); } } if ($this->canReport === 'notinit') { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/reportLibrary.php', 'reportLibrary'); $reports = new $classToLoad($this->registry); $this->canReport = $reports->canReport('calendar'); } $event['_canReport'] = $this->canReport; //----------------------------------------- // Get member details //----------------------------------------- $member = IPSMember::buildDisplayData($event); //----------------------------------------- // Like strip //----------------------------------------- if (!$this->_like) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $this->_like = classes_like::bootstrap('calendar', 'events'); } $event['_like_strip'] = $this->_like->render('summary', $event['event_id']); $event['_like_count'] = $this->_like->getCount($event['event_id']); //----------------------------------------- // Reputation //----------------------------------------- if (is_null($event['has_given_rep'])) { $event['has_given_rep'] = 0; } if (is_null($event['rep_points'])) { $event['rep_points'] = 0; } if ($this->settings['reputation_enabled']) { $event['like'] = $this->registry->repCache->getLikeFormatted(array('app' => 'calendar', 'type' => 'event_id', 'id' => $event['event_id'], 'rep_like_cache' => $event['rep_like_cache'])); } //----------------------------------------- // Times and dates //----------------------------------------- $event['_start_time'] = strtotime($event['event_start_date']); $event['_end_time'] = ($event['event_end_date'] and $event['event_end_date'] != '0000-00-00 00:00:00') ? strtotime($event['event_end_date']) : 0; if (!$event['event_all_day']) { if ($this->memberData['member_id'] and $this->memberData['time_offset']) { $event['_start_time'] = $event['_start_time'] + $this->memberData['time_offset'] * 3600; } else { if (!$this->memberData['member_id'] and $this->settings['time_offset']) { $event['_start_time'] = $event['_start_time'] + $this->settings['time_offset'] * 3600; } } if ($this->memberData['member_id'] and $this->memberData['time_offset']) { $event['_end_time'] = $event['_end_time'] ? $event['_end_time'] + $this->memberData['time_offset'] * 3600 : 0; } else { if (!$this->memberData['member_id'] and $this->settings['time_offset']) { $event['_end_time'] = $event['_end_time'] ? $event['_end_time'] + $this->settings['time_offset'] * 3600 : 0; } } } $event['_start_date'] = gmstrftime($this->settings['clock_date'], $event['_start_time']); $event['_event_time'] = ''; $event['_event_etime'] = ''; if (!$event['event_all_day']) { if ($this->settings['cal_time_format'] == 'standard') { $event['_event_time'] = gmstrftime('%I:%M %p', $event['_start_time']); $event['_event_etime'] = $event['_end_time'] ? gmstrftime('%I:%M %p', $event['_end_time']) : ''; } else { $event['_event_time'] = gmstrftime('%H:%M', $event['_start_time']); $event['_event_etime'] = $event['_end_time'] ? gmstrftime('%H:%M', $event['_end_time']) : ''; } } //----------------------------------------- // Event type //----------------------------------------- $type = $this->lang->words['se_normal']; $ends = ''; if (!$event['event_recurring'] and $event['_end_time'] and gmstrftime($this->settings['clock_date'], $event['_end_time']) != $event['_start_date']) { $type = $this->lang->words['se_range']; $ends = sprintf($this->lang->words['se_ends'], gmstrftime($this->settings['clock_date'], $event['_end_time'])); } else { if ($event['event_recurring']) { $type = $this->lang->words['se_recur']; $ends = sprintf($this->lang->words['se_ends'], gmstrftime($this->settings['clock_date'], $event['_end_time'])); } } //----------------------------------------- // Event content //----------------------------------------- IPSText::getTextClass('bbcode')->parse_html = 0; IPSText::getTextClass('bbcode')->parse_smilies = intval($event['event_smilies']); IPSText::getTextClass('bbcode')->parse_bbcode = 1; IPSText::getTextClass('bbcode')->parsing_section = 'calendar'; IPSText::getTextClass('bbcode')->parsing_mgroup = $member['member_group_id']; IPSText::getTextClass('bbcode')->parsing_mgroup_others = $member['mgroup_others']; $event['event_content'] = IPSText::getTextClass('bbcode')->preDisplayParse($event['event_content']); $event['event_attach_content'] = ''; //----------------------------------------- // Parse attachments //----------------------------------------- static $attachments = null; if ($event['event_attachments']) { //----------------------------------------- // Get attachments class //----------------------------------------- if (!$attachments) { $this->lang->loadLanguageFile(array('public_topic'), 'forums'); $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php', 'class_attach'); $attachments = new $classToLoad($this->registry); $attachments->type = 'event'; $attachments->init(); } $attachHTML = $attachments->renderAttachments(array($event['event_id'] => $event['event_content']), array($event['event_id'])); if (is_array($attachHTML)) { $event['event_content'] = $attachHTML[$event['event_id']]['html']; $event['event_attach_content'] = $attachHTML[$event['event_id']]['attachmentHtml']; } } //----------------------------------------- // Rating //----------------------------------------- $event['_can_rate'] = ($this->memberData['member_id'] and $this->registry->permissions->check('rate', $this->calendar)) ? 1 : 0; $event['_rating_value'] = -1; if ($event['_can_rate']) { $rating = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'cal_event_ratings', 'where' => "rating_eid={$event['event_id']} and rating_member_id=" . $this->memberData['member_id'])); $event['_rating_value'] = $rating['rating_value'] ? $rating['rating_value'] : -1; } //----------------------------------------- // RSVP attendees //----------------------------------------- $event['_rsvp_attendees'] = array(); $event['_rsvp_attendees_short'] = array(); $event['_rsvp_count'] = 0; $event['_can_rsvp'] = false; $event['_can_delete_rsvp'] = false; if ($event['event_rsvp']) { $this->DB->build(array('select' => 'a.*', 'from' => array('cal_event_rsvp' => 'a'), 'where' => 'a.rsvp_event_id=' . $event['event_id'], 'order' => 'm.members_display_name ASC', 'add_join' => array(array('select' => 'm.*', 'from' => array('members' => 'm'), 'where' => 'm.member_id=a.rsvp_member_id', 'type' => 'left'), array('select' => 'pp.*', 'from' => array('profile_portal' => 'pp'), 'where' => 'm.member_id=pp.pp_member_id', 'type' => 'left')))); $this->DB->execute(); while ($r = $this->DB->fetch()) { $event['_rsvp_attendees'][$r['member_id']] = IPSMember::buildDisplayData(array_merge($r, $this->caches['group_cache'][$r['member_group_id']])); $event['_rsvp_attendees'][$r['member_id']]['_can_delete_rsvp'] = false; if ($this->calendar['cal_rsvp_owner'] and $this->memberData['member_id'] and $this->memberData['member_id'] == $r['member_id']) { $event['_rsvp_attendees'][$r['member_id']]['_can_delete_rsvp'] = true; } if ($event['_rsvp_count'] < 5) { $event['_rsvp_attendees_short'][$r['member_id']] = $event['_rsvp_attendees'][$r['member_id']]; } $event['_rsvp_count']++; } if ($this->memberData['member_id'] and $this->registry->permissions->check('rsvp', $this->calendar)) { if (!isset($event['_rsvp_attendees'][$this->memberData['member_id']])) { $event['_can_rsvp'] = true; } else { $event['_have_rsvp'] = true; } } if ($this->calendar['cal_rsvp_owner'] and $this->memberData['member_id'] and $this->memberData['member_id'] == $event['event_member_id']) { $event['_can_delete_rsvp'] = true; } } //----------------------------------------- // Return formatted HTML //----------------------------------------- $cachedEvents[$event['event_id']] = array('member' => $member, 'event' => $event, 'info' => array('type' => $type, 'ends' => $ends)); if ($returnAsArray) { return $cachedEvents[$event['event_id']]; } else { return $this->registry->output->getTemplate('calendar')->showEvent($event, $member, array('type' => $type, 'ends' => $ends, 'calendars' => $this->functions->getCalendars(), 'calendar' => $this->calendar, 'chosen_date' => $this->chosen_date)); } }
/** * Import and parse an iCalendar feed * * @param string $content Feed content * @param int $member_id Member to save events under * @param int $feed_id Feed id * @return mixed False on failure, otherwise an array with keys 'skipped' and 'imported' */ public function import($content, $member_id = 0, $feed_id = 0) { //----------------------------------------- // Init //----------------------------------------- $this->lang->loadLanguageFile(array('admin_calendar'), 'calendar'); //----------------------------------------- // Error checking //----------------------------------------- if (!$content) { $this->_error = $this->lang->words['icali_nocontent']; return; } $_raw = preg_replace("#(\n\r|\r|\n){1,}#", "\n", $content); $_raw = explode("\n", $_raw); if (!count($_raw)) { $this->_error = $this->lang->words['icali_nocontent']; return; } if ($_raw[0] != 'BEGIN:VCALENDAR') { $this->_error = $this->lang->words['icali_badcontent']; return; } $this->_rawIcsData = $_raw; //----------------------------------------- // Loop and start parsing //----------------------------------------- foreach ($this->_rawIcsData as $k => $v) { $line = explode(':', $v); switch ($line[0]) { case 'BEGIN': $this->_parseBeginBlock($line[1], $k); break; /* Unsupported at this time */ /* Unsupported at this time */ case 'CALSCALE': case 'METHOD': case 'X-WR-TIMEZONE': case 'X-WR-RELCALID': default: break; } } //----------------------------------------- // Process raw ICS data now //----------------------------------------- if (count($this->_parsedIcsData)) { $this->_parsedIcsData = $this->_convertToGmt($this->_parsedIcsData); } //----------------------------------------- // And loop over results to insert //----------------------------------------- $_imported = 0; $_skipped = 0; // Leave this here - useful for debugging //print_r($this->_parsedIcsData);exit; if (count($this->_parsedIcsData)) { //----------------------------------------- // Get member data //----------------------------------------- $_member = IPSMember::load($member_id); if (!$_member) { $this->_error = $this->lang->words['icali_nomember']; return false; } //----------------------------------------- // Get like class for notifications //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('calendar', 'calendars'); //----------------------------------------- // Loop over the events //----------------------------------------- foreach ($this->_parsedIcsData['events'] as $event) { $event['uid'] = $event['uid'] ? $event['uid'] : md5(implode(',', $event)); $event_unix_from = $event['start']['gmt_ts']; $event_unix_to = $event['end']['gmt_ts']; $event_all_day = $event['start']['type'] == 'DATE' ? 1 : 0; //----------------------------------------- // End dates are "exclusive" in iCalendar format, meaning // they are actually the day ahead. // @link http://microformats.org/wiki/dtend-issue //----------------------------------------- if ($event_unix_to and $event['end']['type'] == 'DATE') { $event_unix_to -= 86400; } //----------------------------------------- // If end date is same as start date, it's a single day event //----------------------------------------- if ($event_unix_from == $event_unix_to) { $event_unix_to = 0; } //----------------------------------------- // If no end date, but we have a duration, calculate end date //----------------------------------------- if (!$event_unix_to and $event['duration']) { preg_match("#(\\d+?)H#is", $event['duration'], $match); $hour = $match[1] ? $match[1] : 0; preg_match("#(\\d+?)M#is", $event['duration'], $match); $minute = $match[1] ? $match[1] : 0; preg_match("#(\\d+?)S#is", $event['duration'], $match); $second = $match[1] ? $match[1] : 0; $event_unix_to = $event_unix_from + $hour * 3600 + $minute * 60 + $second; } //----------------------------------------- // Recurring... //----------------------------------------- $recurring = 0; if (isset($event['recurr']['FREQ'])) { if ($event['recurr']['FREQ'] == 'MONTHLY' and $event['recurr']['INTERVAL'] == 12) { $event['recurr']['FREQ'] = 'YEARLY'; } switch ($event['recurr']['FREQ']) { case 'WEEKLY': $recurring = 1; break; case 'MONTHLY': $recurring = 2; break; case 'YEARLY': $recurring = 3; break; } $event_unix_to = $event['recurr']['until_ts'] ? $event['recurr']['until_ts'] : time() + 86400 * 365 * 10; } //----------------------------------------- // Adjust timestamps if all day event //----------------------------------------- if ($event_all_day) { $event_unix_from = gmmktime(0, 0, 0, gmstrftime('%m', $event_unix_from), gmstrftime('%d', $event_unix_from), gmstrftime('%Y', $event_unix_from)); $event_unix_to = $event_unix_to ? gmmktime(0, 0, 0, gmstrftime('%m', $event_unix_to), gmstrftime('%d', $event_unix_to), gmstrftime('%Y', $event_unix_to)) : 0; } //----------------------------------------- // If we are missing crucial data, skip //----------------------------------------- if (!($event['description'] or $event['summary']) or !$event_unix_from) { $_skipped++; continue; } //----------------------------------------- // Skip previously imported events //----------------------------------------- if ($event['uid']) { $_check = $this->DB->buildAndFetch(array('select' => 'import_id', 'from' => 'cal_import_map', 'where' => "import_guid='" . $this->DB->addSlashes($event['uid']) . "'")); if ($_check['import_id']) { $_skipped++; continue; } } //----------------------------------------- // Format array for storage //----------------------------------------- $_eventData = array('event_calendar_id' => $this->calendar['cal_id'], 'event_member_id' => $_member['member_id'], 'event_content' => $event['description'] ? nl2br($event['description']) : $event['summary'], 'event_title' => $event['summary'] ? $event['summary'] : IPSText::truncate($event['description'], 100), 'event_title_seo' => IPSText::makeSeoTitle($event['summary']), 'event_smilies' => 1, 'event_comments' => 0, 'event_rsvp' => count($event['attendee']) ? 1 : 0, 'event_perms' => '*', 'event_private' => 0, 'event_approved' => 1, 'event_saved' => $event['created'] ? $event['created'] : time(), 'event_lastupdated' => $event['last_modified'] ? $event['last_modified'] : ($event['created'] ? $event['created'] : time()), 'event_recurring' => $recurring, 'event_start_date' => strftime("%Y-%m-%d %H:%M:00", $event_unix_from), 'event_end_date' => $event_unix_to ? strftime("%Y-%m-%d %H:%M:00", $event_unix_to) : 0, 'event_post_key' => md5(uniqid(microtime(), true)), 'event_sequence' => intval($event['sequence']), 'event_all_day' => $event_all_day); //----------------------------------------- // Data hooks //----------------------------------------- IPSLib::doDataHooks($_eventData, 'calendarAddEvent'); //----------------------------------------- // Insert //----------------------------------------- $this->DB->insert('cal_events', $_eventData); $event_id = $this->DB->getInsertId(); $_imported++; //----------------------------------------- // Insert mapping //----------------------------------------- $this->DB->insert('cal_import_map', array('import_feed_id' => $feed_id, 'import_event_id' => $event_id, 'import_guid' => $event['uid'])); //----------------------------------------- // If we have attendees that are members, insert them //----------------------------------------- if (isset($event['attendee']) and count($event['attendee'])) { foreach ($event['attendee'] as $attendee) { if ($attendee['email']) { $_loadedMember = IPSMember::load($attendee['email']); if ($_loadedMember['member_id']) { $this->DB->insert('cal_event_rsvp', array('rsvp_member_id' => $_loadedMember['member_id'], 'rsvp_event_id' => $event_id, 'rsvp_date' => time())); } } } } //----------------------------------------- // Send notifications //----------------------------------------- $_url = $this->registry->output->buildSEOUrl('app=calendar&module=calendar&section=view&do=showevent&event_id=' . $event_id, 'public', $_eventData['event_title_seo'], 'cal_event'); $_like->sendNotifications($_eventData['event_calendar_id'], array('immediate', 'offline'), array('notification_key' => 'new_event', 'notification_url' => $_url, 'email_template' => 'add_event_follow', 'email_subject' => sprintf($this->lang->words['add_event_follow_subject'], $_url, $_eventData['event_title']), 'build_message_array' => array('NAME' => '-member:members_display_name-', 'AUTHOR' => $_member['members_display_name'], 'TITLE' => $_eventData['event_title'], 'URL' => $_url))); } } //----------------------------------------- // Rebuild cache //----------------------------------------- $this->cache->rebuildCache('calendar_events', 'calendar'); //----------------------------------------- // Return //----------------------------------------- return array('skipped' => $_skipped, 'imported' => $_imported); }
/** * Merge two members * * @return @e void [Redirects to member account] * @author Brandon Farber */ protected function _completeMerge() { if (!$this->request['confirm']) { $member = IPSMember::load($this->request['member_id']); //----------------------------------------- // Load member //----------------------------------------- $newMember = NULL; $_newMember = NULL; /* Name */ if ($this->request['name']) { $newMember = IPSMember::load($this->request['name'], '', 'displayname'); $_newMember = $newMember['member_id']; } /* Email */ if ($this->request['email']) { $newMember = IPSMember::load($this->request['email'], '', 'email'); if ($_newMember !== NULL and $_newMember != $newMember['member_id']) { $this->registry->output->global_error = $this->lang->words['err_transfer_badmulti']; $this->_mergeForm(); return false; } $_newMember = $newMember['member_id']; } /* ID */ if ($this->request['target_id']) { $newMember = IPSMember::load(intval($this->request['target_id']), '', 'id'); if ($_newMember !== NULL and $_newMember != $newMember['member_id']) { $this->registry->output->global_error = $this->lang->words['err_transfer_badmulti']; $this->_mergeForm(); return false; } $_newMember = $newMember['member_id']; } if (!$newMember['member_id']) { $this->registry->output->global_error = $this->lang->words['no_merge_id']; $this->_mergeForm(); return false; } $member2 = $newMember; if (!$member['member_id'] or !$member2['member_id']) { $this->registry->output->global_error = $this->lang->words['no_merge_id']; $this->_mergeForm(); return false; } //----------------------------------------- // Output //----------------------------------------- $this->registry->output->html .= $this->html->mergeConfirm($member, $newMember); } else { $member = IPSMember::load($this->request['member_id']); $member2 = IPSMember::load($this->request['member_id2']); if (!$member['member_id'] or !$member2['member_id']) { $this->registry->output->global_error = $this->lang->words['no_merge_id']; $this->_mergeForm(); return false; } //----------------------------------------- // Take care of forum stuff //----------------------------------------- $this->DB->update('posts', array('author_name' => $member['members_display_name'], 'author_id' => $member['member_id']), "author_id=" . $member2['member_id']); $this->DB->update('topics', array('starter_name' => $member['members_display_name'], 'seo_first_name' => $member['members_seo_name'], 'starter_id' => $member['member_id']), "starter_id=" . $member2['member_id']); $this->DB->update('topics', array('last_poster_name' => $member['members_display_name'], 'seo_last_name' => $member['members_seo_name'], 'last_poster_id' => $member['member_id']), "last_poster_id=" . $member2['member_id']); $this->DB->update('announcements', array('announce_member_id' => $member['member_id']), "announce_member_id=" . $member2['member_id']); $this->DB->update('attachments', array('attach_member_id' => $member['member_id']), "attach_member_id=" . $member2['member_id']); $this->DB->update('polls', array('starter_id' => $member['member_id']), "starter_id=" . $member2['member_id']); $this->DB->update('topic_ratings', array('rating_member_id' => $member['member_id']), "rating_member_id=" . $member2['member_id']); $this->DB->update('moderators', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); $this->DB->update('forums', array('last_poster_name' => $member['members_display_name'], 'seo_last_name' => $member['members_seo_name'], 'last_poster_id' => $member['member_id']), "last_poster_id=" . $member2['member_id']); $this->DB->update('core_share_links_log', array('log_member_id' => $member['member_id']), "log_member_id=" . $member2['member_id']); $this->DB->update('core_soft_delete_log', array('sdl_obj_member_id' => $member['member_id']), "sdl_obj_member_id=" . $member2['member_id']); $this->DB->update('rss_import', array('rss_import_mid' => $member['member_id']), "rss_import_mid=" . $member2['member_id']); $this->DB->update('core_tags', array('tag_member_id' => $member['member_id']), "tag_member_id=" . $member2['member_id']); /* Update archived posts */ $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/archive/writer.php', 'classes_archive_writer'); $archiveWriter = new $classToLoad(); $archiveWriter->setApp('forums'); $archiveWriter->update(array('archive_author_id' => $member['member_id'], 'archive_author_name' => $member['members_display_name']), 'archive_author_id=' . $member2['member_id']); //----------------------------------------- // Clean up profile stuff //----------------------------------------- $this->DB->update('profile_portal_views', array('views_member_id' => $member['member_id']), "views_member_id=" . $member2['member_id']); $this->DB->update('members_warn_logs', array('wl_member' => $member['member_id']), "wl_member=" . $member2['member_id']); $this->DB->update('members_warn_logs', array('wl_moderator' => $member['member_id']), "wl_moderator=" . $member2['member_id']); $this->DB->update('dnames_change', array('dname_member_id' => $member['member_id']), "dname_member_id=" . $member2['member_id']); $this->DB->update('mobile_notifications', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); $this->DB->update('inline_notifications', array('notify_to_id' => $member['member_id']), "notify_to_id=" . $member2['member_id']); $this->DB->update('inline_notifications', array('notify_from_id' => $member['member_id']), "notify_from_id=" . $member2['member_id']); //----------------------------------------- // Statuses //----------------------------------------- $this->DB->update('member_status_actions', array('action_member_id' => $member['member_id']), "action_member_id=" . $member2['member_id']); $this->DB->update('member_status_actions', array('action_status_owner' => $member['member_id']), "action_status_owner=" . $member2['member_id']); $this->DB->update('member_status_replies', array('reply_member_id' => $member['member_id']), "reply_member_id=" . $member2['member_id']); $this->DB->update('member_status_updates', array('status_member_id' => $member['member_id']), "status_member_id=" . $member2['member_id']); $this->DB->update('member_status_updates', array('status_author_id' => $member['member_id']), "status_author_id=" . $member2['member_id']); $statusUpdates = array(); $this->DB->build(array('select' => 'status_id', 'from' => 'member_status_updates', 'where' => 'status_member_id=' . $member['member_id'])); $res = $this->DB->execute(); while ($r = $this->DB->fetch($res)) { $this->registry->getClass('memberStatus')->rebuildStatus($r); } //----------------------------------------- // Update admin stuff //----------------------------------------- $this->DB->update('upgrade_history', array('upgrade_mid' => $member['member_id']), "upgrade_mid=" . $member2['member_id']); $this->DB->update('admin_logs', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); $this->DB->update('error_logs', array('log_member' => $member['member_id']), "log_member=" . $member2['member_id']); $this->DB->update('moderator_logs', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); $this->DB->update('rc_comments', array('comment_by' => $member['member_id']), "comment_by=" . $member2['member_id']); $this->DB->update('rc_reports', array('report_by' => $member['member_id']), "report_by=" . $member2['member_id']); $this->DB->update('rc_reports_index', array('updated_by' => $member['member_id']), "updated_by=" . $member2['member_id']); $this->DB->update('rc_reports_index', array('exdat1' => $member['member_id']), "seotemplate='showuser' AND exdat1=" . $member2['member_id']); $this->DB->update('reputation_cache', array('type_id' => $member['member_id']), "type='member' AND type_id=" . $member2['member_id']); $this->DB->update('reputation_index', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); //----------------------------------------- // Fix up member messages... //----------------------------------------- $this->DB->update('message_posts', array('msg_author_id' => $member['member_id']), 'msg_author_id=' . $member2['member_id']); $this->DB->update('message_topics', array('mt_starter_id' => $member['member_id']), 'mt_starter_id=' . $member2['member_id']); $this->DB->update('message_topics', array('mt_to_member_id' => $member['member_id']), 'mt_to_member_id=' . $member2['member_id']); //----------------------------------------- // Stuff that can't have duplicates //----------------------------------------- //----------------------------------------- // Likes - also invalidates likes cache //----------------------------------------- /* Followed stuffs */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $like = classes_like::bootstrap('core', 'default'); $like->updateMemberId($member2['member_id'], $member['member_id']); //----------------------------------------- // Poll votes //----------------------------------------- $voters = array(); $this->DB->build(array('select' => 'tid', 'from' => 'voters', 'where' => 'member_id=' . $member['member_id'])); $this->DB->execute(); while ($r = $this->DB->fetch()) { $voters[] = $r['tid']; } if (count($voters)) { $this->DB->update('voters', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id'] . " AND tid NOT IN(" . implode(',', $voters) . ")"); } else { $this->DB->update('voters', array('member_id' => $member['member_id']), "member_id=" . $member2['member_id']); } //----------------------------------------- // Profile ratings //----------------------------------------- $ratingsFor = array(); $ratingsGot = array(); $this->DB->build(array('select' => 'rating_by_member_id,rating_for_member_id', 'from' => 'profile_ratings', 'where' => 'rating_by_member_id=' . $member['member_id'] . ' OR rating_for_member_id=' . $member['member_id'])); $this->DB->execute(); while ($r = $this->DB->fetch()) { if ($r['rating_by_member_id'] == $member['member_id']) { $ratingsFor[] = $r['rating_for_member_id']; } if ($r['rating_for_member_id'] == $member['member_id']) { $ratingsGot[] = $r['rating_by_member_id']; } } if (count($ratingsFor)) { $this->DB->update('profile_ratings', array('rating_by_member_id' => $member['member_id']), "rating_by_member_id=" . $member2['member_id'] . " AND rating_for_member_id NOT IN(" . implode(',', $ratingsFor) . ")"); } else { $this->DB->update('profile_ratings', array('rating_by_member_id' => $member['member_id']), "rating_by_member_id=" . $member2['member_id']); } if (count($ratingsGot)) { $this->DB->update('profile_ratings', array('rating_for_member_id' => $member['member_id']), "rating_for_member_id=" . $member2['member_id'] . " AND rating_by_member_id NOT IN(" . implode(',', $ratingsGot) . ")"); } else { $this->DB->update('profile_ratings', array('rating_for_member_id' => $member['member_id']), "rating_for_member_id=" . $member2['member_id']); } //----------------------------------------- // Profile friends //----------------------------------------- $myFriends = array(); $friendsMy = array(); $this->DB->build(array('select' => 'friends_member_id,friends_friend_id', 'from' => 'profile_friends', 'where' => 'friends_member_id=' . $member['member_id'] . ' OR friends_friend_id=' . $member['member_id'])); $this->DB->execute(); while ($r = $this->DB->fetch()) { if ($r['friends_member_id'] == $member['member_id']) { $myFriends[] = $r['friends_friend_id']; } if ($r['friends_friend_id'] == $member['member_id']) { $friendsMy[] = $r['friends_member_id']; } } if (count($myFriends)) { $this->DB->update('profile_friends', array('friends_member_id' => $member['member_id']), "friends_member_id=" . $member2['member_id'] . " AND friends_friend_id NOT IN(" . implode(',', $myFriends) . ")"); } else { $this->DB->update('profile_friends', array('friends_member_id' => $member['member_id']), "friends_member_id=" . $member2['member_id']); } if (count($friendsMy)) { $this->DB->update('profile_friends', array('friends_friend_id' => $member['member_id']), "friends_friend_id=" . $member2['member_id'] . " AND friends_member_id NOT IN(" . implode(',', $friendsMy) . ")"); } else { $this->DB->update('profile_friends', array('friends_friend_id' => $member['member_id']), "friends_friend_id=" . $member2['member_id']); } //----------------------------------------- // Ignored users //----------------------------------------- $myIgnored = array(); $ignoredMe = array(); $this->DB->build(array('select' => 'ignore_owner_id,ignore_ignore_id', 'from' => 'ignored_users', 'where' => 'ignore_owner_id=' . $member['member_id'] . ' OR ignore_ignore_id=' . $member['member_id'])); $this->DB->execute(); while ($r = $this->DB->fetch()) { if ($r['ignore_owner_id'] == $member['member_id']) { $myIgnored[] = $r['ignore_ignore_id']; } if ($r['ignore_ignore_id'] == $member['member_id']) { $ignoredMe[] = $r['ignore_owner_id']; } } if (count($myIgnored)) { $this->DB->update('ignored_users', array('ignore_owner_id' => $member['member_id']), "ignore_owner_id=" . $member2['member_id'] . " AND ignore_ignore_id NOT IN(" . implode(',', $myIgnored) . ")"); } else { $this->DB->update('ignored_users', array('ignore_owner_id' => $member['member_id']), "ignore_owner_id=" . $member2['member_id']); } if (count($ignoredMe)) { $this->DB->update('ignored_users', array('ignore_ignore_id' => $member['member_id']), "ignore_ignore_id=" . $member2['member_id'] . " AND ignore_owner_id NOT IN(" . implode(',', $ignoredMe) . ")"); } else { $this->DB->update('ignored_users', array('ignore_ignore_id' => $member['member_id']), "ignore_ignore_id=" . $member2['member_id']); } //----------------------------------------- // Message topic mapping //----------------------------------------- $pms = array(); $this->DB->build(array('select' => 'map_topic_id', 'from' => 'message_topic_user_map', 'where' => 'map_user_id=' . $member['member_id'])); $this->DB->execute(); while ($r = $this->DB->fetch()) { $pms[] = $r['map_topic_id']; } if (count($pms)) { $this->DB->update('message_topic_user_map', array('map_user_id' => $member['member_id']), "map_user_id=" . $member2['member_id'] . " AND map_topic_id NOT IN(" . implode(',', $pms) . ")"); } else { $this->DB->update('message_topic_user_map', array('map_user_id' => $member['member_id']), 'map_user_id=' . $member2['member_id']); } //----------------------------------------- // Admin permissions //----------------------------------------- $count = $this->DB->buildAndFetch(array('select' => 'row_id', 'from' => 'admin_permission_rows', 'where' => "row_id_type='member' AND row_id=" . $member['member_id'])); if (!$count['row_id']) { $this->DB->update('admin_permission_rows', array('row_id' => $member['member_id']), "row_id_type='member' AND row_id=" . $member2['member_id']); } //----------------------------------------- // Member Sync //----------------------------------------- try { IPSMember::save($member['member_id'], array('core' => array('posts' => $member['posts'] + $member2['posts'], 'warn_level' => $member['warn_level'] + $member2['warn_level'], 'warn_lastwarn' => $member2['warn_lastwarn'] > $member['warn_lastwarn'] ? $member2['warn_lastwarn'] : $member['warn_lastwarn'], 'last_post' => $member2['last_post'] > $member['last_post'] ? intval($member2['last_post']) : intval($member['last_post']), 'last_visit' => $member2['last_visit'] > $member['last_visit'] ? $member2['last_visit'] : $member['last_visit']), 'extendedProfile' => array('pp_reputation_points' => $member['pp_reputation_points'] + $member2['pp_reputation_points']))); } catch (Exception $error) { $this->registry->output->showError($error->getMessage(), 11247); } IPSLib::runMemberSync('onMerge', $member, $member2); //----------------------------------------- // Delete member 2 //----------------------------------------- IPSMember::remove($member2['member_id'], false); //----------------------------------------- // Get current stats... //----------------------------------------- $this->cache->rebuildCache('stats', 'global'); $this->cache->rebuildCache('moderators', 'forums'); $this->cache->rebuildCache('announcements', 'forums'); //----------------------------------------- // Admin logs //----------------------------------------- $this->registry->adminFunctions->saveAdminLog(sprintf($this->lang->words['merged_accounts_log'], $member2['members_display_name'], $member['members_display_name'])); //----------------------------------------- // Redirect //----------------------------------------- $this->registry->output->global_message = $this->lang->words['merged_members']; $this->registry->output->silentRedirectWithMessage($this->settings['base_url'] . "module=members&section=members&do=viewmember&member_id=" . $member['member_id']); } }
/** * Delete a member's email subscriptions * * @return @e void * @author Brandon Farber * @since IPB3 / 22 Oct 2008 */ protected function _deleteSubscriptions() { $member_id = intval($this->request['member_id']); require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $_like->removeByMemberId($member_id); $_like = classes_like::bootstrap('forums', 'forums'); $_like->removeByMemberId($member_id); $this->registry->output->redirect($this->settings['_base_url'] . "app=members&module=members&section=members&do=viewmember&member_id={$member_id}", $this->lang->words['m_subs_redirect']); }
/** * Delete a calendar * * @return @e void */ public function calendarDelete() { //----------------------------------------- // Init //----------------------------------------- $cal_id = intval($this->request['cal_id']); if (!$cal_id) { $this->registry->output->global_message = $this->lang->words['c_noid']; $this->calendarsList(); return; } //----------------------------------------- // Delete //----------------------------------------- $this->DB->delete('cal_calendars', 'cal_id=' . $cal_id); $this->DB->delete('permission_index', "app='calendar' AND perm_type='calendar' AND perm_type_id=" . $cal_id); //----------------------------------------- // Get feeds for removal //----------------------------------------- $_feedIds = array(); $this->DB->build(array('select' => 'feed_id', 'from' => 'cal_import_feeds', 'where' => 'feed_calendar_id=' . $cal_id)); $this->DB->execute(); while ($r = $this->DB->fetch()) { $_feedIds[] = $r['feed_id']; } $this->DB->delete('cal_import_feeds', 'feed_calendar_id=' . $cal_id); if (count($_feedIds)) { $this->DB->delete('cal_import_map', 'import_feed_id IN(' . implode(',', $_feedIds) . ')'); } //----------------------------------------- // Get event ids for comments/ratings //----------------------------------------- $_eventIds = array(); $this->DB->build(array('select' => 'event_id', 'from' => 'cal_events', 'where' => 'event_calendar_id=' . $cal_id)); $this->DB->execute(); while ($r = $this->DB->fetch()) { $_eventIds[] = $r['event_id']; } if (count($_eventIds)) { $this->DB->delete('cal_event_comments', 'comment_eid IN(' . implode(',', $_eventIds) . ')'); $this->DB->delete('cal_event_ratings', 'rating_eid IN(' . implode(',', $_eventIds) . ')'); $this->DB->delete('cal_event_rsvp', 'rsvp_event_id IN(' . implode(',', $_eventIds) . ')'); //----------------------------------------- // Delete attachments //----------------------------------------- $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php', 'class_attach'); $class_attach = new $classToLoad($this->registry); $class_attach->type = 'event'; $class_attach->init(); $class_attach->bulkRemoveAttachment($_eventIds); } $this->DB->delete('cal_events', 'event_calendar_id=' . $cal_id); //----------------------------------------- // Remove likes //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('calendar', 'calendars'); $_like->remove($cal_id); //----------------------------------------- // Rebuild caches //----------------------------------------- $this->calendarsRebuildCache(); $this->cache->rebuildCache('calendar_events', 'calendar'); $this->cache->rebuildCache('rss_calendar', 'calendar'); //----------------------------------------- // Redirect //----------------------------------------- $this->registry->output->global_message = $this->lang->words['c_removed']; $this->calendarsList(); }
/** * Generates checkboxes * * @param string Type of form * @param int Topic ID * @param int Forum ID * @return string HTML of Checkboxes */ protected function _generateCheckBoxes($type = "", $topicID = "", $forumID = "") { //----------------------------------------- // INIT //----------------------------------------- $options_array = array(0 => '', 1 => '', 2 => ''); $group_cache = $this->registry->cache()->getCache('group_cache'); $return = array('sig' => 'checked="checked"', 'emo' => 'checked="checked"', 'html' => null, 'tra' => ($this->getAuthor('auto_track') and !$topicID or $this->getSettings('enableTracker')) ? 'checked="checked"' : ''); if (!$this->getSettings('enableSignature')) { $return['sig'] = ""; } if (!$this->getSettings('enableEmoticons')) { $return['emo'] = ""; } if ($this->_canHtml($forumID)) { $return['html'] = $this->getSettings('post_htmlstatus') ? ' checked="checked"' : ''; } if ($type == 'reply') { if ($topicID and $this->getAuthor('member_id')) { //----------------------------------------- // Like class //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $_track = $_like->isLiked($topicID, $this->getAuthor('member_id')); if ($_track) { $return['tra'] = '-tracking-'; } } } return $return; }
/** * Show unsubscribe dialogue * * @return @e void */ protected function _unsubscribe() { /* Fetch data */ $key = trim(IPSText::base64_decode_urlSafe($this->request['key'])); list($app, $area, $relId, $likeMemberId, $memberId, $email) = explode(';', $key); /* Sanitize */ $relId = intval($relId); $likeMemberId = intval($likeMemberId); $memberId = intval($memberId); $app = IPSText::alphanumericalClean($app); $area = IPSText::alphanumericalClean($area); /* Member? */ if (!$this->memberData['member_id']) { $this->registry->output->showError('no_permission', 'pcgl-1'); } if (!$app || !$area || !$relId) { $this->registry->output->showError('no_permission', 'pcgl-1'); } if ($memberId != $likeMemberId || $memberId != $this->memberData['member_id']) { $this->registry->output->showError('no_unfollow', 'pcgl-2'); } if ($email != $this->memberData['email']) { $this->registry->output->showError('no_unfollow', 'pcgl-3'); } /* Think we're safe... */ try { $this->_like = classes_like::bootstrap($app, $area); } catch (Exception $ex) { $this->registry->output->showError('no_permission', 'pcgl-4'); } /* Get data */ $data = $this->_like->getDataByRelationshipId($relId, false); if (!is_array($data[$this->memberData['member_id']])) { $this->registry->output->showError($this->lang->words['pg_no_longer_following'], 'pcgl-4'); } /* Get meta */ $meta = $this->_like->getMeta($relId); /* Display box, then */ $this->registry->output->setTitle($this->lang->words['pg_unfollow_title'] . ' - ' . ipsRegistry::$settings['board_name']); $this->registry->output->addNavigation($this->lang->words['pg_unfollow_title'], ''); return $this->registry->output->getTemplate('global_other')->followUnsubscribe($data, $meta); }
/** * Main Execution Function * * @param object Registry reference * @return @e void [Outputs to screen/redirects] */ public function doExecute(ipsRegistry $registry) { //----------------------------------------- // INIT //----------------------------------------- $post_data = array(); $poll_data = ''; $function = ''; /* Print CSS */ $this->registry->output->addToDocumentHead('raw', "<link rel='stylesheet' type='text/css' title='Main' media='print' href='{$this->settings['css_base_url']}style_css/{$this->registry->output->skin['_csscacheid']}/ipb_print.css' />"); /* Followed stuffs */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $this->_like = classes_like::bootstrap('forums', 'topics'); /* Init */ if (!$this->registry->isClassLoaded('topics')) { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . "/sources/classes/topics.php", 'app_forums_classes_topics', 'forums'); $this->registry->setClass('topics', new $classToLoad($this->registry)); } try { /* Load up the data dudes */ $this->registry->getClass('topics')->autoPopulate(null, false); } catch (Exception $crowdCheers) { $msg = str_replace('EX_', '', $crowdCheers->getMessage()); $this->registry->output->showError($msg, 10340, null, null, 404); } /* Shortcut */ $this->forumClass = $this->registry->getClass('class_forums'); /* Setup basics for this method */ $topicData = $this->registry->getClass('topics')->getTopicData(); $forumData = $this->forumClass->getForumById($topicData['forum_id']); /* VigLink */ if (!$forumData['viglink']) { $this->settings['viglink_enabled'] = FALSE; } /* Rating */ $this->can_rate = $this->memberData['member_id'] ? intval($this->memberData['g_topic_rate_setting']) : 0; /* Set up topic */ $topicData = $this->topicSetUp($topicData); /* Specific view? */ $this->_doViewCheck(); /* Get Posts */ $_NOW = IPSDebug::getMemoryDebugFlag(); if ($this->registry->getClass('topics')->isArchived($topicData) && $this->registry->class_forums->fetchArchiveTopicType($topicData) != 'working') { /* Load up archive class */ $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/archive/reader.php', 'classes_archive_reader'); $this->archiveReader = new $classToLoad(); $this->archiveReader->setApp('forums'); $postData = $this->archiveReader->get(array('parentData' => $topicData, 'goNative' => true, 'offset' => intval($this->registry->getClass('topics')->pageToSt($this->request['page'])), 'limit' => intval($this->settings['display_max_posts']), 'sortKey' => $this->settings['post_order_column'], 'sortOrder' => $this->settings['post_order_sort'])); } else { $postData = $this->_getPosts(); } /* Finish off post Data */ if (count($postData)) { foreach ($postData as $pid => $data) { $postData[$pid] = $this->parsePostRow($data); } } /* Do we have a P parameter, and if so, is it actually in this set of results? */ if (!$this->request['view'] && ($this->request['p'] && !in_array($this->request['p'], array_keys($postData)))) { /* Go find it */ $this->request['view'] = 'findpost'; $this->_doViewCheck(); /* Exits above */ } unset($this->cached_members); /* Status? */ if ($topicData['_ppd_ok'] === TRUE) { /* status from PPD */ if ($this->forumClass->ppdStatusMessage) { $topicData['_fastReplyStatusMessage'][] = $this->forumClass->ppdStatusMessage; } } $topicData['_fastReplyModAll'] = FALSE; switch (intval($forumData['preview_posts'])) { case 1: case 3: $topicData['_fastReplyModAll'] = TRUE; break; } //----------------------------------------- // Update the item marker //----------------------------------------- if (!$this->request['view'] && !$this->registry->getClass('topics')->isArchived($topicData)) { /* If we marked page 2 but land back on page 1 again we don't want to unmark it! */ $lastMarked = $this->registry->classItemMarking->fetchTimeLastMarked(array('forumID' => $forumData['id'], 'itemID' => $topicData['tid'])); /* is this the very last page? */ if ($this->registry->getClass('topics')->isOnLastPage()) { /* ...then make the timestamp 'NOW' so polls will be cleared correctly */ $this->_maxPostDate = IPS_UNIX_TIME_NOW; } if ($lastMarked < $this->_maxPostDate) { $this->registry->getClass('classItemMarking')->markRead(array('forumID' => $forumData['id'], 'itemID' => $topicData['tid'], 'markDate' => $this->_maxPostDate, 'containerLastActivityDate' => $forumData['last_post'])); } } /* add meta update time */ if ($this->_maxPostDate) { $this->registry->output->addMetaTag('og:updated_time', $this->_maxPostDate, false); } /* Set has unread flag */ $forumData['_hasUnreadTopics'] = $this->registry->getClass('class_forums')->getHasUnread($forumData['id']); IPSDebug::setMemoryDebugFlag("TOPICS: Parsed Posts - Completed", $_NOW); //----------------------------------------- // Generate template //----------------------------------------- $topicData['id'] = $topicData['forum_id']; //----------------------------------------- // This has to be called first to set $this->poll_only //----------------------------------------- $poll_data = $topicData['poll_state'] ? $this->_generatePollOutput() : array('html' => '', 'poll' => ''); $displayData = array('fast_reply' => $this->_getFastReplyData(), 'multi_mod' => $this->registry->getClass('topics')->getMultiModerationData(), 'reply_button' => $this->_getReplyButtonData(), 'active_users' => $this->_getActiveUserData(), 'mod_links' => $this->registry->getClass('topics')->isArchived($topicData) ? '' : $this->_generateModerationPanel(), 'follow_data' => ($this->registry->getClass('topics')->isArchived($topicData) or $topicData['_isDeleted']) ? '' : $this->_like->render('summary', $topicData['tid']), 'same_tagged' => $this->registry->getClass('topics')->isArchived($topicData) ? '' : $this->_getSameTaggedData(), 'poll_data' => $poll_data, 'load_editor_js' => $this->_getFastReplyData() && $topicData['_isDeleted'] ? true : false, 'smilies' => '', 'best_answer_post_data' => $this->_getBestAnswerFeature($postData, $topicData)); //----------------------------------------- // If we can edit, but not reply, load JS still //----------------------------------------- if (!($displayData['fast_reply'] and $displayData['reply_button']['url']) and $this->_canEditAPost) { $displayData['load_editor_js'] = true; $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite'); $editor = new $classToLoad(); $displayData['smilies'] = $editor->fetchEmoticons(); } $postData = $this->_parseAttachments($postData); /* Rules */ if ($forumData['show_rules'] == 2) { IPSText::getTextClass('bbcode')->parse_smilies = 1; IPSText::getTextClass('bbcode')->parse_html = 1; IPSText::getTextClass('bbcode')->parse_nl2br = 1; IPSText::getTextClass('bbcode')->parse_bbcode = 1; IPSText::getTextClass('bbcode')->parsing_section = 'topics'; IPSText::getTextClass('bbcode')->parsing_mgroup = $this->memberData['member_group_id']; IPSText::getTextClass('bbcode')->parsing_mgroup_others = $this->memberData['mgroup_others']; $forumData['rules_text'] = IPSText::getTextClass('bbcode')->preDisplayParse($forumData['rules_text']); } /* Got soft delete pids? */ if (is_array($this->_sdPids) and count($this->_sdPids)) { $displayData['sdData'] = IPSDeleteLog::fetchEntries($this->_sdPids, 'post', false); } if ($topicData['_isDeleted']) { $topicData['sdData'] = IPSDeleteLog::fetchEntries(array($topicData['tid']), 'topic', false); $topicData['sdData'] = $topicData['sdData'][$topicData['tid']]; } if ($topicData['starter_id']) { $topicData['_starter'] = IPSMember::buildDisplayData(IPSMember::load($topicData['starter_id'])); } else { $topicData['_starter'] = IPSMember::buildDisplayData(IPSMember::setUpGuest($topicData['starter_name'] ? $this->settings['guest_name_pre'] . $topicData['starter_name'] . $this->settings['guest_name_suf'] : '')); } /* Can we report? */ $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/reportLibrary.php', 'reportLibrary', 'core'); $reports = new $classToLoad($this->registry); $topicData['_canReport'] = $reports->canReport('post'); /* No likey no lighty */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $topicData['_isLiked'] = $this->memberData['member_id'] ? $_like->isLiked($topicData['tid'], $this->memberData['member_id']) : false; $template = $this->registry->output->getTemplate('topic')->topicViewTemplate($forumData, $topicData, $postData, $displayData); //----------------------------------------- // Send for output //----------------------------------------- $this->registry->output->setTitle(strip_tags($topicData['title']) . '<%pageNumber%> - ' . $forumData['name'] . ' - ' . $this->settings['board_name']); $this->registry->output->addContent($template); if (is_array($this->nav) and count($this->nav)) { foreach ($this->nav as $_nav) { $this->registry->output->addNavigation($_nav[0], $_nav[1], $_nav[2], $_nav[3]); } } /** * Add navigational links */ $this->registry->output->addToDocumentHead('raw', "<link rel='up' href='" . $this->registry->output->buildSEOUrl('showforum=' . $topicData['forum_id'], 'publicNoSession', $forumData['name_seo'], 'showforum') . "' />"); $this->registry->output->addToDocumentHead('raw', "<link rel='author' href='" . $this->registry->output->buildSEOUrl('showuser='******'starter_id'], 'publicNoSession', $topicData['seo_first_name'], 'showuser') . "' />"); /* Add Meta Content */ if ($this->_firstPostContent) { /* Strip tags on title to ensure multi-mod added code isn't displayed */ $this->registry->output->addMetaTag('keywords', strip_tags(trim($topicData['title']) . ' ' . str_replace("\n", " ", str_replace("\r", "", strip_tags($this->_firstPostContent)))), TRUE); } $pageData = $this->registry->output->getPaginationProcessedData(); $pageMeta = $pageData['pages'] > 1 ? sprintf($this->lang->words['topic_meta_pages'], $pageData['current_page'], $pageData['pages']) . ' ' : ''; # Trim to 155 chars based on Dan's recommendation $this->registry->output->addMetaTag('description', trim($pageMeta . sprintf($this->lang->words['topic_meta_description'], strip_tags($topicData['title']), $forumData['name'], str_replace("\r", "", $this->_firstPostContent))), FALSE); /* Set Ad code for the board index */ if ($this->registry->getClass('IPSAdCode')->userCanViewAds()) { $this->registry->getClass('IPSAdCode')->setGlobalCode('header', 'ad_code_topic_view_header'); $this->registry->getClass('IPSAdCode')->setGlobalCode('footer', 'ad_code_topic_view_footer'); } $this->registry->output->sendOutput(); }
/** * Saves the post * * @return @e void */ protected function _reply() { /* Init */ $fid = intval($this->request['f']); $tid = intval($this->request['t']); $topPid = intval($this->request['pid']); /* Basic checks */ if (!$tid) { $this->returnJsonError($this->lang->words['ajax_reply_noperm']); } if ($this->memberData['member_id']) { if (IPSMember::isOnModQueue($this->memberData) === NULL) { $this->returnJsonError($this->lang->words['ajax_reply_noperm']); } } /* Load lang and classes */ $this->registry->getClass('class_localization')->loadLanguageFile(array('public_topics')); if (!is_object($this->postClass)) { require_once IPSLib::getAppDir('forums') . '/sources/classes/post/classPost.php'; /*noLibHook*/ $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . '/sources/classes/post/classPostForms.php', 'classPostForms', 'forums'); $this->postClass = new $classToLoad($this->registry); } /* Fetch topic data */ $topicData = $this->registry->getClass('topics')->getTopicById($tid); if (!$this->registry->getClass('topics')->canView($topicData)) { $this->returnJsonError($this->lang->words['ajax_reply_noperm']); } /* Duplicate posts */ if (time() - $this->memberData['last_post'] <= 4) { $_lastPost = $this->DB->buildAndFetch(array('select' => 'topic_id', 'from' => 'posts', 'where' => 'author_id=' . $this->memberData['member_id'], 'order' => 'post_date DESC', 'limit' => array(0, 1))); /* We made a reply within the last 4 seconds to this topic.. */ if ($_lastPost['topic_id'] == $tid) { $this->returnJsonError($this->lang->words['topic_duplicate_post']); } } /* Regular group flood check */ if ($this->settings['flood_control'] > 0 && $this->memberData['g_avoid_flood'] != 1) { if (time() - $this->memberData['last_post'] < $this->settings['flood_control'] or time() < $this->memberData['last_post']) { $this->returnJsonError($this->lang->words['topic_duplicate_post']); } } /* Are we following? */ if ($this->memberData['auto_track']) { $_likes = 1; } else { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $_likes = $_like->isLiked($topicData['tid'], $this->memberData['member_id']); } /* Set post class data */ $this->postClass->setForumData($this->registry->getClass('class_forums')->getForumById($topicData['forum_id'])); $this->postClass->setTopicID($tid); $this->postClass->setForumID($fid); $this->postClass->setSettings(array('enableSignature' => 1, 'enableEmoticons' => 1, 'post_htmlstatus' => 0, 'enableTracker' => $_likes ? 1 : 0)); /* Topic Data */ $this->postClass->setTopicData($topicData); $this->postClass->setAuthor($this->member->fetchMemberData()); $this->postClass->setIsAjax(TRUE); $this->postClass->setPublished('reply'); $this->postClass->setPostContent($_POST['Post']); /* POST */ try { /** * If there was an error, return it as a JSON error */ if ($this->postClass->addReply() === FALSE) { $this->returnJsonError($this->postClass->getPostError()); } /* If it requires preview, return a message */ if ($this->postClass->getPublished() === false) { $this->returnJsonArray(array('success' => 1, 'message' => $this->lang->words['thanks_need_preview'])); } IPSDebug::fireBug('info', array('The post was successfully saved...')); $topic = $this->postClass->getTopicData(); $post = $this->postClass->getPostData(); /* If we are merging, back up one */ if ($post['pid'] == $topPid) { $topPid--; } /* Can we report? */ $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/reportLibrary.php', 'reportLibrary', 'core'); $reports = new $classToLoad($this->registry); /* Can we view this topic? */ $this->registry->getClass('topics')->setTopicData($topic); $topic = $this->registry->getClass('topics')->setUpTopic($this->registry->getClass('topics')->getTopicData()); $topic['_canReport'] = $reports->canReport('post'); /* Get posts */ $posts = $this->_getPosts($tid, $topPid, $this->registry->getClass('topics')->getTopicData('forum_id')); IPSDebug::fireBug('info', array('Found ' . count($posts) . ' posts...')); /* Got anything sailor? */ if (!count($posts)) { $this->returnHtml(''); } else { $html = ''; $lastpid = 0; $forumData = $this->postClass->getForumData(); $modAll = ($this->memberData['g_is_supmod'] or isset($this->memberData['forumsModeratorData'][$forumData['id']]) and ($this->memberData['forumsModeratorData'][$forumData['id']]['delete_post'] or $this->memberData['forumsModeratorData'][$forumData['id']]['split_move'])); foreach ($posts as $pid => $data) { /* Should we display the moderate checkbox for this post? */ $data['post']['moddable'] = FALSE; if ($modAll or isset($this->memberData['forumsModeratorData'][$forumData['id']]) and ($data['approved'] == 0 and $this->memberData['forumsModeratorData'][$forumData['id']]['post_q'] or $data['queued'] == 2 and $this->memberData['forumsModeratorData'][$forumData['id']]['bw_mod_un_soft_delete'] or $data['queued'] == 0 and $this->memberData['forumsModeratorData'][$forumData['id']]['bw_mod_soft_delete'])) { $data['post']['moddable'] = TRUE; } $html .= $this->registry->output->getTemplate('topic')->post($data, array(), $topic, $forumData); $lastpid = $pid; } if (count($posts) == 1) { $this->returnJsonArray(array('success' => 1, 'post' => $html, 'postid' => $lastpid), true); } else { $this->returnHtml($html); } } } catch (Exception $error) { $this->returnJsonError($error->getMessage()); } }
/** * Check out the tracker whacker * * @param integer $tid * @return @e void */ protected function addTopicToTracker($tid = 0) { if (!$tid) { return; } if ($this->getAuthor('member_id')) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); if ($this->hasSetting('enableTracker') && $this->getSettings('enableTracker')) { $_like->add($tid, $this->getAuthor('member_id'), array('like_notify_do' => 1, 'like_notify_meta' => $tid, 'like_notify_freq' => $this->getAuthor('auto_track') ? $this->getAuthor('auto_track') : 'immediate')); } else { $_like->remove($tid, $this->getAuthor('member_id')); } } }
/** * Delete a forum * * @return @e void Outputs to screen */ public function doDelete() { //----------------------------------------- // Auth check... //----------------------------------------- $this->registry->adminFunctions->checkSecurityKey(); //----------------------------------------- // Continue //----------------------------------------- $this->request['f'] = intval($this->request['f']); $this->request['new_parent_id'] = intval($this->request['new_parent_id']); $forum = $this->registry->class_forums->forum_by_id[$this->request['f']]; if (!$forum['id']) { $this->registry->output->showError($this->lang->words['for_noid_source'], 11313); } if (!$this->request['new_parent_id']) { $this->request['new_parent_id'] = -1; } else { if ($this->request['new_parent_id'] == $this->request['f']) { $this->registry->output->global_message = $this->lang->words['for_child_no_parent']; $this->deleteForm(); return; } } //----------------------------------------- // Would deleting this category orphan the only // remaining forums? //----------------------------------------- if ($forum['parent_id'] == -1) { $otherParent = 0; foreach ($this->registry->class_forums->forum_by_id as $id => $data) { if ($data['parent_id'] == -1) { $otherParent = $id; break; } } if (!$otherParent) { $this->registry->output->showError($this->lang->words['nodelete_last_cat'], 11364); } } //----------------------------------------- // Get library //----------------------------------------- $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . '/sources/classes/moderate.php', 'moderatorLibrary', 'forums'); $modfunc = new $classToLoad($this->registry); /* Load tagging stuff */ if (!$this->registry->isClassLoaded('tags')) { require_once IPS_ROOT_PATH . 'sources/classes/tags/bootstrap.php'; /*noLibHook*/ $this->registry->setClass('tags', classes_tags_bootstrap::run('forums', 'topics')); } //----------------------------------------- // Move stuff //----------------------------------------- if (isset($this->request['MOVE_ID'])) { $this->request['MOVE_ID'] = intval($this->request['MOVE_ID']); if (!$this->request['MOVE_ID']) { $this->registry->output->global_error = $this->lang->words['forum_delete_none_selected']; $this->deleteForm(); return; } if ($this->request['MOVE_ID'] == $this->request['f']) { $this->registry->output->global_error = $this->lang->words['for_wherewhatwhy']; $this->deleteForm(); return; } //----------------------------------------- // Move topics... //----------------------------------------- $this->DB->update('topics', array('forum_id' => $this->request['MOVE_ID']), 'forum_id=' . $this->request['f']); //----------------------------------------- // Move polls... //----------------------------------------- $this->DB->update('polls', array('forum_id' => $this->request['MOVE_ID']), 'forum_id=' . $this->request['f']); //----------------------------------------- // Move voters... //----------------------------------------- $this->DB->update('voters', array('forum_id' => $this->request['MOVE_ID']), 'forum_id=' . $this->request['f']); /* Move tags */ $this->registry->tags->moveTagsByParentId($this->request['f'], $this->request['MOVE_ID']); $modfunc->forumRecount($this->request['MOVE_ID']); } //----------------------------------------- // Delete the forum //----------------------------------------- $this->DB->delete('forums', "id=" . $this->request['f']); $this->DB->delete('permission_index', "app='forums' AND perm_type='forum' AND perm_type_id=" . $this->request['f']); //----------------------------------------- // Remove moderators from this forum //----------------------------------------- $this->DB->build(array('select' => '*', 'from' => 'moderators', 'where' => "forum_id LIKE '%,{$this->request['f']},%'")); $outer = $this->DB->execute(); while ($r = $this->DB->fetch($outer)) { $forums = explode(',', IPSText::cleanPermString($r['forum_id'])); $newForums = array(); foreach ($forums as $aForumId) { if ($aForumId != $this->request['f']) { $newForums[] = $aForumId; } } if (!count($newForums)) { $this->DB->delete('moderators', "mid=" . $r['mid']); } else { $this->DB->update('moderators', array('forum_id' => ',' . implode(',', $newForums) . ','), 'mid=' . $r['mid']); } } //----------------------------------------- // Delete forum subscriptions //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'forums'); $_like->remove($this->request['f']); //----------------------------------------- // Update children //----------------------------------------- $this->DB->update('forums', array('parent_id' => $this->request['new_parent_id']), "parent_id=" . $this->request['f']); //----------------------------------------- // Rebuild moderator cache //----------------------------------------- $classToLoad = IPSLib::loadActionOverloader(IPSLib::getAppDir('forums') . '/modules_admin/forums/moderator.php', 'admin_forums_forums_moderator'); $moderator = new $classToLoad(); $moderator->makeRegistryShortcuts($this->registry); $moderator->rebuildModeratorCache(); $this->registry->adminFunctions->saveAdminLog(sprintf($this->lang->words['for_removedlog'], $forum['name'])); $this->registry->output->global_message = $this->lang->words['for_removed']; $this->registry->output->silentRedirectWithMessage($this->settings['base_url'] . $this->form_code); }
/** * Approves an event * * @return @e void */ public function calendarEventApprove() { //----------------------------------------- // Init //----------------------------------------- $event_id = intval($this->request['event_id']); $md5check = trim($this->request['md5check']); if (!$this->memberData['g_is_supmod']) { $this->registry->output->showError('calendar_bad_approve', 1043, null, null, 403); } if ($md5check != $this->member->form_hash) { $this->registry->output->showError('calendar_bad_key', 2041, null, null, 403); } //----------------------------------------- // Get event //----------------------------------------- $event = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'cal_events', 'where' => "event_id=" . $event_id . " AND event_calendar_id=" . $this->calendar['cal_id'])); if (!$event['event_id']) { $this->registry->output->showError('calendar_event_not_found', 1045, null, null, 404); } //----------------------------------------- // Event approved? //----------------------------------------- $eventApproved = $event['event_approved'] ? 0 : 1; //----------------------------------------- // Update event //----------------------------------------- $this->DB->update('cal_events', array('event_approved' => $event['event_approved'] ? 0 : 1), 'event_id=' . $event_id); //----------------------------------------- // Hide likes //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('calendar', 'events'); $_like->toggleVisibility($event_id, $event['event_approved'] ? 0 : 1); //----------------------------------------- // Send notifications if approved //----------------------------------------- if ($eventApproved) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('calendar', $type == 'edit' ? 'events' : 'calendars'); $_url = $this->registry->output->buildSEOUrl('app=calendar&module=calendar&section=view&do=showevent&event_id=' . $event_id, 'public', $event['event_title_seo'], 'cal_event'); $_author = IPSMember::load($event['event_member_id']); $_like->sendNotifications($event['event_calendar_id'], array('immediate', 'offline'), array('notification_key' => 'new_event', 'notification_url' => $_url, 'email_template' => 'add_event_follow', 'email_subject' => sprintf($this->lang->words['add_event_follow_subject'], $_url, $event['event_title']), 'build_message_array' => array('NAME' => '-member:members_display_name-', 'AUTHOR' => $_author['members_display_name'], 'TITLE' => $event['event_title'], 'URL' => $_url))); } //----------------------------------------- // Recache //----------------------------------------- $this->cache->rebuildCache('calendar_events', 'calendar'); //----------------------------------------- // Redirect //----------------------------------------- $_dateData = explode(' ', $event['event_start_date']); $_dateBits = explode('-', $_dateData[0]); if ($this->request['modcp'] == 'unapprovedevents') { $this->registry->output->silentRedirect($this->settings['base_url'] . 'app=core&module=modcp&fromapp=calendar&tab=unapprovedevents'); } else { $this->registry->output->silentRedirect($this->settings['base_url'] . "app=calendar&module=calendar&section=view&cal_id={$this->calendar['cal_id']}&do=showday&y={$_dateBits[0]}&m={$_dateBits[1]}&d={$_dateBits[2]}&modfilter={$this->request['modfilter']}", $this->calendar['cal_title_seo'], true, 'cal_day'); } }
/** * Delete / undelete posts * * @param array Array of Post IDs * @param boolean Approve (TRUE) / Unapprove (FALSE) * @return boolean */ public function topicToggleSoftDelete($topicIds, $delete = FALSE, $reason = '') { //----------------------------------------- // INIT //----------------------------------------- $_restoreTopic = 1; if ($delete === TRUE) { $_restoreTopic = -1; } $_topics = array(); $_forumIDs = array(); $_tids = IPSLib::cleanIntArray($topicIds); //----------------------------------------- // Fetch distinct topic IDs //----------------------------------------- $this->DB->build(array('select' => '*', 'from' => 'topics', 'where' => 'tid IN (' . implode(',', $_tids) . ')')); $this->DB->execute(); while ($row = $this->DB->fetch()) { if (!$this->registry->getClass('topics')->isArchived($row)) { $_topics[$row['tid']] = $row; $_forumIDs[$row['forum_id']] = $row['forum_id']; } } //----------------------------------------- // Did we get the first post too? //----------------------------------------- foreach ($_topics as $tid => $topicData) { $this->DB->update('topics', array('approved' => $_restoreTopic), 'tid=' . $tid); if ($delete) { IPSDeleteLog::addEntry($tid, 'topic', $reason, $this->memberData); } /* Rebuild topic */ $this->rebuildTopic($tid); /* Mod log */ $this->addModerateLog($topicData['forum_id'], $tid, 0, $topicData['title'], sprintf($this->lang->words['acp_altered_topics'], "approved={$_restoreTopic}", $topicData['title'])); } /* Restoring */ if (!$delete) { /* Un-deleting, so delete */ IPSDeleteLog::removeEntries($_tids, 'post'); /* Delete from recent posts */ $this->registry->topics->restoreRecentPost(array('post_topic_id' => $_tids)); /* Run moderation sync */ $this->runModSync('topicUnhide', $_tids); } else { /* Delete from recent posts */ $this->registry->topics->deleteRecentPost(array('post_topic_id' => $_tids)); /* Run moderation sync */ $this->runModSync('topicHide', $_tids); } if (count($_forumIDs)) { foreach ($_forumIDs as $_fid) { $this->forumRecount($_fid); } } /* Tagging */ $this->registry->tags->updateVisibilityByMetaId($_tids, $delete ? 0 : 1); /* Likes */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); $_like->toggleVisibility($_tids, $delete ? 0 : 1); $this->cache->rebuildCache('stats', 'global'); return TRUE; }
/** * Sends "like" notifications * * @param array Array of GENERIC data (comment_xxxx) * @param string Comment Text * @return nowt lad */ public function sendNotifications(array $array, $comment) { list($_app, $_area) = explode('-', $this->whoAmI()); /* Send them if they are approved */ if ($array['comment_approved']) { $this->lang->loadLanguageFile(array('public_comments'), 'core'); /* Fetch meta data */ $parent = $this->remapFromLocal($this->fetchParent($array['comment_parent_id']), 'parent'); $_url = $this->fetchSetting('urls-showParent', $parent); $url = $this->registry->output->buildSEOUrl(sprintf($_url, $parent['parent_id']), 'public', $parent['parent_seo_title'], $this->seoTemplate()); $commentUrl = $this->registry->output->buildSEOUrl('app=core&module=global&section=comments&do=findComment&fromApp=' . $_app . '-' . $_area . '&parentId=' . $parent['parent_id'] . '&commentId=' . $array['comment_id'], 'public', true, 'findcomment'); /* Fetch like class */ try { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap($_app, $_area); $_like->sendNotifications($parent['parent_id'], array('immediate', 'offline'), array('notification_key' => 'new_comment', 'notification_url' => $url, 'email_template' => 'comment_notifications', 'email_subject' => sprintf($this->lang->words['comment_notice_subject'], $url, $parent['parent_title']), 'build_message_array' => array('NAME' => '-member:members_display_name-', 'AUTHOR' => $this->memberData['members_display_name'], 'TITLE' => $parent['parent_title'], 'URL' => $url, 'COMMENTURL' => $commentUrl, 'COMMENT' => $comment))); } catch (Exception $e) { /* No like class for this comment class */ } } }
/** * Perform the viewNewContent search * Forum Version * Populates $this->_count and $this->_results * * @return array */ public function viewNewContent() { $oldStamp = $this->registry->getClass('classItemMarking')->fetchOldestUnreadTimestamp(array(), 'forums'); $check = IPS_UNIX_TIME_NOW - 86400 * $this->settings['topic_marking_keep_days']; $forumIdsOk = array(); $start = IPSSearchRegistry::get('in.start'); $perPage = IPSSearchRegistry::get('opt.search_per_page'); $seconds = IPSSearchRegistry::get('in.period_in_seconds'); $followedOnly = $this->memberData['member_id'] ? IPSSearchRegistry::get('in.vncFollowFilterOn') : false; $permissions = array(); /* Loop through the forums and build a list of forums we're allowed access to */ $bvnp = explode(',', $this->settings['vnp_block_forums']); IPSSearchRegistry::set('in.search_sort_by', 'date'); IPSSearchRegistry::set('in.search_sort_order', 'desc'); IPSSearchRegistry::set('opt.noPostPreview', true); IPSSearchRegistry::set('opt.searchType', 'titles'); $followedForums = array(); $followedTopics = array(); //----------------------------------------- // Only content we have participated in? //----------------------------------------- if (IPSSearchRegistry::get('in.userMode')) { IPSSearchRegistry::set('in.start', 0); IPSSearchRegistry::set('opt.search_per_page', 1000); $_tempResults = $this->viewUserContent($this->memberData); IPSSearchRegistry::set('in.start', $start); IPSSearchRegistry::set('opt.search_per_page', $perPage); if ($_tempResults['count']) { $this->sphinxClient->SetFilter('tid', $_tempResults['resultSet']); } else { return array('count' => 0, 'resultSet' => array()); } switch (IPSSearchRegistry::get('in.userMode')) { default: case 'all': case 'content': IPSSearchRegistry::set('opt.searchType', 'both'); IPSSearchRegistry::set('opt.noPostPreview', true); break; case 'title': IPSSearchRegistry::set('opt.searchType', 'titles'); IPSSearchRegistry::set('opt.noPostPreview', false); break; } } /* Set return type */ IPSSearchRegistry::set('set.returnType', 'tids'); /* Get list of good forum IDs */ $_forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds($this->memberData['member_id'], $followedOnly ? array() : $bvnp); /* Fetch forum rel ids */ if ($followedOnly) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ /* @link http://community.invisionpower.com/tracker/issue-33284-view-new-content-just-items-i-follow */ //$like = classes_like::bootstrap( 'forums', 'forums' ); //$followedForums = $like->getDataByMemberIdAndArea( $this->memberData['member_id'] ); $followedForums = array(); //( $followedForums === null ) ? array() : array_keys( $followedForums ); $like = classes_like::bootstrap('forums', 'topics'); $followedTopics = $like->getDataByMemberIdAndArea($this->memberData['member_id']); $followedTopics = $followedTopics === null ? array() : array_keys($followedTopics); } /* What type of date restriction? */ if (IPSSearchRegistry::get('in.period_in_seconds') !== false) { $oldStamp = time() - $seconds; $forumIdsOk = $_forumIdsOk; } else { foreach ($_forumIdsOk as $id) { if ($followedOnly && !in_array($id, $followedForums)) { // We don't want to skip followed topics just because we don't follow the forum //continue; } $lMarked = $this->registry->getClass('classItemMarking')->fetchTimeLastMarked(array('forumID' => $id), 'forums'); $fData = $this->registry->getClass('class_forums')->forumsFetchData($id); if ($fData['last_post'] > $lMarked) { $forumIdsOk[$id] = $id; } } if (intval($this->memberData['_cache']['gb_mark__forums']) > 0) { $oldStamp = $this->memberData['_cache']['gb_mark__forums']; } /* Finalize times */ if (!$oldStamp or $oldStamp == IPS_UNIX_TIME_NOW) { $oldStamp = intval($this->memberData['last_visit']); } /* Older than 3 months.. then limit */ if ($oldStamp < $check) { $oldStamp = $check; } /* If no forums, we're done */ if (!count($forumIdsOk)) { /* Return it */ return array('count' => 0, 'resultSet' => array()); } } /* Only show VNC results from specified forums? */ if (is_array(IPSSearchRegistry::get('forums.vncForumFilters')) and count(IPSSearchRegistry::get('forums.vncForumFilters'))) { $_newIdsOk = array(); foreach (IPSSearchRegistry::get('forums.vncForumFilters') as $forumId) { if (in_array($forumId, $forumIdsOk)) { $_newIdsOk[] = $forumId; } } $forumIdsOk = $_newIdsOk; } /* Set the timestamps */ $this->sphinxClient->SetFilterRange('last_post', $oldStamp, time()); $this->setDateRange(0, 0); /* Force it into filter so that search can pick it up */ $this->searchForumIds = $forumIdsOk; /* Set up some vars */ IPSSearchRegistry::set('set.resultCutToDate', $oldStamp); /* Fetch first 300 results */ IPSSearchRegistry::set('opt.search_per_page', 300); IPSSearchRegistry::set('in.start', 0); /* Run search */ $data = $this->search(); /* Reset for display function */ IPSSearchRegistry::set('in.start', $start); IPSSearchRegistry::set('opt.search_per_page', $perPage); $_ffWhere = ''; /* Followed topics only */ if ($followedOnly) { if (!count($followedTopics) && !count($followedForums)) { return array('count' => 0, 'resultSet' => array()); } if (count($followedForums)) { /* @link http://community.invisionpower.com/tracker/issue-33284-view-new-content-just-items-i-follow */ //$_ffWhere = ' OR forum_id IN (' . implode( ',', $followedForums ) . ') '; } } /* This method allows us to have just one "tid IN()" clause, instead of two, depending on scenario */ if (count($followedTopics)) { $where[] = "( tid IN(" . implode(',', $followedTopics) . ')' . $_ffWhere . ' )'; } else { if (!count($data['resultSet'])) { return array('count' => 0, 'resultSet' => array()); } if (IPSSearchRegistry::get('set.returnType') == 'pids') { $this->DB->build(array('select' => 'topic_id', 'from' => 'posts', 'where' => 'pid IN(' . implode(',', $data['resultSet']) . ')')); $this->DB->execute(); $_tmpTids = array(); while ($row = $this->DB->fetch()) { $_tmpTids[] = $row['topic_id']; } if (count($_tmpTids)) { $where[] = "( tid IN(" . implode(',', $_tmpTids) . ')' . $_ffWhere . ' )'; } } else { $where[] = "( tid IN(" . implode(',', $data['resultSet']) . ')' . $_ffWhere . ' )'; } } $permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics(0); $permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts(0); if ($permissions['TopicSoftDeleteSee'] and $permissions['canQueue']) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden', 'sdeleted')); } else { if ($permissions['TopicSoftDeleteSee']) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'sdeleted')); } else { if ($permissions['canQueue']) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden')); } else { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible')); } } } $where = implode(" AND ", $where); /* Fetch the count */ $count = $this->DB->buildAndFetch(array('select' => 'count(*) as count', 'from' => 'topics', 'where' => $where)); /* Fetch the count */ if ($count['count']) { $limit = IPSSearchRegistry::get('in.period') != 'unread' ? array($start, $perPage) : array(0, 1200); $this->DB->build(array('select' => 'tid, forum_id, last_post', 'from' => 'topics', 'where' => $where, 'order' => 'last_post DESC', 'limit' => $limit)); $inner = $this->DB->execute(); while ($row = $this->DB->fetch($inner)) { $rtids[$row['tid']] = $row; } } /* Set up some vars */ IPSSearchRegistry::set('set.resultCutToDate', $oldStamp); if (IPSSearchRegistry::get('in.period') == 'unread') { $filter = $this->registry->class_forums->postProcessVncTids($rtids, array($start, $perPage)); $data['count'] = $filter['count']; $data['resultSet'] = $filter['tids']; } else { $data = array('count' => $count['count'], 'resultSet' => is_array($rtids) ? array_keys($rtids) : array()); } /* ensure we check TIDS */ IPSSearchRegistry::set('set.returnType', 'tids'); /* Return it */ return $data; }
/** * Setup for the forum controller * * @return @e void */ public function initForums() { $this->registry->getClass('class_localization')->loadLanguageFile(array('public_forums', 'public_boards')); //----------------------------------------- // Multi TIDS? // If st is not defined then kill cookie // st will always be defined across pages //----------------------------------------- if (!array_key_exists('page', $this->request) and !array_key_exists('prune_day', $this->request)) { IPSCookie::set('modtids', ',', 0); $this->request['selectedtids'] = ''; } else { $this->request['selectedtids'] = IPSCookie::get('modtids'); } //----------------------------------------- // Get the forum info based on the forum ID, // and get the category name, ID, etc. //----------------------------------------- $this->forum = $this->registry->getClass('class_forums')->getForumById($this->request['f']); /* Followed stuffs */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $this->_like = classes_like::bootstrap('forums', 'forums'); /* Load tagging stuff */ if (!$this->registry->isClassLoaded('tags')) { require_once IPS_ROOT_PATH . 'sources/classes/tags/bootstrap.php'; /*noLibHook*/ $this->registry->setClass('tags', classes_tags_bootstrap::run('forums', 'topics')); } /* Init */ if (!$this->registry->isClassLoaded('topics')) { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . "/sources/classes/topics.php", 'app_forums_classes_topics', 'forums'); $this->registry->setClass('topics', new $classToLoad($this->registry)); } }
/** * Fetch all meta data from various like rows * * @param array $likes Like rows * @return @e array */ public static function get(array $likes) { $apps = array(); $process = array(); $lookUp = array(); foreach ($likes as $id => $like) { if (empty($like['like_app']) or empty($like['like_area']) or empty($like['like_rel_id'])) { continue; } $apps[$like['like_app'] . '-' . $like['like_area']][$id] = $like; $lookUp[$like['like_app'] . '-' . $like['like_area'] . '-' . $like['like_rel_id']] = $like['like_id']; } /* Process based on apps */ foreach ($apps as $app => $data) { list($_app, $_area) = explode('-', $app); $_bootstrap = classes_like::bootstrap($_app, $_area); $relIds = array(); foreach ($data as $_k => $_v) { $relIds[] = $_v['like_rel_id']; } /* Bulk fetch */ $process[$app] = $_bootstrap->getMeta($relIds); } /* Fold up array */ foreach ($process as $app => $data) { list($_app, $_area) = explode('-', $app); foreach ($data as $relId => $_like) { if ($relId) { $like_id = $lookUp[$_app . '-' . $_area . '-' . $relId]; if ($like_id and is_array($_like) and is_array($likes[$like_id])) { $likes[$like_id] = array_merge($likes[$like_id], $_like); } } } } return $likes; }
/** * View content you are following * * @author Brandon Farber * @param string $error Error message * @return @e void */ public function viewFollowedContent($error = '') { IPSSearchRegistry::set('in.search_app', $this->request['search_app']); IPSSearchRegistry::set('opt.searchType', 'titles'); IPSSearchRegistry::set('opt.noPostPreview', true); $results = array(); $formatted = array(); $count = 0; //----------------------------------------- // Determine content type //----------------------------------------- $contentTypes = IPSSearchRegistry::get('config.followContentTypes'); //----------------------------------------- // Verify likes are available //----------------------------------------- if (count(IPSLib::getEnabledApplications('like')) and count($contentTypes) and IPSLib::appIsInstalled(IPSSearchRegistry::get('in.search_app'), true)) { //----------------------------------------- // What content type? //----------------------------------------- $_type = ''; if ($this->request['contentType'] and in_array($this->request['contentType'], $contentTypes)) { $_type = $this->request['contentType']; } else { $_type = $contentTypes[0]; } $this->request['contentType'] = $_type; IPSSearchRegistry::set('in.followContentType', $this->request['contentType']); /* Fetch like class */ try { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $this->_like = classes_like::bootstrap(IPSSearchRegistry::get('in.search_app'), $_type); } catch (Exception $e) { /* Fail safe... */ $this->registry->output->addNavigation($this->lang->words['followed_ct_title'], ''); $this->title = $this->lang->words['followed_ct_title']; $this->output .= $this->registry->output->getTemplate('search')->followedContentView(array(), '', 0, $error, $contentTypes); } /* Do we have some custom join and sort data? */ if (method_exists($this->_like, 'getSearchJoinAndSortBy')) { $custom = $this->_like->getSearchJoinAndSortBy(); $countQ = array('select' => 'COUNT(*) as er', 'from' => array('core_like' => 'l'), 'where' => 'like_member_id=' . $this->memberData['member_id'] . " AND like_visible=1 AND like_app='" . IPSSearchRegistry::get('in.search_app') . "' AND like_area='" . $_type . "'"); if ($custom['from']) { $countQ['add_join'][] = array('from' => $custom['from'], 'where' => $custom['where']); } if ($custom['order']) { $countQ['order'] = $custom['order'] . ' DESC'; } if ($custom['extraWhere']) { $countQ['where'] .= ' AND ' . $custom['extraWhere']; } $count = $this->DB->buildAndFetch($countQ); $count = $count['er']; $q = array('select' => 'l.*', 'from' => array('core_like' => 'l'), 'where' => 'l.like_member_id=' . $this->memberData['member_id'] . " AND l.like_visible=1 AND l.like_app='" . IPSSearchRegistry::get('in.search_app') . "' AND l.like_area='" . $_type . "'", 'limit' => array(IPSSearchRegistry::get('in.start'), IPSSearchRegistry::get('opt.search_per_page')), 'order' => 'like_added DESC'); if ($custom['from']) { $q['add_join'][] = array('from' => $custom['from'], 'where' => $custom['where']); } if ($custom['order']) { $q['order'] = $custom['order'] . ' DESC'; } if ($custom['extraWhere']) { $q['where'] .= ' AND ' . $custom['extraWhere']; } $this->DB->build($q); } else { $count = $this->DB->buildAndFetch(array('select' => 'COUNT(*) as er', 'from' => 'core_like', 'where' => 'like_member_id=' . $this->memberData['member_id'] . " AND like_visible=1 AND like_app='" . IPSSearchRegistry::get('in.search_app') . "' AND like_area='" . $_type . "'")); $count = $count['er']; $this->DB->build(array('select' => '*', 'from' => 'core_like', 'where' => 'like_member_id=' . $this->memberData['member_id'] . " AND like_visible=1 AND like_app='" . IPSSearchRegistry::get('in.search_app') . "' AND like_area='" . $_type . "'", 'limit' => array(IPSSearchRegistry::get('in.start'), IPSSearchRegistry::get('opt.search_per_page')), 'order' => 'like_added DESC')); } $outer = $this->DB->execute(); while ($r = $this->DB->fetch($outer)) { $results[] = $r['like_rel_id']; $formatted[$r['like_id']] = $r; } /* Process */ $results = $this->searchController->fetchFollowedContentOutput($results, $formatted); $pages = $this->registry->getClass('output')->generatePagination(array('totalItems' => $count, 'itemsPerPage' => IPSSearchRegistry::get('opt.search_per_page'), 'currentStartValue' => IPSSearchRegistry::get('in.start'), 'baseUrl' => "app=core&module=search&do=followed&search_app=" . IPSSearchRegistry::get('in.search_app') . '&sid=' . $this->request['_sid'] . "&contentType=" . $this->request['contentType'])); } else { $count = 0; $results = array(); } /* Output */ $this->registry->output->addNavigation($this->lang->words['followed_ct_title'], ''); $this->title = $this->lang->words['followed_ct_title']; $this->output .= $this->registry->output->getTemplate('search')->followedContentView($results, $pages, $count, $error, $contentTypes); }
/** * Merge two or more topics * * @return @e void [Outputs to screen] */ protected function _multiTopicMerge() { $this->_genericPermissionCheck('split_merge'); if (count($this->tids) < 2) { $this->_showError('mod_topics_merge_two', 103107); } //----------------------------------------- // Get the topics in ascending date order //----------------------------------------- $topics = array(); $tids = array(); $merge_ids = array(); $newViews = 0; $this->DB->build(array('select' => 'tid, forum_id, approved, views', 'from' => 'topics', 'where' => 'tid IN (' . implode(",", $this->tids) . ')', 'order' => 'start_date asc')); $this->DB->execute(); while ($r = $this->DB->fetch()) { $topics[] = $r; $tids[] = $r['tid']; $newViews += $r['views']; } //----------------------------------------- // Check... //----------------------------------------- if (count($topics) < 2) { $this->_showError('mod_topics_merge_two', 103108); } //----------------------------------------- // Make sure we can moderate EACH topic //----------------------------------------- foreach ($topics as $topic) { $this->_resetModerator($topic['forum_id']); $this->_genericPermissionCheck('split_merge'); } //----------------------------------------- // Get topic ID for first topic 'master' //----------------------------------------- $first_topic = array_shift($topics); $main_topic_id = $first_topic['tid']; $unapproved = array(); foreach ($topics as $t) { /* Add to unapproved array */ if (!$t['approved']) { $unapproved[] = $t['tid']; } $merge_ids[] = $t['tid']; } //----------------------------------------- // Sort out polls //----------------------------------------- $polls = array(); /* Who has a poll? */ $this->DB->build(array('select' => '*', 'from' => 'polls', 'where' => "tid={$main_topic_id} OR tid IN(" . implode(',', $merge_ids) . ")")); $this->DB->execute(); while ($row = $this->DB->fetch()) { $polls[$row['tid']] = $row; } /* We have one poll */ if (count($polls) == 1) { /* Update the poll ONLY if it's not our main one */ if (empty($polls[$main_topic_id])) { $this->DB->update('polls', array('tid' => $main_topic_id), "tid IN(" . implode(',', $merge_ids) . ")"); $this->DB->update('voters', array('tid' => $main_topic_id), "tid IN(" . implode(',', $merge_ids) . ")"); $this->DB->update('topics', array('poll_state' => 1), "tid={$main_topic_id}"); } } elseif (count($polls) > 1) { // Have we selected one? $chosenTid = intval($this->request['chosenpolltid']); if ($chosenTid) { /* Chosen one is not from the main topic? */ if ($chosenTid != $main_topic_id) { $this->DB->delete('polls', "tid={$main_topic_id}"); $this->DB->delete('voters', "tid={$main_topic_id}"); // Update poll status here if the chosen poll is not from the main topic otherwise there's no need to.. right? ;P $this->DB->update('topics', array('poll_state' => 1), "tid={$main_topic_id}"); } // Remove the non chosen ones $this->DB->delete('polls', "tid IN(" . implode(',', $merge_ids) . ")" . " AND tid <> {$chosenTid}"); $this->DB->delete('voters', "tid IN(" . implode(',', $merge_ids) . ")" . " AND tid <> {$chosenTid}"); // Update the master topic $this->DB->update('polls', array('tid' => $main_topic_id), "tid={$chosenTid}"); $this->DB->update('voters', array('tid' => $main_topic_id), "tid={$chosenTid}"); } else { ipsRegistry::getClass('class_localization')->loadLanguageFile(array('public_topic')); $this->output .= $this->registry->getClass('output')->getTemplate('mod')->mergeMultiplePolls($polls, $this->request['selectedtids']); return false; } } //----------------------------------------- // Update the posts, subs and topic //----------------------------------------- /* Bug #20829: If the topic is not approved, set all the posts unapproved so that they are not displayed after the merge */ if (is_array($unapproved) && count($unapproved)) { $this->DB->update('posts', array('queued' => 1), 'topic_id IN (' . implode(",", $unapproved) . ")"); } $this->DB->update('posts', array('topic_id' => $main_topic_id, 'new_topic' => 0), 'topic_id IN (' . implode(",", $merge_ids) . ")"); $this->DB->update('topics', array('views' => $newViews), 'tid=' . $main_topic_id); /* @Link http://community.invisionpower.com/resources/bugs.html/_/ip-board/merging-topics-does-not-update-attach-parent-id-for-attachments-r41886 */ $this->DB->update('attachments', array('attach_parent_id' => $main_topic_id), 'attach_parent_id IN(' . implode(",", $merge_ids) . ") AND attach_rel_module='post'"); $this->DB->delete('voters', "tid IN (" . implode(",", $merge_ids) . ")"); $this->DB->delete('topics', "tid IN (" . implode(",", $merge_ids) . ")"); /* Bug #38221: Set the new first post in topic */ $first_post = $this->DB->buildAndFetch(array('select' => 'pid', 'from' => 'posts', 'where' => "topic_id={$main_topic_id}", 'order' => "pid ASC", 'limit' => array(0, 1))); $this->DB->update('posts', array('new_topic' => 1), 'pid = ' . $first_post['pid']); //----------------------------------------- // Update followers //----------------------------------------- require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'topics'); foreach ($merge_ids as $mid) { $_like->merge($mid, $main_topic_id); } //----------------------------------------- // Remove from delete log //----------------------------------------- IPSDeleteLog::removeEntries($merge_ids, 'topic', TRUE); //----------------------------------------- // Update the newly merged topic //----------------------------------------- $this->modLibrary->rebuildTopic($main_topic_id); $this->registry->class_forums->allForums[$this->forum['id']]['_update_deletion'] = 1; $this->modLibrary->forumRecount($this->forum['id']); $this->cache->rebuildCache('stats', 'global'); /* Tags */ $this->registry->tags->moveTagsByMetaId($tids, $main_topic_id); /* Run Sync */ foreach ($merge_ids as $mid) { $this->modLibrary->runModSync('topicMerge', $mid, $main_topic_id); } /* Log */ $this->_addModeratorLog(sprintf($this->lang->words['multi_topic_merge_mod_log'], count($topics))); }
/** * Perform the viewNewContent search * Forum Version * Populates $this->_count and $this->_results * * @return nothin' */ public function viewNewContent() { $rtids = array(); $oldStamp = $this->registry->getClass('classItemMarking')->fetchOldestUnreadTimestamp(array(), 'forums'); $check = IPS_UNIX_TIME_NOW - 86400 * $this->settings['topic_marking_keep_days']; $forumIdsOk = array(); $where = array(); $_tidsOnly = array(); $noLimit = FALSE; /* Loop through the forums and build a list of forums we're allowed access to */ $bvnp = explode(',', $this->settings['vnp_block_forums']); $start = IPSSearchRegistry::get('in.start'); $perPage = IPSSearchRegistry::get('opt.search_per_page'); $seconds = IPSSearchRegistry::get('in.period_in_seconds'); $followedOnly = $this->memberData['member_id'] ? IPSSearchRegistry::get('in.vncFollowFilterOn') : false; $followedForums = array(); $followedTopics = array(); IPSSearchRegistry::set('in.search_sort_by', 'date'); IPSSearchRegistry::set('in.search_sort_order', 'desc'); IPSSearchRegistry::set('opt.searchType', 'titles'); IPSSearchRegistry::set('opt.noPostPreview', true); //----------------------------------------- // Only content we have participated in? //----------------------------------------- if (IPSSearchRegistry::get('in.userMode')) { $_tempResults = $this->viewUserContent($this->memberData); if ($_tempResults['count']) { $_tidsOnly = array_merge($_tidsOnly, $_tempResults['resultSet']); } else { return array('count' => 0, 'resultSet' => array()); } switch (IPSSearchRegistry::get('in.userMode')) { default: case 'all': case 'content': IPSSearchRegistry::set('opt.searchType', 'both'); IPSSearchRegistry::set('opt.noPostPreview', true); break; case 'title': IPSSearchRegistry::set('opt.searchType', 'titles'); IPSSearchRegistry::set('opt.noPostPreview', false); break; } } /* Set return type */ IPSSearchRegistry::set('set.returnType', 'tids'); /* Get list of good forum IDs */ $_forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds($this->memberData['member_id'], $followedOnly ? array() : $bvnp); /* Fetch forum rel ids */ if ($followedOnly) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ /* @link http://community.invisionpower.com/tracker/issue-33284-view-new-content-just-items-i-follow */ //$like = classes_like::bootstrap( 'forums', 'forums' ); //$followedForums = $like->getDataByMemberIdAndArea( $this->memberData['member_id'] ); $followedForums = array(); //( $followedForums === null ) ? array() : array_keys( $followedForums ); $like = classes_like::bootstrap('forums', 'topics'); $followedTopics = $like->getDataByMemberIdAndArea($this->memberData['member_id'], 5000); $followedTopics = $followedTopics === null ? array() : array_keys($followedTopics); } /* Period filtering */ if (IPSSearchRegistry::get('in.period_in_seconds') !== false) { $where[] = "last_post > " . (IPS_UNIX_TIME_NOW - $seconds); $forumIdsOk = $_forumIdsOk; } else { if (intval($this->memberData['_cache']['gb_mark__forums']) > 0) { $oldStamp = $this->memberData['_cache']['gb_mark__forums']; } /* Finalize times */ if (!$oldStamp or $oldStamp == IPS_UNIX_TIME_NOW) { $oldStamp = intval($this->memberData['last_visit']); } /* Older than 3 months.. then limit */ if ($oldStamp < $check) { $oldStamp = $check; } foreach ($_forumIdsOk as $id) { /*if ( $followedOnly && ! in_array( $id, $followedForums ) ) { // We don't want to skip followed topics just because we don't follow the forum continue; }*/ $lMarked = $this->registry->getClass('classItemMarking')->fetchTimeLastMarked(array('forumID' => $id), 'forums'); $fData = $this->registry->getClass('class_forums')->forumsFetchData($id); if ($fData['last_post'] > $lMarked) { $forumIdsOk[$id] = $id; } } /* If no forums, we're done */ if (!count($forumIdsOk)) { /* Return it */ return array('count' => 0, 'resultSet' => array()); } /* Based on oldest timestamp */ $where[] = "last_post > " . $oldStamp; } $forumIdsOk = count($forumIdsOk) ? $forumIdsOk : array(0 => 0); /* Only show VNC results from specified forums? */ if (is_array(IPSSearchRegistry::get('forums.vncForumFilters')) and count(IPSSearchRegistry::get('forums.vncForumFilters'))) { $_newIdsOk = array(); foreach (IPSSearchRegistry::get('forums.vncForumFilters') as $forumId) { if (in_array($forumId, $forumIdsOk)) { $_newIdsOk[] = $forumId; } } $forumIdsOk = $_newIdsOk; } //----------------------------------------- // No forums? //----------------------------------------- if (!count($forumIdsOk)) { return array('count' => 0, 'resultSet' => array()); } $where[] = "forum_id IN (" . implode(",", $forumIdsOk) . ")"; /* Add in last bits */ $where[] = "state != 'link'"; /* Set up perms */ $permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics(0); $permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts(0); if ($permissions['TopicSoftDeleteSee'] and $permissions['canQueue']) { $permWhere = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden', 'sdeleted')); } else { if ($permissions['TopicSoftDeleteSee']) { $permWhere = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'sdeleted')); } else { if ($permissions['canQueue']) { $permWhere = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden')); } else { $permWhere = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible')); } } } $where[] = $this->registry->class_forums->fetchTopicArchiveQuery(array('not', 'exclude')); /* add perm */ $where[] = $permWhere; $_ffWhere = ''; /* Followed topics only? */ if ($followedOnly) { if (!count($followedTopics) && !count($followedForums)) { return array('count' => 0, 'resultSet' => array()); } $_tidsOnly = array_merge($_tidsOnly, $followedTopics); if (count($followedForums)) { $_ffWhere = ' OR forum_id IN (' . implode(',', $followedForums) . ') '; } } /* This method allows us to have just one "tid IN()" clause, instead of two, depending on scenario */ if (count($_tidsOnly) and count($followedTopics)) { /* Only look for tids in both arrays */ $_both = array_intersect($_tidsOnly, $followedTopics); if (count($_both)) { $where[] = "( tid IN(" . implode(',', $_both) . ')' . $_ffWhere . ' )'; } } else { if (count($_tidsOnly)) { $where[] = "( tid IN(" . implode(',', $_tidsOnly) . ')' . $_ffWhere . ' )'; $noLimit = TRUE; // If we're here, we've already limited in $this->viewUserContent() } else { if (count($followedTopics)) { $where[] = "( tid IN(" . implode(',', $followedTopics) . ')' . $_ffWhere . ' )'; } } } $where = implode(" AND ", $where); /* Fetch the count */ $count = $this->DB->buildAndFetch(array('select' => 'count(*) as count', 'from' => 'topics', 'where' => $where)); /* Fetch the count */ if ($count['count']) { $limit = $noLimit ? NULL : IPSSearchRegistry::get('in.period') != 'unread' ? array($start, $perPage) : array(0, 1200); $this->DB->build(array('select' => 'tid, forum_id, last_post', 'from' => 'topics', 'where' => $where, 'order' => 'last_post DESC', 'limit' => $limit)); $inner = $this->DB->execute(); while ($row = $this->DB->fetch($inner)) { $rtids[$row['tid']] = $row; } } /* Set up some vars */ IPSSearchRegistry::set('set.resultCutToDate', $oldStamp); if (IPSSearchRegistry::get('in.period') == 'unread') { $filter = $this->registry->class_forums->postProcessVncTids($rtids, array($start, $perPage)); $data['count'] = $filter['count']; $data['resultSet'] = $filter['tids']; } else { $data = array('count' => (isset($_tempResults['count']) and $_tempResults['count'] > $count['count']) ? $_tempResults['count'] : $count['count'], 'resultSet' => array_keys($rtids)); // For explaination of why we check $_tempResults, see bug report 38178 } /* Return it */ return $data; }
/** * Recache the user's watched forums * * @param int Member ID * @return boolean * @author Matt */ public function recacheWatchedForums($memberID) { /* INIT */ $final = array(); $memberID = intval($memberID); /* Get forums the member follows */ require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('forums', 'forums'); $forums = $_like->getDataByMemberIdAndArea($memberID); $forums = is_array($forums) ? array_keys($forums) : array(); foreach ($forums as $forum) { if ($this->registry->permissions->check('view', $this->forum_by_id[$forum]) === TRUE) { $final[] = $forum; } } IPSMember::packMemberCache($memberID, array('watchedForums' => $final)); return TRUE; }
/** * Saves the add/edit calendar event form * * @param string $type Either add or edit * @return @e void */ public function calendarEventSave($type = 'add') { //----------------------------------------- // Check permissions //----------------------------------------- if ($this->request['auth_key'] != $this->member->form_hash) { $this->registry->output->showError('no_permission', 10410, null, null, 403); } if ($this->request['preview']) { return $this->calendarEventForm($type); } //----------------------------------------- // Init //----------------------------------------- $event_id = intval($this->request['event_id']); $calendar_id = intval($this->request['event_calendar_id']); $_calendar = $this->functions->getCalendar($calendar_id); $event_title = IPSText::getTextClass('bbcode')->stripBadWords(trim($this->request['event_title'])); $start_date = ''; $end_date = ''; $recurring = 0; //----------------------------------------- // Verify start date/time //----------------------------------------- switch ($this->settings['cal_date_format']) { case 'american': default: $_startBits = explode('/', $this->request['start_date']); if ($this->request['set_enddate']) { $_endBits = $this->request['end_date'] ? explode('/', $this->request['end_date']) : array(); } break; case 'danish': $_inputStart = explode('/', $this->request['start_date']); $_startBits = array(0 => $_inputStart[1], 1 => $_inputStart[2], 2 => $_inputStart[0]); if ($this->request['set_enddate']) { $_inputEnd = $this->request['end_date'] ? explode('/', $this->request['end_date']) : array(); $_endBits = array(0 => $_inputEnd[1], 1 => $_inputEnd[2], 2 => $_inputEnd[0]); } break; case 'italian': $_inputStart = explode('/', $this->request['start_date']); $_startBits = array(0 => $_inputStart[1], 1 => $_inputStart[0], 2 => $_inputStart[2]); if ($this->request['set_enddate']) { $_inputEnd = $this->request['end_date'] ? explode('/', $this->request['end_date']) : array(); $_endBits = array(0 => $_inputEnd[1], 1 => $_inputEnd[0], 2 => $_inputEnd[2]); } break; case 'db': $_inputStart = explode('-', $this->request['start_date']); $_startBits = array(0 => $_inputStart[1], 1 => $_inputStart[2], 2 => $_inputStart[0]); if ($this->request['set_enddate']) { $_inputEnd = $this->request['end_date'] ? explode('-', $this->request['end_date']) : array(); $_endBits = array(0 => $_inputEnd[1], 1 => $_inputEnd[2], 2 => $_inputEnd[0]); } break; } if (!$this->request['start_date'] or count($_startBits) != 3) { $this->registry->output->showError('calendar_invalid_date', 10427.0); } else { if (!@checkdate($_startBits[0], $_startBits[1], $_startBits[2])) { $this->registry->output->showError('calendar_invalid_date', 10427.1); } } if ($this->request['all_day']) { $start_date = gmmktime(0, 0, 0, $_startBits[0], $_startBits[1], $_startBits[2]); } else { $_time = explode(':', $this->request['start_time']); if ($this->settings['cal_time_format'] == 'standard') { if (count($_time) != 2 or $_time[0] > 12 or $_time[1] > 59) { $this->registry->output->showError('calendar_invalid_time', 10427.2); } if ($this->request['start_time_ampm'] == 'PM' and $_time[0] < 12) { $_time[0] += 12; } else { if ($this->request['start_time_ampm'] == 'AM' and $_time[0] == 12) { $_time[0] = 0; } } } else { if (count($_time) != 2 or $_time[0] > 23 or $_time[1] > 59) { $this->registry->output->showError('calendar_invalid_time', 10427.2); } } $start_date = gmmktime($_time[0], $_time[1], 0, $_startBits[0], $_startBits[1], $_startBits[2]); } //----------------------------------------- // Verify end date/time //----------------------------------------- if ($this->request['set_enddate']) { if (count($_endBits) != 3) { $this->registry->output->showError('calendar_invalid_date', 10427.3); } else { if (!@checkdate($_endBits[0], $_endBits[1], $_endBits[2])) { $this->registry->output->showError('calendar_invalid_date', 10427.4); } } if ($this->request['all_day']) { $end_date = gmmktime(0, 0, 0, $_endBits[0], $_endBits[1], $_endBits[2]); } else { $_time = explode(':', $this->request['end_time']); if ($this->settings['cal_time_format'] == 'standard') { if (count($_time) != 2 or $_time[0] > 12 or $_time[1] > 59) { $this->registry->output->showError('calendar_invalid_date', 10427.5); } if ($this->request['end_time_ampm'] == 'PM') { $_time[0] += 12; } } else { if (count($_time) != 2 or $_time[0] > 23 or $_time[1] > 59) { $this->registry->output->showError('calendar_invalid_date', 10427.5); } } $end_date = gmmktime($_time[0], $_time[1], 0, $_endBits[0], $_endBits[1], $_endBits[2]); } } if ($end_date and $end_date < $start_date) { $this->registry->output->showError('calendar_range_wrong', 10421); } else { if ($this->request['end_date'] and $this->request['set_enddate'] and !$end_date) { $this->registry->output->showError('calendar_range_wrong', 10421.1); } } //----------------------------------------- // Set recurring flag //----------------------------------------- if ($this->request['set_recurfields']) { if (!$end_date) { $this->registry->output->showError('recurring_requires_enddate', 10427.6); } $recurring = intval($this->request['recur_unit']); } //----------------------------------------- // Adjust to GMT //----------------------------------------- if ($this->request['event_timezone'] and !$this->request['all_day']) { $start_date = $start_date - $this->request['event_timezone'] * 3600; if ($end_date) { $end_date = $end_date - $this->request['event_timezone'] * 3600; } } $start_date = gmstrftime("%Y-%m-%d %H:%M:00", $start_date); $end_date = $end_date ? gmstrftime("%Y-%m-%d %H:%M:00", $end_date) : 0; //----------------------------------------- // Check posted content for errors //----------------------------------------- if (strlen(trim(IPSText::removeControlCharacters(IPSText::br2nl($_POST['Post'])))) < 1) { $this->registry->output->showError('calendar_post_too_short', 10417, null, null, 403); } $this->settings['max_post_length'] = $this->settings['max_post_length'] ? $this->settings['max_post_length'] : 2140000; if (IPSText::mbstrlen($_POST['Post']) > $this->settings['max_post_length'] * 1024) { $this->registry->output->showError('calendar_post_too_long', 10418, null, null, 403); } if (!$event_title or IPSText::mbstrlen($event_title) < 2) { $this->registry->output->showError('calendar_no_title', 10419, null, null, 403); } if (IPSText::mbstrlen($event_title) > 200) { $this->registry->output->showError('calendar_title_too_long', 10420, null, null, 403); } //----------------------------------------- // Adding or editing? //----------------------------------------- if ($type == 'edit') { //----------------------------------------- // Get event //----------------------------------------- if (!$event_id) { $this->registry->output->showError('calendar_event_not_found', 10414, null, null, 404); } $event = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'cal_events', 'where' => 'event_id=' . $event_id)); if (!$event['event_id']) { $this->registry->output->showError('calendar_event_not_found', 10415, null, null, 404); } //----------------------------------------- // Do we have permission to edit? //----------------------------------------- if (!$this->memberData['g_is_supmod'] and $this->memberData['member_id'] != $event['event_member_id']) { $this->registry->output->showError('calendar_no_edit_perm', 10416, null, null, 403); } } //----------------------------------------- // Set event view permissions //----------------------------------------- if ($this->memberData['g_access_cp']) { if (is_array($this->request['e_groups'])) { foreach ($this->cache->getCache('group_cache') as $group) { if ($group['g_access_cp']) { $this->request['e_groups'][] = $group['g_id']; } } $read_perms = implode(",", $this->request['e_groups']); } } $read_perms = $read_perms ? $read_perms : '*'; //----------------------------------------- // Get editor and format post //----------------------------------------- $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite'); $editor = new $classToLoad(); $event_content = $editor->process($_POST['Post']); IPSText::getTextClass('bbcode')->parse_html = 0; IPSText::getTextClass('bbcode')->parse_smilies = intval($this->request['enableemo']); IPSText::getTextClass('bbcode')->parse_bbcode = 1; IPSText::getTextClass('bbcode')->parsing_section = 'calendar'; $event_content = IPSText::getTextClass('bbcode')->preDbParse($event_content); //----------------------------------------- // Event approved? //----------------------------------------- if ($this->request['e_type'] == 'private') { $event_approved = 1; } else { $event_approved = $this->registry->permissions->check('nomod', $_calendar) ? 1 : ($_calendar['cal_moderate'] ? 0 : 1); } //----------------------------------------- // Store the event //----------------------------------------- if ($type == 'add') { //----------------------------------------- // Format array for storage //----------------------------------------- $_eventData = array('event_calendar_id' => $calendar_id, 'event_member_id' => $this->memberData['member_id'], 'event_content' => $event_content, 'event_title' => $event_title, 'event_title_seo' => IPSText::makeSeoTitle($event_title), 'event_smilies' => intval($this->request['enableemo']), 'event_comments' => 0, 'event_perms' => $read_perms, 'event_private' => $this->request['e_type'] == 'private' ? 1 : 0, 'event_approved' => $event_approved, 'event_saved' => time(), 'event_lastupdated' => time(), 'event_recurring' => $recurring, 'event_start_date' => $start_date, 'event_end_date' => $end_date, 'event_post_key' => $this->request['post_key'], 'event_rsvp' => $this->registry->permissions->check('askrsvp', $_calendar) ? intval($this->request['event_rsvp']) : 0, 'event_sequence' => 0, 'event_all_day' => intval($this->request['all_day'])); //----------------------------------------- // Data hooks //----------------------------------------- IPSLib::doDataHooks($_eventData, 'calendarAddEvent'); //----------------------------------------- // Insert //----------------------------------------- $this->DB->insert('cal_events', $_eventData); $event_id = $this->DB->getInsertId(); //----------------------------------------- // Set language strings //----------------------------------------- $_langString = $event_approved ? $this->lang->words['new_event_redirect'] : $this->lang->words['new_event_mod']; } else { //----------------------------------------- // Format array for storage //----------------------------------------- $_eventData = array('event_calendar_id' => $calendar_id, 'event_content' => $event_content, 'event_title' => $event_title, 'event_title_seo' => IPSText::makeSeoTitle($event_title), 'event_smilies' => intval($this->request['enableemo']), 'event_perms' => $read_perms, 'event_private' => $this->request['e_type'] == 'private' ? 1 : 0, 'event_approved' => $event_approved, 'event_lastupdated' => time(), 'event_recurring' => $recurring, 'event_start_date' => $start_date, 'event_end_date' => $end_date, 'event_post_key' => $this->request['post_key'], 'event_rsvp' => $this->registry->permissions->check('askrsvp', $_calendar) ? intval($this->request['event_rsvp']) : $event['event_rsvp'], 'event_sequence' => intval($event['event_rsvp']) + 1, 'event_all_day' => intval($this->request['all_day'])); //----------------------------------------- // Data hooks //----------------------------------------- IPSLib::doDataHooks($_eventData, 'calendarEditEvent'); //----------------------------------------- // Update database //----------------------------------------- $this->DB->update('cal_events', $_eventData, 'event_id=' . $event_id); //----------------------------------------- // Set language strings //----------------------------------------- $_langString = $event_approved ? $this->lang->words['edit_event_redirect'] : $this->lang->words['new_event_mod']; } //----------------------------------------- // Upload attachments //----------------------------------------- if ($this->memberData['g_attach_max'] != -1) { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php', 'class_attach'); $class_attach = new $classToLoad($this->registry); $class_attach->type = 'event'; $class_attach->attach_post_key = $_eventData['event_post_key']; $class_attach->attach_rel_id = $event_id; $class_attach->init(); $class_attach->processMultipleUploads(); $class_attach->postProcessUpload(array()); } //----------------------------------------- // Send notifications //----------------------------------------- if ($event_approved) { require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php'; /*noLibHook*/ $_like = classes_like::bootstrap('calendar', $type == 'edit' ? 'events' : 'calendars'); $_url = $this->registry->output->buildSEOUrl('app=calendar&module=calendar&section=view&do=showevent&event_id=' . $event_id, 'public', $_eventData['event_title_seo'], 'cal_event'); $_like->sendNotifications($type == 'edit' ? $event_id : $_eventData['event_calendar_id'], array('immediate', 'offline'), array('notification_key' => $type == 'edit' ? 'updated_event' : 'new_event', 'notification_url' => $_url, 'email_template' => $type . '_event_follow', 'email_subject' => sprintf($this->lang->words[$type . '_event_follow_subject'], $_url, $_eventData['event_title']), 'build_message_array' => array('NAME' => '-member:members_display_name-', 'AUTHOR' => $this->memberData['members_display_name'], 'TITLE' => $_eventData['event_title'], 'URL' => $_url))); } //----------------------------------------- // Rebuild cache //----------------------------------------- $this->cache->rebuildCache('calendar_events', 'calendar'); //----------------------------------------- // Redirect //----------------------------------------- if ($event_approved) { $this->registry->output->redirectScreen($_langString, $this->settings['base_url'] . "app=calendar&module=calendar&section=view&do=showevent&event_id=" . $event_id, $_eventData['event_title_seo'], 'cal_event'); } else { $this->registry->output->redirectScreen($_langString, $this->settings['base_url'] . "app=calendar&module=calendar&section=view&cal_id=" . $calendar_id, $this->caches['calendars'][$calendar_id]['cal_title_seo'], 'cal_calendar'); } }