Oh, the stories I have to share, my friends.
Nearly two weeks ago, Michael and I headed out with the dogs to visit friends in Colorado. The RV was packed to the brim–we were all ready for a few days away from the heat of Texas.
Just outside of Lubbock we blew a tire on the RV. Shreds of our tire joined the many other shards already littering the side of the road.
I've always wondered what it'd be like to blow a tire–now I know–lesson learned.
All-in-all, things went well. The blown tire was on the curb side of the RV, meaning Michael was not right next to the highway as he struggled to assess damage and change the tire. Our three dogs handled it well, moving as asked to the front seat of the truck when Michael needed to get under the seat they were secured to in order to access the heavy-duty jack. The spare tire was in excellent shape, the jack worked, and every vehicle passing us never seriously compromised our safety.
As with any scary situation, it feels better if you walk away feeling you learned something from that experience.
Here's what I learned from this segment of our trip.
Before hitting the road, make sure everyone knows where your emergency equipment is located. If it's not easily accessible, move it so it is.
Review how to put things like jacks together before hand so repairs go faster.
Pack water and snacks for all–be sure to include something your dogs can use as a water bowl.
Have alternate RV spots to spend the night in case you are delayed.
Lastly, and most importantly, never ever text and drive. As I stood watching for anyone not paying attention in the steady line of traffic coming our way at speeds around 75-80 mph, I prayed each and every driver was paying attention. Stay alert, giving those working on the side of the road all the space you can as you pass.
Thank God for cell phones and internet. By doing a quick search, we were able to get to Discount Tire in Lubbock before they closed. Even though they were busy, in a matter of hours, they had four new tires in place and we were back on the road.
As I sat and waited in Lubbock, I thanked God no one was injured. I thanked God our GMC truck kept the trailer in control and the damage to the trailer minimal. We're fortunate Michael and I have been traveling together by RV for many years. We've learned each others strong points and work well together getting whatever needs to be done. I'm not saying it's always pretty–but we get 'er done!
What surprised me the most was how our dogs settled in and acted as if this was just another day. They sat quietly beside me, watching people and cars come and go as I tried to pre-determine what person went with what car. I learned I am not good at that game but it certainly entertained me! Even Mother Nature stepped up her game–the dark rain clouds building all around us held off until we were well down the road.


text:
<?php

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

/**
* mcp_main
* Handling mcp actions
*/
class mcp_main
{
	var $p_master;
	var $u_action;

	function mcp_main(&$p_master)
	{
		$this->p_master = &$p_master;
	}

	function main($id, $mode)
	{
		global $auth, $db, $user, $template, $action;
		global $config, $phpbb_root_path, $phpEx, $request;
		global $phpbb_dispatcher;

		$quickmod = ($mode == 'quickmod') ? true : false;

		switch ($action)
		{
			case 'lock':
			case 'unlock':
				$topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				lock_unlock($action, $topic_ids);
			break;

			case 'lock_post':
			case 'unlock_post':

				$post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0));

				if (!sizeof($post_ids))
				{
					trigger_error('NO_POST_SELECTED');
				}

				lock_unlock($action, $post_ids);
			break;

			case 'make_announce':
			case 'make_sticky':
			case 'make_global':
			case 'make_normal':

				$topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				change_topic_type($action, $topic_ids);
			break;

			case 'move':
				$user->add_lang('viewtopic');

				$topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				mcp_move_topic($topic_ids);
			break;

			case 'fork':
				$user->add_lang('viewtopic');

				$topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				mcp_fork_topic($topic_ids);
			break;

			case 'delete_topic':
				$user->add_lang('viewtopic');

				// f parameter is not reliable for permission usage, however we just use it to decide
				// which permission we will check later on. So if it is manipulated, we will still catch it later on.
				$forum_id = $request->variable('f', 0);
				$topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
				$soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				mcp_delete_topic($topic_ids, $soft_delete, $request->variable('delete_reason', '', true));
			break;

			case 'delete_post':
				$user->add_lang('posting');

				// f parameter is not reliable for permission usage, however we just use it to decide
				// which permission we will check later on. So if it is manipulated, we will still catch it later on.
				$forum_id = $request->variable('f', 0);
				$post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0));
				$soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;

				if (!sizeof($post_ids))
				{
					trigger_error('NO_POST_SELECTED');
				}

				mcp_delete_post($post_ids, $soft_delete, $request->variable('delete_reason', '', true));
			break;

			case 'restore_topic':
				$user->add_lang('posting');

				$topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));

				if (!sizeof($topic_ids))
				{
					trigger_error('NO_TOPIC_SELECTED');
				}

				mcp_restore_topic($topic_ids);
			break;

			default:
				/**
				* This event allows you to handle custom quickmod options
				*
				* @event core.modify_quickmod_actions
				* @var	string	action		Topic quick moderation action name
				* @var	bool	quickmod	Flag indicating whether MCP is in quick moderation mode
				* @since 3.1.0-a4
				* @change 3.1.0-RC4 Added variables: action, quickmod
				*/
				$vars = array('action', 'quickmod');
				extract($phpbb_dispatcher->trigger_event('core.modify_quickmod_actions', compact($vars)));
			break;
		}

		switch ($mode)
		{
			case 'front':
				include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx);

				$user->add_lang('acp/common');

				mcp_front_view($id, $mode, $action);

				$this->tpl_name = 'mcp_front';
				$this->page_title = 'MCP_MAIN';
			break;

			case 'forum_view':
				include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx);

				$user->add_lang('viewforum');

				$forum_id = request_var('f', 0);

				$forum_info = phpbb_get_forum_data($forum_id, 'm_', true);

				if (!sizeof($forum_info))
				{
					$this->main('main', 'front');
					return;
				}

				$forum_info = $forum_info[$forum_id];

				mcp_forum_view($id, $mode, $action, $forum_info);

				$this->tpl_name = 'mcp_forum';
				$this->page_title = 'MCP_MAIN_FORUM_VIEW';
			break;

			case 'topic_view':
				include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx);

				mcp_topic_view($id, $mode, $action);

				$this->tpl_name = 'mcp_topic';
				$this->page_title = 'MCP_MAIN_TOPIC_VIEW';
			break;

			case 'post_details':
				include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx);

				mcp_post_details($id, $mode, $action);

				$this->tpl_name = ($action == 'whois') ? 'mcp_whois' : 'mcp_post';
				$this->page_title = 'MCP_MAIN_POST_DETAILS';
			break;

			default:
				if ($quickmod)
				{
					switch ($action)
					{
						case 'lock':
						case 'unlock':
						case 'make_announce':
						case 'make_sticky':
						case 'make_global':
						case 'make_normal':
						case 'make_onindex':
						case 'move':
						case 'fork':
						case 'delete_topic':
							trigger_error('TOPIC_NOT_EXIST');
						break;

						case 'lock_post':
						case 'unlock_post':
						case 'delete_post':
							trigger_error('POST_NOT_EXIST');
						break;
					}
				}

				trigger_error('NO_MODE', E_USER_ERROR);
			break;
		}
	}
}

/**
* Lock/Unlock Topic/Post
*/
function lock_unlock($action, $ids)
{
	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_dispatcher;

	if ($action == 'lock' || $action == 'unlock')
	{
		$table = TOPICS_TABLE;
		$sql_id = 'topic_id';
		$set_id = 'topic_status';
		$l_prefix = 'TOPIC';
	}
	else
	{
		$table = POSTS_TABLE;
		$sql_id = 'post_id';
		$set_id = 'post_edit_locked';
		$l_prefix = 'POST';
	}

	$orig_ids = $ids;

	if (!phpbb_check_ids($ids, $table, $sql_id, array('m_lock')))
	{
		// Make sure that for f_user_lock only the lock action is triggered.
		if ($action != 'lock')
		{
			return;
		}

		$ids = $orig_ids;

		if (!phpbb_check_ids($ids, $table, $sql_id, array('f_user_lock')))
		{
			return;
		}
	}
	unset($orig_ids);

	$redirect = request_var('redirect', build_url(array('action', 'quickmod')));
	$redirect = reapply_sid($redirect);

	$s_hidden_fields = build_hidden_fields(array(
		$sql_id . '_list'	=> $ids,
		'action'			=> $action,
		'redirect'			=> $redirect)
	);
	$success_msg = '';

	if (confirm_box(true))
	{
		$sql = "UPDATE $table
			SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
		$db->sql_query($sql);

		$data = ($action == 'lock' || $action == 'unlock') ? phpbb_get_topic_data($ids) : phpbb_get_post_data($ids);

		foreach ($data as $id => $row)
		{
			add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']);
		}

		/**
		 * Perform additional actions after locking/unlocking posts/topics
		 *
		 * @event core.mcp_lock_unlock_after
		 * @var	string	action				Variable containing the action we perform on the posts/topics ('lock', 'unlock', 'lock_post' or 'unlock_post')
		 * @var	array	ids					Array containing the post/topic IDs that have been locked/unlocked
		 * @var	array	data				Array containing posts/topics data
		 * @since 3.1.7-RC1
		 */
		$vars = array(
			'action',
			'ids',
			'data',
		);
		extract($phpbb_dispatcher->trigger_event('core.mcp_lock_unlock_after', compact($vars)));

		$success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS';

		meta_refresh(2, $redirect);
		$message = $user->lang[$success_msg];

		if (!$request->is_ajax())
		{
			$message .= '

' . $user->lang('RETURN_PAGE', '', '');
		}
		trigger_error($message);
	}
	else
	{
		confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields);
	}

	redirect($redirect);
}

/**
* Change Topic Type
*/
function change_topic_type($action, $topic_ids)
{
	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request;

	switch ($action)
	{
		case 'make_announce':
			$new_topic_type = POST_ANNOUNCE;
			$check_acl = 'f_announce';
			$l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS';
		break;

		case 'make_global':
			$new_topic_type = POST_GLOBAL;
			$check_acl = 'f_announce';
			$l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS';
		break;

		case 'make_sticky':
			$new_topic_type = POST_STICKY;
			$check_acl = 'f_sticky';
			$l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES';
		break;

		default:
			$new_topic_type = POST_NORMAL;
			$check_acl = false;
			$l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS';
		break;
	}

	$forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true);

	if ($forum_id === false)
	{
		return;
	}

	$redirect = request_var('redirect', build_url(array('action', 'quickmod')));
	$redirect = reapply_sid($redirect);

	$s_hidden_fields = array(
		'topic_id_list'	=> $topic_ids,
		'f'				=> $forum_id,
		'action'		=> $action,
		'redirect'		=> $redirect,
	);
	$success_msg = '';

	if (confirm_box(true))
	{
		$sql = 'UPDATE ' . TOPICS_TABLE . "
			SET topic_type = $new_topic_type
			WHERE " . $db->sql_in_set('topic_id', $topic_ids);
		$db->sql_query($sql);

		if (($new_topic_type == POST_GLOBAL) && sizeof($topic_ids))
		{
			// Delete topic shadows for global announcements
			$sql = 'DELETE FROM ' . TOPICS_TABLE . '
				WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids);
			$db->sql_query($sql);

			$sql = 'UPDATE ' . TOPICS_TABLE . "
				SET topic_type = $new_topic_type
					WHERE " . $db->sql_in_set('topic_id', $topic_ids);
			$db->sql_query($sql);
		}

		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED';

		if (sizeof($topic_ids))
		{
			$data = phpbb_get_topic_data($topic_ids);

			foreach ($data as $topic_id => $row)
			{
				add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']);
			}
		}

		meta_refresh(2, $redirect);
		$message = $user->lang[$success_msg];

		if (!$request->is_ajax())
		{
			$message .= '

' . $user->lang('RETURN_PAGE', '', '');
		}
		trigger_error($message);
	}
	else
	{
		confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields));
	}

	redirect($redirect);
}

/**
* Move Topic
*/
function mcp_move_topic($topic_ids)
{
	global $auth, $user, $db, $template, $phpbb_log, $request;
	global $phpEx, $phpbb_root_path;

	// Here we limit the operation to one forum only
	$forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true);

	if ($forum_id === false)
	{
		return;
	}

	$to_forum_id = request_var('to_forum_id', 0);
	$redirect = request_var('redirect', build_url(array('action', 'quickmod')));
	$additional_msg = $success_msg = '';

	$s_hidden_fields = build_hidden_fields(array(
		'topic_id_list'	=> $topic_ids,
		'f'				=> $forum_id,
		'action'		=> 'move',
		'redirect'		=> $redirect)
	);

	if ($to_forum_id)
	{
		$forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');

		if (!sizeof($forum_data))
		{
			$additional_msg = $user->lang['FORUM_NOT_EXIST'];
		}
		else
		{
			$forum_data = $forum_data[$to_forum_id];

			if ($forum_data['forum_type'] != FORUM_POST)
			{
				$additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
			}
			else if (!$auth->acl_get('f_post', $to_forum_id) || (!$auth->acl_get('m_approve', $to_forum_id) && !$auth->acl_get('f_noapprove', $to_forum_id)))
			{
				$additional_msg = $user->lang['USER_CANNOT_POST'];
			}
			else if ($forum_id == $to_forum_id)
			{
				$additional_msg = $user->lang['CANNOT_MOVE_SAME_FORUM'];
			}
		}
	}
	else if (isset($_POST['confirm']))
	{
		$additional_msg = $user->lang['FORUM_NOT_EXIST'];
	}

	if (!$to_forum_id || $additional_msg)
	{
		$request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
		$request->overwrite('confirm_key', null);
	}

	if (confirm_box(true))
	{
		$topic_data = phpbb_get_topic_data($topic_ids);
		$leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false;

		$forum_sync_data = array();

		$forum_sync_data[$forum_id] = current($topic_data);
		$forum_sync_data[$to_forum_id] = $forum_data;

		$topics_moved = $topics_moved_unapproved = $topics_moved_softdeleted = 0;
		$posts_moved = $posts_moved_unapproved = $posts_moved_softdeleted = 0;

		foreach ($topic_data as $topic_id => $topic_info)
		{
			if ($topic_info['topic_visibility'] == ITEM_APPROVED)
			{
				$topics_moved++;
			}
			else if ($topic_info['topic_visibility'] == ITEM_UNAPPROVED || $topic_info['topic_visibility'] == ITEM_REAPPROVE)
			{
				$topics_moved_unapproved++;
			}
			else if ($topic_info['topic_visibility'] == ITEM_DELETED)
			{
				$topics_moved_softdeleted++;
			}

			$posts_moved += $topic_info['topic_posts_approved'];
			$posts_moved_unapproved += $topic_info['topic_posts_unapproved'];
			$posts_moved_softdeleted += $topic_info['topic_posts_softdeleted'];
		}

		$db->sql_transaction('begin');

		// Move topics, but do not resync yet
		move_topics($topic_ids, $to_forum_id, false);

		if ($request->is_set_post('move_lock_topics') && $auth->acl_get('m_lock', $to_forum_id))
		{
			$sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_status = ' . ITEM_LOCKED . '
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
			$db->sql_query($sql);
		}

		$shadow_topics = 0;
		$forum_ids = array($to_forum_id);
		foreach ($topic_data as $topic_id => $row)
		{
			// Get the list of forums to resync
			$forum_ids[] = $row['forum_id'];

			// We add the $to_forum_id twice, because 'forum_id' is updated
			// when the topic is moved again later.
			$phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MOVE', false, array(
				'forum_id'		=> (int) $to_forum_id,
				'topic_id'		=> (int) $topic_id,
				$row['forum_name'],
				$forum_data['forum_name'],
				(int) $row['forum_id'],
				(int) $forum_data['forum_id'],
			));

			// Leave a redirection if required and only if the topic is visible to users
			if ($leave_shadow && $row['topic_visibility'] == ITEM_APPROVED && $row['topic_type'] != POST_GLOBAL)
			{
				$shadow = array(
					'forum_id'				=>	(int) $row['forum_id'],
					'icon_id'				=>	(int) $row['icon_id'],
					'topic_attachment'		=>	(int) $row['topic_attachment'],
					'topic_visibility'		=>	ITEM_APPROVED, // a shadow topic is always approved
					'topic_reported'		=>	0, // a shadow topic is never reported
					'topic_title'			=>	(string) $row['topic_title'],
					'topic_poster'			=>	(int) $row['topic_poster'],
					'topic_time'			=>	(int) $row['topic_time'],
					'topic_time_limit'		=>	(int) $row['topic_time_limit'],
					'topic_views'			=>	(int) $row['topic_views'],
					'topic_posts_approved'	=>	(int) $row['topic_posts_approved'],
					'topic_posts_unapproved'=>	(int) $row['topic_posts_unapproved'],
					'topic_posts_softdeleted'=>	(int) $row['topic_posts_softdeleted'],
					'topic_status'			=>	ITEM_MOVED,
					'topic_type'			=>	POST_NORMAL,
					'topic_first_post_id'	=>	(int) $row['topic_first_post_id'],
					'topic_first_poster_colour'=>(string) $row['topic_first_poster_colour'],
					'topic_first_poster_name'=>	(string) $row['topic_first_poster_name'],
					'topic_last_post_id'	=>	(int) $row['topic_last_post_id'],
					'topic_last_poster_id'	=>	(int) $row['topic_last_poster_id'],
					'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'],
					'topic_last_poster_name'=>	(string) $row['topic_last_poster_name'],
					'topic_last_post_subject'=>	(string) $row['topic_last_post_subject'],
					'topic_last_post_time'	=>	(int) $row['topic_last_post_time'],
					'topic_last_view_time'	=>	(int) $row['topic_last_view_time'],
					'topic_moved_id'		=>	(int) $row['topic_id'],
					'topic_bumped'			=>	(int) $row['topic_bumped'],
					'topic_bumper'			=>	(int) $row['topic_bumper'],
					'poll_title'			=>	(string) $row['poll_title'],
					'poll_start'			=>	(int) $row['poll_start'],
					'poll_length'			=>	(int) $row['poll_length'],
					'poll_max_options'		=>	(int) $row['poll_max_options'],
					'poll_last_vote'		=>	(int) $row['poll_last_vote']
				);

				$db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow));

				// Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts
				$shadow_topics++;
			}
		}
		unset($topic_data);

		$sync_sql = array();
		if ($posts_moved)
		{
			$sync_sql[$to_forum_id][] = 'forum_posts_approved = forum_posts_approved + ' . (int) $posts_moved;
			$sync_sql[$forum_id][] = 'forum_posts_approved = forum_posts_approved - ' . (int) $posts_moved;
		}
		if ($posts_moved_unapproved)
		{
			$sync_sql[$to_forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved + ' . (int) $posts_moved_unapproved;
			$sync_sql[$forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved - ' . (int) $posts_moved_unapproved;
		}
		if ($posts_moved_softdeleted)
		{
			$sync_sql[$to_forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted + ' . (int) $posts_moved_softdeleted;
			$sync_sql[$forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted - ' . (int) $posts_moved_softdeleted;
		}

		if ($topics_moved)
		{
			$sync_sql[$to_forum_id][] = 'forum_topics_approved = forum_topics_approved + ' . (int) $topics_moved;
			if ($topics_moved - $shadow_topics > 0)
			{
				$sync_sql[$forum_id][] = 'forum_topics_approved = forum_topics_approved - ' . (int) ($topics_moved - $shadow_topics);
			}
		}
		if ($topics_moved_unapproved)
		{
			$sync_sql[$to_forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved + ' . (int) $topics_moved_unapproved;
			$sync_sql[$forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved - ' . (int) $topics_moved_unapproved;
		}
		if ($topics_moved_softdeleted)
		{
			$sync_sql[$to_forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted + ' . (int) $topics_moved_softdeleted;
			$sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted;
		}

		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS';

		foreach ($sync_sql as $forum_id_key => $array)
		{
			$sql = 'UPDATE ' . FORUMS_TABLE . '
				SET ' . implode(', ', $array) . '
				WHERE forum_id = ' . $forum_id_key;
			$db->sql_query($sql);
		}

		$db->sql_transaction('commit');

		sync('forum', 'forum_id', array($forum_id, $to_forum_id));
	}
	else
	{
		$template->assign_vars(array(
			'S_FORUM_SELECT'		=> make_forum_select($to_forum_id, $forum_id, false, true, true, true),
			'S_CAN_LEAVE_SHADOW'	=> true,
			'S_CAN_LOCK_TOPIC'		=> ($auth->acl_get('m_lock', $to_forum_id)) ? true : false,
			'ADDITIONAL_MSG'		=> $additional_msg)
		);

		confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
	}

	$redirect = request_var('redirect', "index.$phpEx");
	$redirect = reapply_sid($redirect);

	if (!$success_msg)
	{
		redirect($redirect);
	}
	else
	{
		meta_refresh(3, $redirect);

		$message = $user->lang[$success_msg];
		$message .= '

' . sprintf($user->lang['RETURN_PAGE'], '', '');
		$message .= '

' . sprintf($user->lang['RETURN_FORUM'], '', '');
		$message .= '

' . sprintf($user->lang['RETURN_NEW_FORUM'], '', '');

		trigger_error($message);
	}
}

/**
* Restore Topics
*/
function mcp_restore_topic($topic_ids)
{
	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;

	if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve')))
	{
		return;
	}

	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
	$forum_id = $request->variable('f', 0);

	$s_hidden_fields = build_hidden_fields(array(
		'topic_id_list'	=> $topic_ids,
		'f'				=> $forum_id,
		'action'		=> 'restore_topic',
		'redirect'		=> $redirect,
	));
	$success_msg = '';

	if (confirm_box(true))
	{
		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS';

		$data = phpbb_get_topic_data($topic_ids);

		$phpbb_content_visibility = $phpbb_container->get('content.visibility');
		foreach ($data as $topic_id => $row)
		{
			$return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), '');
			if (!empty($return))
			{
				add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']);
			}
		}
	}
	else
	{
		confirm_box(false, (sizeof($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields);
	}

	$topic_id = $request->variable('t', 0);
	if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
	{
		$redirect = $request->variable('redirect', "index.$phpEx");
		$redirect = reapply_sid($redirect);
		$redirect_message = 'PAGE';
	}
	else if ($topic_id)
	{
		$redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
		$redirect_message = 'TOPIC';
	}
	else
	{
		$redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
		$redirect_message = 'FORUM';
	}

	if (!$success_msg)
	{
		redirect($redirect);
	}
	else
	{
		meta_refresh(3, $redirect);
		trigger_error($user->lang[$success_msg] . '

' . sprintf($user->lang['RETURN_' . $redirect_message], '', ''));
	}
}

/**
* Delete Topics
*/
function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic')
{
	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;

	$check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
	if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission)))
	{
		return;
	}

	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
	$forum_id = $request->variable('f', 0);

	$s_hidden_fields = array(
		'topic_id_list'	=> $topic_ids,
		'f'				=> $forum_id,
		'action'		=> $action,
		'redirect'		=> $redirect,
	);
	$success_msg = '';

	if (confirm_box(true))
	{
		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS';

		$data = phpbb_get_topic_data($topic_ids);

		foreach ($data as $topic_id => $row)
		{
			if ($row['topic_moved_id'])
			{
				add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']);
			}
			else
			{
				// Only soft delete non-shadow topics
				if ($is_soft)
				{
					$phpbb_content_visibility = $phpbb_container->get('content.visibility');
					$return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason);
					if (!empty($return))
					{
						add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
					}
				}
				else
				{
					add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
				}
			}
		}

		if (!$is_soft)
		{
			$return = delete_topics('topic_id', $topic_ids);
		}
	}
	else
	{
		global $template;

		$user->add_lang('posting');

		// If there are only shadow topics, we neither need a reason nor softdelete
		$sql = 'SELECT topic_id
			FROM ' . TOPICS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
				AND topic_moved_id = 0';
		$result = $db->sql_query_limit($sql, 1);
		$only_shadow = !$db->sql_fetchfield('topic_id');
		$db->sql_freeresult($result);

		$only_softdeleted = false;
		if (!$only_shadow && $auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
		{
			// If there are only soft deleted topics, we display a message why the option is not available
			$sql = 'SELECT topic_id
				FROM ' . TOPICS_TABLE . '
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
					AND topic_visibility <> ' . ITEM_DELETED;
			$result = $db->sql_query_limit($sql, 1);
			$only_softdeleted = !$db->sql_fetchfield('topic_id');
			$db->sql_freeresult($result);
		}

		$template->assign_vars(array(
			'S_SHADOW_TOPICS'		=> $only_shadow,
			'S_SOFTDELETED'			=> $only_softdeleted,
			'S_TOPIC_MODE'			=> true,
			'S_ALLOWED_DELETE'		=> $auth->acl_get('m_delete', $forum_id),
			'S_ALLOWED_SOFTDELETE'	=> $auth->acl_get('m_softdelete', $forum_id),
		));

		$l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS';
		if ($only_softdeleted)
		{
			$l_confirm .= '_PERMANENTLY';
			$s_hidden_fields['delete_permanent'] = '1';
		}
		else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id))
		{
			$s_hidden_fields['delete_permanent'] = '1';
		}

		confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
	}

	$topic_id = $request->variable('t', 0);
	if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
	{
		$redirect = $request->variable('redirect', "index.$phpEx");
		$redirect = reapply_sid($redirect);
		$redirect_message = 'PAGE';
	}
	else if ($is_soft && $topic_id)
	{
		$redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
		$redirect_message = 'TOPIC';
	}
	else
	{
		$redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
		$redirect_message = 'FORUM';
	}

	if (!$success_msg)
	{
		redirect($redirect);
	}
	else
	{
		meta_refresh(3, $redirect);
		trigger_error($user->lang[$success_msg] . '

' . sprintf($user->lang['RETURN_' . $redirect_message], '', ''));
	}
}

/**
* Delete Posts
*/
function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post')
{
	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;

	$check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
	if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission)))
	{
		return;
	}

	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
	$forum_id = $request->variable('f', 0);

	$s_hidden_fields = array(
		'post_id_list'	=> $post_ids,
		'f'				=> $forum_id,
		'action'		=> $action,
		'redirect'		=> $redirect,
	);
	$success_msg = '';

	if (confirm_box(true) && $is_soft)
	{
		$post_info = phpbb_get_post_data($post_ids);

		$topic_info = $approve_log = array();

		// Group the posts by topic_id
		foreach ($post_info as $post_id => $post_data)
		{
			if ($post_data['post_visibility'] != ITEM_APPROVED)
			{
				continue;
			}
			$topic_id = (int) $post_data['topic_id'];

			$topic_info[$topic_id]['posts'][] = (int) $post_id;
			$topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id'];

			if ($post_id == $post_data['topic_first_post_id'])
			{
				$topic_info[$topic_id]['first_post'] = true;
			}

			if ($post_id == $post_data['topic_last_post_id'])
			{
				$topic_info[$topic_id]['last_post'] = true;
			}

			$approve_log[] = array(
				'forum_id'		=> $post_data['forum_id'],
				'topic_id'		=> $post_data['topic_id'],
				'post_subject'	=> $post_data['post_subject'],
				'poster_id'		=> $post_data['poster_id'],
				'post_username'	=> $post_data['post_username'],
				'username'		=> $post_data['username'],
			);
		}

		$phpbb_content_visibility = $phpbb_container->get('content.visibility');
		foreach ($topic_info as $topic_id => $topic_data)
		{
			$phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), $soft_delete_reason, isset($topic_data['first_post']), isset($topic_data['last_post']));
		}
		$affected_topics = sizeof($topic_info);
		// None of the topics is really deleted, so a redirect won't hurt much.
		$deleted_topics = 0;

		$success_msg = (sizeof($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS'];

		foreach ($approve_log as $row)
		{
			$post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
			add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
		}

		$topic_id = $request->variable('t', 0);

		// Return links
		$return_link = array();
		if ($affected_topics == 1 && $topic_id)
		{
			$return_link[] = sprintf($user->lang['RETURN_TOPIC'], '', '');
		}
		$return_link[] = sprintf($user->lang['RETURN_FORUM'], '', '');

	}
	else if (confirm_box(true))
	{
		if (!function_exists('delete_posts'))
		{
			include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
		}

		// Count the number of topics that are affected
		// I did not use COUNT(DISTINCT ...) because I remember having problems
		// with it on older versions of MySQL -- Ashe

		$sql = 'SELECT DISTINCT topic_id
			FROM ' . POSTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_id', $post_ids);
		$result = $db->sql_query($sql);

		$topic_id_list = array();
		while ($row = $db->sql_fetchrow($result))
		{
			$topic_id_list[] = $row['topic_id'];
		}
		$affected_topics = sizeof($topic_id_list);
		$db->sql_freeresult($result);

		$post_data = phpbb_get_post_data($post_ids);

		foreach ($post_data as $id => $row)
		{
			$post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
			add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
		}

		// Now delete the posts, topics and forums are automatically resync'ed
		delete_posts('post_id', $post_ids);

		$sql = 'SELECT COUNT(topic_id) AS topics_left
			FROM ' . TOPICS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_id_list);
		$result = $db->sql_query_limit($sql, 1);

		$deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics;
		$db->sql_freeresult($result);

		$topic_id = $request->variable('t', 0);

		// Return links
		$return_link = array();
		if ($affected_topics == 1 && !$deleted_topics && $topic_id)
		{
			$return_link[] = sprintf($user->lang['RETURN_TOPIC'], '', '');
		}
		$return_link[] = sprintf($user->lang['RETURN_FORUM'], '', '');

		if (sizeof($post_ids) == 1)
		{
			if ($deleted_topics)
			{
				// We deleted the only post of a topic, which in turn has
				// been removed from the database
				$success_msg = $user->lang['TOPIC_DELETED_SUCCESS'];
			}
			else
			{
				$success_msg = $user->lang['POST_DELETED_SUCCESS'];
			}
		}
		else
		{
			if ($deleted_topics)
			{
				// Some of topics disappeared
				$success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '

' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING'];
			}
			else
			{
				$success_msg = $user->lang['POSTS_DELETED_SUCCESS'];
			}
		}
	}
	else
	{
		global $template;

		$user->add_lang('posting');

		$only_softdeleted = false;
		if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
		{
			// If there are only soft deleted posts, we display a message why the option is not available
			$sql = 'SELECT post_id
				FROM ' . POSTS_TABLE . '
				WHERE ' . $db->sql_in_set('post_id', $post_ids) . '
					AND post_visibility <> ' . ITEM_DELETED;
			$result = $db->sql_query_limit($sql, 1);
			$only_softdeleted = !$db->sql_fetchfield('post_id');
			$db->sql_freeresult($result);
		}

		$template->assign_vars(array(
			'S_SOFTDELETED'			=> $only_softdeleted,
			'S_ALLOWED_DELETE'		=> $auth->acl_get('m_delete', $forum_id),
			'S_ALLOWED_SOFTDELETE'	=> $auth->acl_get('m_softdelete', $forum_id),
		));

		$l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS';
		if ($only_softdeleted)
		{
			$l_confirm .= '_PERMANENTLY';
			$s_hidden_fields['delete_permanent'] = '1';
		}
		else if (!$auth->acl_get('m_softdelete', $forum_id))
		{
			$s_hidden_fields['delete_permanent'] = '1';
		}

		confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
	}

	$redirect = $request->variable('redirect', "index.$phpEx");
	$redirect = reapply_sid($redirect);

	if (!$success_msg)
	{
		redirect($redirect);
	}
	else
	{
		if ($affected_topics != 1 || $deleted_topics || !$topic_id)
		{
			$redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false);
		}

		meta_refresh(3, $redirect);
		trigger_error($success_msg . '

' . sprintf($user->lang['RETURN_PAGE'], '', '') . '

' . implode('

', $return_link));
	}
}

/**
* Fork Topic
*/
function mcp_fork_topic($topic_ids)
{
	global $auth, $user, $db, $template, $config;
	global $phpEx, $phpbb_root_path, $phpbb_dispatcher;

	if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_')))
	{
		return;
	}

	$to_forum_id = request_var('to_forum_id', 0);
	$forum_id = request_var('f', 0);
	$redirect = request_var('redirect', build_url(array('action', 'quickmod')));
	$additional_msg = $success_msg = '';
	$counter = array();

	$s_hidden_fields = build_hidden_fields(array(
		'topic_id_list'	=> $topic_ids,
		'f'				=> $forum_id,
		'action'		=> 'fork',
		'redirect'		=> $redirect)
	);

	if ($to_forum_id)
	{
		$forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');

		if (!sizeof($topic_ids))
		{
			$additional_msg = $user->lang['NO_TOPIC_SELECTED'];
		}
		else if (!sizeof($forum_data))
		{
			$additional_msg = $user->lang['FORUM_NOT_EXIST'];
		}
		else
		{
			$forum_data = $forum_data[$to_forum_id];

			if ($forum_data['forum_type'] != FORUM_POST)
			{
				$additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
			}
			else if (!$auth->acl_get('f_post', $to_forum_id))
			{
				$additional_msg = $user->lang['USER_CANNOT_POST'];
			}
		}
	}
	else if (isset($_POST['confirm']))
	{
		$additional_msg = $user->lang['FORUM_NOT_EXIST'];
	}

	if ($additional_msg)
	{
		$request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
		$request->overwrite('confirm_key', null);
	}

	if (confirm_box(true))
	{
		$topic_data = phpbb_get_topic_data($topic_ids, 'f_post');

		$total_topics = $total_topics_unapproved = $total_topics_softdeleted = 0;
		$total_posts = $total_posts_unapproved = $total_posts_softdeleted = 0;
		$new_topic_id_list = array();

		foreach ($topic_data as $topic_id => $topic_row)
		{
			if (!isset($search_type) && $topic_row['enable_indexing'])
			{
				// Select the search method and do some additional checks to ensure it can actually be utilised
				$search_type = $config['search_type'];

				if (!class_exists($search_type))
				{
					trigger_error('NO_SUCH_SEARCH_MODULE');
				}

				$error = false;
				$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
				$search_mode = 'post';

				if ($error)
				{
					trigger_error($error);
				}
			}
			else if (!isset($search_type) && !$topic_row['enable_indexing'])
			{
				$search_type = false;
			}

			$sql_ary = array(
				'forum_id'					=> (int) $to_forum_id,
				'icon_id'					=> (int) $topic_row['icon_id'],
				'topic_attachment'			=> (int) $topic_row['topic_attachment'],
				'topic_visibility'			=> (int) $topic_row['topic_visibility'],
				'topic_reported'			=> 0,
				'topic_title'				=> (string) $topic_row['topic_title'],
				'topic_poster'				=> (int) $topic_row['topic_poster'],
				'topic_time'				=> (int) $topic_row['topic_time'],
				'topic_posts_approved'		=> (int) $topic_row['topic_posts_approved'],
				'topic_posts_unapproved'	=> (int) $topic_row['topic_posts_unapproved'],
				'topic_posts_softdeleted'	=> (int) $topic_row['topic_posts_softdeleted'],
				'topic_status'				=> (int) $topic_row['topic_status'],
				'topic_type'				=> (int) $topic_row['topic_type'],
				'topic_first_poster_name'	=> (string) $topic_row['topic_first_poster_name'],
				'topic_last_poster_id'		=> (int) $topic_row['topic_last_poster_id'],
				'topic_last_poster_name'	=> (string) $topic_row['topic_last_poster_name'],
				'topic_last_post_time'		=> (int) $topic_row['topic_last_post_time'],
				'topic_last_view_time'		=> (int) $topic_row['topic_last_view_time'],
				'topic_bumped'				=> (int) $topic_row['topic_bumped'],
				'topic_bumper'				=> (int) $topic_row['topic_bumper'],
				'poll_title'				=> (string) $topic_row['poll_title'],
				'poll_start'				=> (int) $topic_row['poll_start'],
				'poll_length'				=> (int) $topic_row['poll_length'],
				'poll_max_options'			=> (int) $topic_row['poll_max_options'],
				'poll_vote_change'			=> (int) $topic_row['poll_vote_change'],
			);

			$db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
			$new_topic_id = $db->sql_nextid();
			$new_topic_id_list[$topic_id] = $new_topic_id;

			switch ($topic_row['topic_visibility'])
			{
				case ITEM_APPROVED:
					$total_topics++;
				break;
				case ITEM_UNAPPROVED:
				case ITEM_REAPPROVE:
					$total_topics_unapproved++;
				break;
				case ITEM_DELETED:
					$total_topics_softdeleted++;
				break;
			}

			if ($topic_row['poll_start'])
			{
				$poll_rows = array();

				$sql = 'SELECT *
					FROM ' . POLL_OPTIONS_TABLE . "
					WHERE topic_id = $topic_id";
				$result = $db->sql_query($sql);

				while ($row = $db->sql_fetchrow($result))
				{
					$sql_ary = array(
						'poll_option_id'	=> (int) $row['poll_option_id'],
						'topic_id'			=> (int) $new_topic_id,
						'poll_option_text'	=> (string) $row['poll_option_text'],
						'poll_option_total'	=> 0
					);

					$db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
				}
				$db->sql_freeresult($result);
			}

			$sql = 'SELECT *
				FROM ' . POSTS_TABLE . "
				WHERE topic_id = $topic_id
				ORDER BY post_time ASC, post_id ASC";
			$result = $db->sql_query($sql);

			$post_rows = array();
			while ($row = $db->sql_fetchrow($result))
			{
				$post_rows[] = $row;
			}
			$db->sql_freeresult($result);

			if (!sizeof($post_rows))
			{
				continue;
			}

			foreach ($post_rows as $row)
			{
				$sql_ary = array(
					'topic_id'			=> (int) $new_topic_id,
					'forum_id'			=> (int) $to_forum_id,
					'poster_id'			=> (int) $row['poster_id'],
					'icon_id'			=> (int) $row['icon_id'],
					'poster_ip'			=> (string) $row['poster_ip'],
					'post_time'			=> (int) $row['post_time'],
					'post_visibility'	=> (int) $row['post_visibility'],
					'post_reported'		=> 0,
					'enable_bbcode'		=> (int) $row['enable_bbcode'],
					'enable_smilies'	=> (int) $row['enable_smilies'],
					'enable_magic_url'	=> (int) $row['enable_magic_url'],
					'enable_sig'		=> (int) $row['enable_sig'],
					'post_username'		=> (string) $row['post_username'],
					'post_subject'		=> (string) $row['post_subject'],
					'post_text'			=> (string) $row['post_text'],
					'post_edit_reason'	=> (string) $row['post_edit_reason'],
					'post_edit_user'	=> (int) $row['post_edit_user'],
					'post_checksum'		=> (string) $row['post_checksum'],
					'post_attachment'	=> (int) $row['post_attachment'],
					'bbcode_bitfield'	=> $row['bbcode_bitfield'],
					'bbcode_uid'		=> (string) $row['bbcode_uid'],
					'post_edit_time'	=> (int) $row['post_edit_time'],
					'post_edit_count'	=> (int) $row['post_edit_count'],
					'post_edit_locked'	=> (int) $row['post_edit_locked'],
					'post_postcount'	=> $row['post_postcount'],
				);
				// Adjust post count only if the post can be incremented to the user counter
				if ($row['post_postcount'])
				{
					if (isset($counter[$row['poster_id']]))
					{
						++$counter[$row['poster_id']];
					}
					else
					{
						$counter[$row['poster_id']] = 1;
					}
				}
				$db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
				$new_post_id = $db->sql_nextid();

				switch ($row['post_visibility'])
				{
					case ITEM_APPROVED:
						$total_posts++;
					break;
					case ITEM_UNAPPROVED:
					case ITEM_REAPPROVE:
						$total_posts_unapproved++;
					break;
					case ITEM_DELETED:
						$total_posts_softdeleted++;
					break;
				}

				// Copy whether the topic is dotted
				markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']);

				if (!empty($search_type))
				{
					$search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id);
					$search_mode = 'reply'; // After one we index replies
				}

				// Copy Attachments
				if ($row['post_attachment'])
				{
					$sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . "
						WHERE post_msg_id = {$row['post_id']}
							AND topic_id = $topic_id
							AND in_message = 0";
					$result = $db->sql_query($sql);

					$sql_ary = array();
					while ($attach_row = $db->sql_fetchrow($result))
					{
						$sql_ary[] = array(
							'post_msg_id'		=> (int) $new_post_id,
							'topic_id'			=> (int) $new_topic_id,
							'in_message'		=> 0,
							'is_orphan'			=> (int) $attach_row['is_orphan'],
							'poster_id'			=> (int) $attach_row['poster_id'],
							'physical_filename'	=> (string) utf8_basename($attach_row['physical_filename']),
							'real_filename'		=> (string) utf8_basename($attach_row['real_filename']),
							'download_count'	=> (int) $attach_row['download_count'],
							'attach_comment'	=> (string) $attach_row['attach_comment'],
							'extension'			=> (string) $attach_row['extension'],
							'mimetype'			=> (string) $attach_row['mimetype'],
							'filesize'			=> (int) $attach_row['filesize'],
							'filetime'			=> (int) $attach_row['filetime'],
							'thumbnail'			=> (int) $attach_row['thumbnail']
						);
					}
					$db->sql_freeresult($result);

					if (sizeof($sql_ary))
					{
						$db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary);
					}
				}
			}

			// Copy topic subscriptions to new topic
			$sql = 'SELECT user_id, notify_status
				FROM ' . TOPICS_WATCH_TABLE . '
				WHERE topic_id = ' . $topic_id;
			$result = $db->sql_query($sql);

			$sql_ary = array();
			while ($row = $db->sql_fetchrow($result))
			{
				$sql_ary[] = array(
					'topic_id'		=> (int) $new_topic_id,
					'user_id'		=> (int) $row['user_id'],
					'notify_status'	=> (int) $row['notify_status'],
				);
			}
			$db->sql_freeresult($result);

			if (sizeof($sql_ary))
			{
				$db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
			}

			// Copy bookmarks to new topic
			$sql = 'SELECT user_id
				FROM ' . BOOKMARKS_TABLE . '
				WHERE topic_id = ' . $topic_id;
			$result = $db->sql_query($sql);

			$sql_ary = array();
			while ($row = $db->sql_fetchrow($result))
			{
				$sql_ary[] = array(
					'topic_id'		=> (int) $new_topic_id,
					'user_id'		=> (int) $row['user_id'],
				);
			}
			$db->sql_freeresult($result);

			if (sizeof($sql_ary))
			{
				$db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
			}
		}

		// Sync new topics, parent forums and board stats
		$sql = 'UPDATE ' . FORUMS_TABLE . '
			SET forum_posts_approved = forum_posts_approved + ' . $total_posts . ',
				forum_posts_unapproved = forum_posts_unapproved + ' . $total_posts_unapproved . ',
				forum_posts_softdeleted = forum_posts_softdeleted + ' . $total_posts_softdeleted . ',
				forum_topics_approved = forum_topics_approved + ' . $total_topics . ',
				forum_topics_unapproved = forum_topics_unapproved + ' . $total_topics_unapproved . ',
				forum_topics_softdeleted = forum_topics_softdeleted + ' . $total_topics_softdeleted . '
			WHERE forum_id = ' . $to_forum_id;
		$db->sql_query($sql);

		if (!empty($counter))
		{
			// Do only one query per user and not a query per post.
			foreach ($counter as $user_id => $count)
			{
				$sql = 'UPDATE ' . USERS_TABLE . '
					SET user_posts = user_posts + ' . (int) $count . '
					WHERE user_id = ' . (int) $user_id;
				$db->sql_query($sql);
			}
		}

		sync('topic', 'topic_id', $new_topic_id_list);
		sync('forum', 'forum_id', $to_forum_id);

		set_config_count('num_topics', sizeof($new_topic_id_list), true);
		set_config_count('num_posts', $total_posts, true);

		foreach ($new_topic_id_list as $topic_id => $new_topic_id)
		{
			add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']);
		}

		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS';
	}
	else
	{
		$template->assign_vars(array(
			'S_FORUM_SELECT'		=> make_forum_select($to_forum_id, false, false, true, true, true),
			'S_CAN_LEAVE_SHADOW'	=> false,
			'ADDITIONAL_MSG'		=> $additional_msg)
		);

		confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
	}

	$redirect = request_var('redirect', "index.$phpEx");
	$redirect = reapply_sid($redirect);

	if (!$success_msg)
	{
		redirect($redirect);
	}
	else
	{
		$redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
		meta_refresh(3, $redirect_url);
		$return_link = sprintf($user->lang['RETURN_FORUM'], '', '');

		if ($forum_id != $to_forum_id)
		{
			$return_link .= '

' . sprintf($user->lang['RETURN_NEW_FORUM'], '', '');
		}

		trigger_error($user->lang[$success_msg] . '

' . $return_link);
	}
}

redpajama_set_name: RedPajamaGithub


text:
Mittal steals a march on Chirac over Arcelor
By Ross Tieman
MAGNATE Lakshmi Mittal appeared to be one step ahead of French President Jacques Chirac today as the battle for European steelmaker Arcelor raged on.
Mittal, who through his Mittal Steel giant has made a hostile £12.8bn bid for Arcelor, held 'constructive' talks with Luxembourg Prime Minister Jean-Claude Juncker, whose tiny nation will play a crucial role in the bid battle.
With a stake of more than 5% in Arcelor, and control over the legal framework in the tiny state where Arcelor is based, the attitude of the Luxembourg government is key to the success of any takeover bid.
Mittal, the British boss of Rotterdambased Mittal Steel, has offered to relocate his company's headquarters to Luxembourg if the bid succeeds. He also needs the Luxembourg government to change its laws to allow a compulsory buy-in of Arcelor minorities if the offer is a success.
Mittal is a day ahead of Chirac in seeking Juncker's favour. Juncker is due to meet Chirac at his Elysée Palace in Paris tomorrow for talks about the bid.
Chirac will be aiming to persuade Juncker to mount every possible obstacle to a takeover of Arcelor, born from the February 2002 merger of the national steel industries of Luxembourg, France and Spain. The talks between the two come amid mounting political hostility and other obstacles in Europe to the bid launched by Mittal on Friday.
After criticism yesterday from French Finance Minister Thierry Breton, European competition commissioner Neelie Kroes waded into the battle today, saying her department was likely to cast a 'severe eye' over the deal for any monopoly concerns. The deal, if it comes off, would make Mittal the world's leading steel company.
Arcelor chief executive and chairman Guy Dollé is '300% hostile' to the bid by Mittal, and both companies are digging in for months of trench warfare conducted through the media.
Dollé, who yesterday declined to give details about Arcelor's defence strategy, today told France's La Tribune that he might look for a foreign white knight.
'An alliance in Europe looks difficult to me regarding competition issues, but is more likely at an international level,' he said.
Dollé says the firm's defences are well-prepared as he claims to have been anticipating an approach from Mittal for months.
Even so, the market is betting on an increased bid from Mittal. Arcelor shares today traded down 53 cents at e29.20, still comfortably ahead of Mittal's cash-and-shares offer that values the target at e28.21 a share.

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: How to retrieve Parent's Id of a triggered child record, inside the trigger - Solved Certification__c(Parent object) --> Exam__c(Child object)
Trigger triggers when Child is updated.
trigger certificationToFailedNew on Exam__c (after update) {
    //List out all the exams associated with the parent of the triggered object. exam record -> ParentID -> other child records which share the same parent
    List<Exam__c> exams = new List<Exam__c>();
    exams = [
        SELECT Id,Exam_id__c, Exam_state__c, Certification__r.Id, Certification__r.Exam_state__c
        FROM Exam__c
        WHERE Exam_state__c in ('Failed') AND Certification__r.Exam_state__c in ('Active') AND Certification__r.id == Certification__c.id IN :trigger.newMap.keySet()
            AND id != id IN :trigger.newMap.keySet()];

I'm trying to filter out child records(Exam__c), which share the same parent(Certification__c) of the triggered child record. Or the siblings of the triggered record (other records which share the same parent)
What needs to be changed in my code @ 'WHERE' to get the required records only.
Working UPDATED CODE
trigger certificationToFailedNew on Exam__c (after update) {

    set<id> certificationId = new set<id>();
    String x;
    String y;

    for(Exam__c e : Trigger.new){
        certificationId.add(e.Certification__c);
        x = e.Exam_id__c;
        y = e.Exam_state__c;
    }

    List<Exam__c> exams = new List<Exam__c>();
    exams = [
        SELECT Id, Exam_id__c, Exam_state__c, Certification__r.Id, Certification__r.Exam_state__c
        FROM Exam__c
        WHERE Exam_state__c in ('Failed') AND Certification__r.Exam_state__c in ('Active')
            AND Id NOT IN :trigger.newMap.keySet() AND Certification__r.Id IN :certificationId
            AND Exam_id__c = :x AND Exam_state__c = :y];
}

A: This is not valid SOQL syntax.
    WHERE Exam_state__c in ('Failed') AND Certification__r.Exam_state__c in ('Active')
        AND Certification__r.id == Certification__c.id IN :trigger.newMap.keySet()
        AND id != id IN :trigger.newMap.keySet()];

Additionally, the values in Trigger.newMap().keySet() are Exam__c Ids. You cannot filter Certification__c Ids against them.
Instead, you need to loop over the trigger objects to accumulate a Set<Id> of the Ids of the parent records whose other children you wish to filter.
Then, both of your AND clauses are replaced by
Certification__c NOT IN :setOfParents

That will exclude all siblings of the current records (as well as the current records themselves), as it sounds like you want. If you wanted to get only siblings, you'd reverse the Boolean and add another clause:
    Certification__c IN :setOfParents AND id NOT IN :trigger.newMap.keySet()

A: To get the parent record id first you need to iterate over the trigger and add the parant id in one set.
trigger certificationToFailedNew on Exam__c (after update) {
    set<id> certificationId = new set<id>();
    for(Exam__c e : Trigger.new){
        certificationId.add(e.Certification__c);
    }
    List<Exam__c> exams = [SELECT Id,Exam_id__c, Exam_state__c,Certification__r.Id,
                           Certification__r.Exam_state__c FROM Exam__c
                           WHERE Exam_state__c = 'Failed' AND Certification__r.Exam_state__c = 'Active'
                           AND Certification__r.id  IN :certificationId AND id NOT IN :trigger.newMap.keySet()];
}

redpajama_set_name: RedPajamaStackExchange


Many backpackers setting out on their first trip tend to have questions that revolve around the same few concerns, many of which end up in my inbox. Traveling for the first time can bring up all kinds of anxieties about handing the basics abroad that you've comfortably gotten down pat at home.
As with many travel questions it's good to get down to specifics and while these answers are certainly not comprehensive, they should help you get off to a good start.
1. What Is It Like Traveling Solo?
Traveling for the first time alone can seem like taking a trip into disaster before you ever hit the road. There are many advantages to traveling solo, ways to ease into it, and the advice of experienced travelers from all walks of life to alleviate some of your anxiety.
The truth is that when traveling, you're often not alone and being without others eventually becomes a great motivator for getting social.
2. How Will I Overcome Language Barriers?
Much of that depends on your mother-tongue but assuming you know enough basic English to read this post you're off to a good start. Although the notion is controversial, English is the universal language and widely spoken in enough key places where (relatively) clear communication is necessary. Airports, hotels, and ordering food from most menus will be straightforward.
To help yourself out with or without English though, you can learn these 4 word combinations for free using these resources, language social networks, or get digital with one of several nifty mobile phone apps like Word Lens.
3. How Can I Save Money And Travel Longer?
Most backpackers and budget travelers have at least heard of hostels (in case you haven't) but there are many more ways to save before and during your trip. Although it seems counter-intuitive, flying more, on multi-city flights can often be less expensive than booking a simple round-trip fare. Where you go makes a big difference too so figure out the cheapest places to travel with your currency before you lose them.
Ask One Of The World's Largest Providers: When Do I Really Need To Get Travel Insurance?
Finally, if you've got the time, travel slower to see more and use a simple travel budget to track your spending.
4. Where Should I Go?
I've gone into resolving not knowing where you want to go before at length but the gist is to go where you want based on why you travel.
Don't limit yourself initially, life is short so go visit the places you've always wanted to.
5. Should I Get Travel Insurance?
The answer depends on where you're going and what you want to insure. Medical insurance and coverage for your valuables (including cash and passports) are the main two reasons people consider travel insurance.
(I'll be covering this topic in a more detail post in a few weeks.) There are several big caveats to coverage so be sure to read any policy carefully and check if emergency health care is covered by the government of the countries you'll be visiting.
Almost always entwined in backpacking questions are how to choose the right backpack, pack light, and cope with being far away from home. The fortunate thing is that you'll find plenty of opinions online about all of your first-timer questions that manifest themselves in various ways after your first jaunt. That's one of the beauties of travel, that these questions have endless answers and discovering what works in each place keep the journey interesting.
If my memory is right, Michael Hodson (http://www.goseewrite.com) first brought it to my attention. Pretty cool to see it in action – they're working on getting more languages released *and* an Android plus Blackberry version. Hopefully soon!
I'm looking forward to your post on travel insurance. As a general rule I'm anti-insurance because I think insurance companies are the devil, that said, that's not so useful if you're hurt!
I'm always trying to save money but skipping the insurance maybe isn't the best option. Do you have tips about what countries will treat you regardless? I think for the most part Italy will treat anyone for emergency or minor cases (just not surgeries and stuff). I could be wrong since I've never been to the hospital (know on wood!!).
Many travelers seem to have a love-hate relationship with travel insurance. The experiences people have had with them really vary widely but (knock on wood too!) I've never had a serious injury or something similar to deal with.
I need to do some digging (and will be sure to for the upcoming post) but off-hand most Western European countries, New Zealand, and maybe Australia; though I wouldn't be surprised to find many more countries in other parts of the world where emergency services would be covered.
I use travel insurance and I've been robbed twice so it's paid for itself 🙂 Although now that I am planning on staying longer I wonder about it as hospitals etc are so cheap here in South America and the private ones provide great care.
What type of coverage did you go with – was it easy to be reimbursed?
For $5 that's not bad at all! Which coverage/provider did you go with?
The insurance debate is an interesting one. By far the biggest issue with not having insurance is if you get seriously hurt or ill. It may be unlikely but it can be worth your life if it occurs. If the country you are visiting does not have some sense of emergency care without hefty payments (that you may not be able to readily make) then you are in serious trouble. A fair chunk of Asia, Africa and the Americas (and especially the USA) are not good in this regard and that cost can run into $100000s. This is when insurance becomes valuable.
A very good point – it's not fun to think about but something that many (including myself) don't consider often enough.
My travel insurance lapsed when I entered the US and I hadn't renewed a US based policy. A quick trip to the doctor's office to have some blood work done for a visa cost me a cool $300 bucks.
A serious injury can break your longterm budget and you're foolish to travel without it!
It *is* expensive without any kind of insurance – in the US the bare minimum for a visit has got to be around $100.
Have you couchsurfed, Anil? I've done it twice (Once in London and once in Hamburg) and I've been able to meet really cool people who is interested in showing you around and share some cool tips. Our couch "host" from Hamburg was particularly helpful and became a very good friend afterwards. That'd be another way to save some money.
I haven't unfortunately; mostly because I spend so much time online working at weird hours, I'd make a terrible guest. Certainly a good way to save and add experiences to a trip though.
Wow, great write up packed with stuff good to know here. I look forward to read more about your advices around travel insurances, THAT is a tough subject!
haha, yes, thank you. It is certainly a topic I'm finding that has layers upon layers!
Good back to basic points mate. As for the travel insurance debate, most people get it at home for their car or their house so why not insurance yourself and your belongings while abroad? Aren't you worth more than both of those two items combined.
Good point, especially about the medical coverage.
Wonderful post Anil. It answers many of the questions I had before my first time out on the road. There seems to be a lot of talk lately about whether travel insurance is worthwhile or not, crazy! I'll certainly be investing in some!
Number 3 is the question we get the most from other travelers when we tell them we've been on the road for the last 2 years. It's always a hard one to answer because it varies depending on what type of traveler you are. Budget backpacking has so may different interpretations!
Yes, the costs depend on many factors but generally the more flexible your travel plans, the less expensive your options.
I have a question. Where is the backpacking???


text:
Manchester United v Tottenham – Premier League
Manchester United v Tottenham - Premier League Betting Preview and Prediction
Manchester United v Tottenham – Premier League Betting Preview and Prediction
Manchester United and Tottenham are set to clash on Wednesday, December 4, in what will be one of the most anticipated fixtures of EPL's round 15. Both sides have had their ups and downs this term and neither have as of yet justified their tag of being one of the "Big Six". They will, however, have a perfect chance to do just that at Old Trafford, where the struggling Red Devils will play host to the "new and improved" Spurs.
Jose Mourinho's magic touch
People talk about Jose Mourinho and his so-called "magic touch", which can take any club from being an average team to being champions. And while the Portuguese mastermind failed to live up to the expectations in recent years, his arrival at Tottenham ahead of round 13 helped the Spurs improve even so slightly. As it stands now, Spurs are sitting at sixth place in the league with a 5-5-4 record and 20 points next to their name, which sets them one point behind fifth-placed Crystal Palace, meaning a win here would catapult Tottenham into the top five. In regards to Tottenham's last five fixtures, the Spurs lost to Liverpool (1:2), drew with Everton (1:1) and Sheffield United and ever since they signed Mourinho, Spurs won their next two against West Ham (2:3) and Bournemouth (3:2).
Tottenham's bout with Bournemouth ended with Spurs claiming all three points, yet we can't praise them too much for conceding two goals on that night. Tottenham opened the scoring in 21st minute, to which they added two more in 50th and 69th minute. Being three goals up, the hosts clearly let their guard down and conceded twice in 73rd and 90'+6 to win the game with minimal margin. While Spurs never really came close to losing that fixture, it's surprising to see how poorly they perform in the defense, considering they also conceded two goals against West Ham (3:2) in the previous round.
Manchester United meet with their former head coach
To say the Red Devils haven't had a strong start of the season would at this point be an understatement. As a team that entered the 2019/20 season with high ambitions to contest top spots, Man United fell flat relatively early and are now sitting mid-table with a 4-6-4 record and 18 points, which sets them eight points adrift from the top four and 22 points short of reaching Liverpool. It's safe to say Ole Gunnar Solskjaer and his men can throw their ambitions to claim the title right out the window, yet there is still a very solid chance they can clinch a European league spot. Looking back at their last five fixtures, United defeated Norwich (3:1), lost to Bournemouth (0:1), defeated Brighton (3:1) and drew their next two against Sheffield Utd (3:3) and Aston Villa (2:2) this past weekend.
In Man United's clash with Villa (2:2), Man United produced 16 goal attempts and six shots on goal with 62% ball possession while Aston Villa had to settle with three shots on goal with nine-goal attempts. It would be safe to say United were the more dangerous team in the attack, yet that did not stop them from conceding twice. Their defense has been a major issue seeing how they conceded at least once in all of their last five fixtures. On average United conceded 1.6 goals in their last five and 1 goal in their last five home games.
Scott McTominay and Nemanja Matic are both listed as questionable for the upcoming fixture. Adding to the list, Eric Bailly, Timothy Fosu-Mensah and Diogo Dalot will also remain sidelined until they fully recover from their injuries. Tottenham on the other side have no new injury concerns, meaning they will remain without Lamela, Davies and Vorm. Lloris is a long-term absentee, who should not return to the pitch until 2020.
Looking at Tottenham, we can't really say they significantly improved under the new coach, but with two wins behind them, morale and confidence are surely high, which, we believe will sooner or later result in stronger performances. The Red Devils on the other side have nothing to show for. Their results are mediocre at most and we can't really say their morale is high by any means. They have had a tough start of the season and looking at their recent results, we don't believe their form has improved even so slightly.
All things considered, Tottenham come off as a stronger team here. Not only have they shown more in recent weeks, but they also boast with a stronger team and are traveling to Manchester with high spirits. While Man United haven't lost a single home match since the end of August, they also failed to defeat any strong team in front of their own fans, which leads us to believe they won't have an easy time against Tottenham this Wednesday. Jose Moutinho's return back to Old Trafford should add some flare to the game and will inspire some much-needed motivation for Spurs to win and get themselves into the top five.
Prediction: Tottenham +0.00 Asian Handicap
Odds: 2.01 Matchbook
Tags: England, Manchester United, Tottenham, UK
Previous Wolverhampton v West Ham – Premier League
Next Melbourne City v Perth Glory – A-League


Gillian Cullen (b. 1983), Healing, 2018. © Gillian Cullen. Photo © National Gallery of Ireland.
"The common thread that unites my work as a full-time illustrator and fine artist is my desire to capture the essence of the subject matter; to enhance some intangible, ephemeral quality that may not be always be noticed. For me, detail is everything. I hone in on particular elements, whether it be a subject's hair or the petal of a flower, and map out their intricacies. I invite the viewer to look deeply at the little details that exist all around us, and to take a moment to appreciate their beauty.
These areas of detail and subtle textures are incorporated into my portrait Healing. It portrays my husband Macdara, who, ten years ago, fell 100 feet down a cliff in a climbing accident. He suffered numerous injuries and fractures, including a broken back. I drew this portrait in honour of him; in celebration of his incredible strength and personal journey. I wanted to depict how beautiful, strong and incredible the human body is – every freckle, bone and scar. This drawing tells a story of healing and strength, both physical and emotional, yet also evokes a feeling of gentleness and vulnerability."
Gillian Cullen, a fine artist from Meath, specialises in detailed pencil drawings. She draws inspiration from all elements of nature. This love of nature is a recurring theme in her work. A graduate of Environmental Science at Trinity College, Dublin, she has a deep respect for the natural environment. Gillian has taken part in numerous exhibitions, including the annual exhibitions in the Royal Hibernian Academy and the Royal Ulster Academy. In 2016 she was awarded the Prize for Drawing and the Rowel Friers prize, by the RUA. Her work features in many private and public collections.


text:
Q: Display content then manually refresh in PyGTK (2) Having trouble understanding how to manually (I'm not using timeouts at this stage) refresh a window, or part of a window in PyGTK, version 2.
I want to display some information, in this example, a selection of output from the "df" command, and then be able to manually refresh the window, using a "refresh" button. I've looked at various examples and the PyGTK tutorial, but the exact place to put the refresh code escapes me. Tried using queue_draw in the "freedisk" function, in another function within that, in the "main" loop, without success.
I appreciate GTK3 is the preferred version these days, but I'd rather get this right, before updating.
The code for "freedisk":
#!/usr/bin/env python

import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk

def yield_lines(data):
    for line in data.split("\n"):
        yield line

def line_to_list(line):
    return re.sub(" +", " ", line).split()

def remov_percent(col):
    return re.sub("%", "", col)

class freedisk:
    def getdiskfree(self):
        diskfreecmd = ['/usr/bin/df', '-hlT', '-x', 'tmpfs']
        diskfree = subprocess.Popen(diskfreecmd, stdout=subprocess.PIPE).communicate()[0]
        return diskfree

    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False

    def destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.connect("delete_event", self.delete_event)

        box1 = gtk.VBox(False, 10)
        box1a = gtk.HBox(False, 0)
        box2 = gtk.VBox(False, 10)
        box3 = gtk.HBox(False, 0)

        frame_1 = gtk.Frame()

        window.add(box1)

        diskfreedata = self.getdiskfree()
        diskfreedata = diskfreedata.replace("Mounted on", "Mounted_on")

        lines = yield_lines(diskfreedata)

        headers = line_to_list(lines.next())

        columns = [list() for i in range(len(headers))]

        for i,h in enumerate(headers):
            columns[i].append(h)

        for line in lines:
            for i,l in enumerate(line_to_list(line)):
                columns[i].append(l)

        j=0
        for i in columns[0]:
            j += 1

        title = gtk.Label('Disk usage and free space')
        box1.pack_start(title, False, False, 10)
        box1.pack_start(box1a, True, True, 0)
        box1a.pack_start(frame_1, True, True, 20)
        frame_1.add(box2)

        ucdiskfreedata = unicode(diskfreedata)

        label = gtk.Label(diskfreedata)
        label.set_line_wrap(False)
        label.set_max_width_chars(80)
        label.modify_font(pango.FontDescription("monospace"))

        box_sp1 = gtk.HBox(False, 0)
        box_sp2 = gtk.HBox(False, 0)

        refresh_button = gtk.Button("Refresh")

        close_button = gtk.Button("Close")
        close_button.connect("clicked", self.delete_event, "quit")

        mntlabel = [list() for i in range(j)]
        sizelabel = [list() for i in range(j)]
        progbar = [list() for i in range(j)]
        freelabel = [list() for i in range(j)]
        perlabel = [list() for i in range(j)]

        rows = [list() for i in range(j)]

        box2.pack_start(box_sp1, False, False, 0)

        rows[0] = gtk.HBox(True, 0)
        box2.pack_start(rows[0], False, False, 5)

        mntlabel[0] = gtk.Label(columns[6][0])
        freelabel[0] = gtk.Label(columns[4][0])
        sizelabel[0] = gtk.Label(columns[2][0])
        blank = gtk.Label(columns[5][0])
        rows[0].pack_start(mntlabel[0], False, False, 0)
        rows[0].pack_start(sizelabel[0], False, False, 0)
        rows[0].pack_start(blank, False, False, 0)
        rows[0].pack_start(freelabel[0], False, False, 0)

        for i in range(1,j):
            x = remov_percent(columns[5][i])
            y = decimal.Decimal(x) /  decimal.Decimal('100')
            mntlabel[i] = gtk.Label(columns[6][i])
            mntlabel[i].set_justify(gtk.JUSTIFY_RIGHT)
            freelabel[i] = gtk.Label(columns[4][i])
            sizelabel[i] = gtk.Label(columns[2][i])
            progbar[i] = gtk.ProgressBar()
            gtk.ProgressBar.set_fraction(progbar[i], y)
            progbar[i].set_text(str(columns[5][i]))
            rows[i] = gtk.HBox(True, 0)
            rows[i].pack_start(mntlabel[i], False, False, 0)
            rows[i].pack_start(sizelabel[i], False, False, 0)
            rows[i].pack_start(progbar[i], False, False, 0)
            rows[i].pack_start(freelabel[i], False, False, 0)
            box2.pack_start(rows[i], False, False, 0)

            box2.pack_start(box_sp2, False, False, 10)

            box3.pack_end(close_button, False, False, 20)
            box3.pack_end(refresh_button, False, False, 20)
            box1.pack_start(box3, False, False, 10)

            box1.show()
            box1a.show()
            box2.show()
            box_sp1.show()
            box_sp2.show()
            frame_1.show()
            title.show()

            mntlabel[0].show()
            blank.show()
            for i in range(0, j):
               rows[i].show()
               mntlabel[i].show()
               sizelabel[i].show()
               freelabel[i].show()
            for i in range(1,j):
                progbar[i].show()

            refresh_button.show()
            close_button.show()
            box3.show()
            window.show()

def main():
    gtk.main()

if __name__ == "__main__":
    freedisk()
    main()

Edited (24.10.17) to add a simpler example then, just show the outputs of the command "ls":
#!/usr/bin/env python

import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk

class PyGlist:

    def getlisting(self):
        listingcmd = ['ls', '-1']
        listing = subprocess.Popen(listingcmd, stdout=subprocess.PIPE).communicate()[0]
        return listing

    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False

    def destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        # nothing here
        return None

    def processlisting(self):
        listingdata = self.getlisting()
        print (listingdata)
        loclabel = gtk.Label(listingdata)
        loclabel.set_line_wrap(False)
        loclabel.set_max_width_chars(80)
        loclabel.modify_font(pango.FontDescription("monospace"))
        return loclabel

    def refresh(self, widget, data):
        widget = self.processlisting()
        widget.queue_draw()
        return

    def main(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.connect("delete_event", self.delete_event)

        box1 = gtk.VBox(False, 10)
        box1a = gtk.HBox(False, 0)
        box2 = gtk.VBox(False, 10)
        box3 = gtk.HBox(False, 0)
        frame_1 = gtk.Frame()
        window.add(box1)

        title = gtk.Label('Listing')
        box1.pack_start(title, False, False, 10)
        box1.pack_start(box1a, True, True, 0)
        box1a.pack_start(frame_1, True, True, 20)
        frame_1.add(box2)

        label = self.processlisting()

        box_sp1 = gtk.HBox(False, 0)
        box_sp2 = gtk.HBox(False, 0)

        box2.pack_start(label, False, False, 0)

        refresh_button = gtk.Button("Refresh")
        refresh_button.connect("clicked", self.refresh, label)

        close_button = gtk.Button("Close")
        close_button.connect("clicked", self.delete_event, "quit")

        box3.pack_end(close_button, False, False, 20)
        box3.pack_end(refresh_button, False, False, 20)
        box1.pack_start(box3, False, False, 10)

        box1.show()
        box1a.show()
        label.show()
        box2.show()
        box_sp1.show()
        box_sp2.show()
        frame_1.show()
        title.show()

        refresh_button.show()
        close_button.show()
        box3.show()
        window.show()

        gtk.main()

if __name__ == "__main__":
    pyglist =PyGlist()
    pyglist.main()

I'm getting closer to understanding now what's happening; I'm just slow at picking up concepts.

A: That's because in processlisting you create a new label each time, but you never add it to the widget tree, so it is never displayed. What you should do is reuse the label you already added in the user interface, and modify that one. Just pass it as a parameter when you connect to the clicked signal of the refresh button.
Also, no need to call show on each widget, just call show_all on the toplevel gtk window.
Finally, you only need to connect to the destroy signal to call gtk_main_quit. delete-event is when you want to intercept the user wanting to close the window and want to change the default behavior.
#!/usr/bin/env python

import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk

class PyGlist:

    def getlisting(self):
        listingcmd = ['ls', '-1']
        listing = subprocess.Popen(listingcmd, stdout=subprocess.PIPE).communicate()[0]
        print listing
        return listing

    def on_destroy(self, widget, data=None):
        gtk.main_quit()

    def refresh(self, refresh_button, label):
        label.set_text(self.getlisting())

    def main(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.connect("destroy", self.on_destroy)

        box1 = gtk.VBox(False, 10)
        box1a = gtk.HBox(False, 0)
        box2 = gtk.VBox(False, 10)
        box3 = gtk.HBox(False, 0)
        frame_1 = gtk.Frame()
        window.add(box1)

        title = gtk.Label('Listing')
        box1.pack_start(title, False, False, 10)
        box1.pack_start(box1a, True, True, 0)
        box1a.pack_start(frame_1, True, True, 20)
        frame_1.add(box2)

        label = gtk.Label(self.getlisting())
        label.set_line_wrap(False)
        label.set_max_width_chars(80)
        label.modify_font(pango.FontDescription("monospace"))

        box_sp1 = gtk.HBox(False, 0)
        box_sp2 = gtk.HBox(False, 0)

        box2.pack_start(label, False, False, 0)

        refresh_button = gtk.Button("Refresh")
        refresh_button.connect("clicked", self.refresh, label)

        close_button = gtk.Button("Close")
        close_button.connect("clicked", self.on_destroy)

        box3.pack_end(close_button, False, False, 20)
        box3.pack_end(refresh_button, False, False, 20)
        box1.pack_start(box3, False, False, 10)

        window.show_all()

        gtk.main()

if __name__ == "__main__":
    pyglist =PyGlist()
    pyglist.main()

A: I've cracked it, finally. Thanks to the help of the posters above.
The simpler example showed me where I was overcomplicating things.
The original program "freedisk" I finally got working, by moving more code into a separate function which made it easier to see what was happening.
Basically, the aim was to take the output of "df" and tweak it slightly with a hybrid text and graphical display.
Aside from any formatting boxes, titles, etc, there would be a VBox container with one HBox per line of "df" output, recreating some of the columnar output in text form, but with one column of progressbars.
The data translation and creation of rows I moved into a separate function.
This would be called initially, and then each time a "refresh" button were pressed.
Any existing rows inside the vertical box would be destroyed before the data was recalculated and then re-output. And this was where the final piece of the puzzle fell into place.
After destroying the widgets, and replacing them, I'd not realised they had to be re-"show"n. Adding one final line "widget.show_all()" solved the problem.


Abstract Kesha Hd Wallpaper 1440 900 was posted in December 29, 2013 at 4:55 pm. Abstract Kesha Hd Wallpaper 1440 900 has been viewed by 1085 users. If you want to use this wallpaper, please click the download link below to go to the download page. Right click the image and select "Save Image As" to download the Abstract Kesha Hd Wallpaper 1440 900 to your computer or select "Set Desktop Background As" if your browser has that capability.


1-Lil' Monsters 2-Construction Trucks 3-Polka Dots 4-Blue Soccer 5-Trucks, Cars & Planes 6-Blue Baseball 7-Krazy Kats! 8-Butterflies 9-Symmetrical Squares 10-Blue Skys 11-Puppies 12-Spring Garden 13-Red Baseball 14-Dinos! 15-Shark Attack 16-Monster Madness 17-Camo 18-Black Soccer 19-Flames 20-Zoo Buddies!
13-Red Baseball 14-Dinos 15- Shark Attack!


Guzman, C. C. de & J. S. Siemonsma, eds. 1999. Spices (Pl Res SEAs) 13:170-172.
National Germplasm Resources Laboratory, Beltsville, Maryland. URL: https://npgsweb.ars-grin.gov/gringlobal/taxonomydetail.aspx?id=407755. Accessed 22 April 2019.


Faster, stronger, and more effective, this NanoEnhanced Hemp Oil far outpaces tinctures. The advanced technology behind this ground-breaking liquid delivery system makes for precise dosing and immediate effect.
Liposomal delivery brings the power of intravenous therapy into convenient oral delivery. Typical absorption of Cannabidiol oil is poor, with only about 10% uptake in the GI tract. Liposomal encapsulation of compounds similar to Cannabidiol have been shown to increase absorbtion five-to tenfold. This pharmaceutical-grade LIPOSOMAL Cannabidiol outperforms other products thanks to smaller, more stable, single-layer spheres made from the highest-grade ingredients available.
This pharmaceutical-grade NanoEnhanced Hemp Oil outperforms the leading pharma brand thanks to smaller, more stable, single-layer spheres made from the highest grade ingredients available, which has shown to increase absorption by 5-10 fold. In a test against cannabinoid uptake results, published by a leading pharma brand, this liposomal hemp oil was absorbed in the blood in amounts three times as great at half the dose. In fact, phospholipid therapy, using both injectable forms and oral forms, has long and solid clinical history.
The liposomes bring the power of intravenous therapy into convenient oral delivery. Unlike other liposomes on the market that use low grades of phospholipids, which breakdown and do not deliver compounds effectively, our high-phosphatidylcholine phospholipid mixes are smaller, more stable, and tightly distributed, single-layer spheres. The vesicles are small enough to begin absorption as soon as they hit your mouth; it's lightning fast!
The science behind why Phytocannabinoid Diol rich Hemp Oil is proving to be so effective is based on the human Endocannabinoid System. This system is part of our immune system and when it is activated by taking Cannabinoids, studies have shown the body has a better ability to fight, resist, and assist in repairing the body and mind.
From infants to kids and adults to the old of age, studies have shown hemp oil to be safe to use, and its benefits well documented. As with any supplement, we highly recommend you consult your physician or a medical professional to see if hemp oil is right for you.
Tightly controlled small sizing, verified by Laser Dynamic Light Scattering on each batch; Pleasant taste, suitable for intra-buccal delivery; Precise pump delivery; Easy to disperse in water when desired; Intramural delivery for best systemic availability; Easy to dispense and take directly from bottle.
This NanoEnhanced Hemp Oil is made with the highest quality hemp strains grown to the strictest organic standards that we can find. We use a super-critical whole plant extraction process that yields all of the synergistic cannabinoids, terpenoids and other natural compounds of the original plant. This Hemp Oil is nonpsychoactive and safe for daily consumption.
This website is owned by Annie's Apothecary, independent affiliate of PrimeMyBody and is not endorsed by PrimeMyBody. Any opinions expressed on this website should not be construed as a representation of PrimeMyBody.


text:
Sherman Alexie Charters Bus to Tour Seattle Bookstores on Indies First
In celebration of the fourth annual Indies First, author Sherman Alexie has invited Seattle city council members and local reporters, musicians, and fellow authors to join him on a tour bus to travel to three indie bookstores in the Seattle area on November 26.
"I want to honor independent bookstores in the largest, silliest, most fun way possible," said Alexie, "with snacks and coffee and a party bus filled with poets, novelists, playwrights, cartoonists, essayists, journalists, and graphic artists."
During the tour, Alexie and two dozen companions, who will be adorned with festive blue-and-white Indies First scarves from Ruffneck, will stop at Third Place Books, University Book Store, and The Elliott Bay Book Company, where they will spend time shopping and interacting with customers.
Among those joining Alexie on the tour will be authors Deb Caletti, Jessixa Bagley, Nancy Rawles, and Sarah Glidden; musician Gabriel Teodros; and reporters Nicole Brodeur of the Seattle Times and Paul Constant of the Seattle Review of Books.
Each person on the tour will suggest a book they think would make a great gift; the recommendations will be compiled in a list and shared with the bookstores on the tour. Alexie has chosen Cosmopolitanism: Ethics in a World of Strangers by Kwame Anthony Appiah (W.W. Norton) and Wave by Sonali Deraniyagala (Vintage).
Indies First was started by Alexie in 2013, when he called on authors to show their support for independent booksellers by signing up to work at their favorite indie bookstore on Small Business Saturday, the Saturday after Thanksgiving.
Other authors who led the campaign in the years that followed include this year's spokesperson, Lena Dunham, as well as Kate DiCamillo, Neil Gaiman and Amanda Palmer, Daniel Handler (aka Lemony Snicket), and Cheryl Strayed.
Follow Indies First on Facebook and Twitter for up-to-the-minute news about the event, and share Indies First updates with customers using the hashtag #IndiesFirst. Questions about Indies First should be directed to indiesfirst@bookweb.org.


Get ready to build something big with Transformers Generations Power of the Primes Legends!
Each individually packaged figure has two amazing modes, going from vehicle to 4-inch heroic Autobot or evil Decepticon.
Some can interact with the Prime Masters as pilots!
Each figure includes figure, collector card, and instructions.


text:
Global Warmist, Heal Thyself
Townhall Magazine
Posted: Jul 10, 2014 8:35 AM
Editor's Note: This column originally appeared in the July issue of Townhall Magazine.
The global warming fear mongers are at it again.
But twice recently they've been caught in the act. Not only are they lying, they're so desperate that they're starting to look ridiculous.
"Three years of observations show that the Antarctic ice sheet is now losing 159 billion tonnes of ice each year—twice as much as when it was last surveyed," reports the U.K.'s University of Leeds. "A team of scientists from the UK Centre for Polar Observation and Modelling, led by researchers at the University of Leeds, have produced the first complete assessment of Antarctic ice sheet elevation change."
Like you, I'm suspicious of any group of scientists that live in a "kingdom" that can't even practice general dentistry correctly.
Or health care.
Or, apparently, math.
The press release goes on to say that the ice melt could contribute to an increase in "global sea levels by 0.45 millimetres each year alone."
That figure is really not that impressive, especially when you understand that it means about a 2 inch rise over 100 years.
But what's really impressive about the figure is that it's just not true.
From climate website Watts Up With That?:
Sanity Check:
From Climatesanity: Conversion factors for ice and water mass and volume
If one cubic kilometer of water (i.e., one gigatonne of water) is spread evenly over the entire 361 million square kilometers, the thickness of the new layer of water will be given by:
1km3 /361x106km2 =2.78x10-6 meters = 2.78 microns.
Or, in terms of gigatonnes:
1Gt x (1km3/Gt) /361x106km2 = 2.78 x 10-6 meters = 2.78 microns / Gt
That is, one cubic kilometer of water (i.e., one gigatonne of water) will add less than 3 millionths of a meter to the oceans!
From the press release, we are seeing about 159 billion tons/year of ice convert- ed to meltwater (unless it sublimates), so the effect on sea level would be 159/1000 or 0.159 x 3 millionths of a meter, or 0.477 millionths of meter of sea level rise per year from this.
I'll leave it to the highly trained scientist at the University of Leeds to convert the millionths of a meter into inches for you. But it's my strong recommendation you not allow them to do your taxes.
But hold on there, pardners, we're not done yet.
We can at least agree, as we've been told for years, that 97 percent of climate scientists agree that global warming is caused by man, right? I mean, that's indisputable.
Then why are the scientists so eager to hide their data?
"The University of Queensland in Australia is taking legal action to block the release of data used by one of its scientists to come up with the oft-quoted statistic that 97 percent of climate scientists agree that mankind is causing global warming," reports the Daily Caller.
It seems a blogger has gotten ahold of the primary data used in the research, and the data suggests that far from having a consensus that global warming is entirely manmade, scientists are still skeptical.
This is not the first time that critics have questioned the results of that study. A catalog of studies in a report pub- lished by Science & Education shows that a little more than one quarter of 1 percent of all studies conclude that glob- al warming is entirely man-made, says the Daily Caller.
"In fact, Cook's paper provides the clearest available statistical evidence that there is scarcely any explicit support among scientists for the consensus that the IPCC, politicians, bureaucrats, academics and the media have so long and so falsely proclaimed," says statistician Dr. William Briggs in a press release accompanying the report. "That was not the outcome Cook had hoped for, and it was not the outcome he had stated in his paper, but it was the outcome he had really found."
And here's what I know about people who lie: they are liars.
Some people lie for profit, some people lie for power, and some people just lie for the fun of it. I suspect in the global warming crowd there's a small group of people who are liars, with the large admixture of people who are just believers.
But among believers in history, even Thomas had doubts.
It is up to the faithful, the believers, the ideologues, to cast out the liars.
The people who should be offended by these ploys, stratagems, and sophistications are those who believe deeply in the science of global warming.
But until they cast out the liars, their faith counts for nothing.
After all, it is just another lie. •
John Ransom is the editor of TownhallFinance.com
Meet The WV Lawmaker Talking About Annexing VA's 2A Sanctuary Counties


text:
Alumni, donors and friends
Lifetime service award
Marietta (Landis '65) Sawatzky
Richard Ramseyer '57
Judy (Mull '63) Pierman
William Herr '61
Missionary in Taiwan
Bluffton '65
Major: Elementary education
2011 Lifetime Service Award
The award recognizes an individual who, inspired by personal faith to make a difference in the lives of others, has dedicated his or her life to heartfelt service to people, community or church.
Committed to the call
As she was nearing graduation from Bluffton with her education degree, Marietta Landis received a letter from Hugh and Janet Sprunger, who were Mennonite missionaries in Taiwan.
The Sprungers, with whom Landis had corresponded since they met at a church camp in Pennsylvania, wrote that a teacher was needed for elementary-age missionary children in a one-room school setting. "We think you're the person for that," they added—words that the ensuing 46 years have borne out.
On July 31, 1965, scarcely two months after graduation, she was on her way to Taiwan, where she pursued a teaching ministry that's been "the heart of what I've done," she says.
Teaching on Taiwan
She taught at Hualien Christian School on the island's east coast during her initial three-year assignment with the then-General Conference Mennonite Church Board of Christian Service. Having met and married Sheldon Sawatzky in Taiwan, she then settled into the role of a pastor's wife while they began raising their three children.
She did a little substitute teaching during that time, and later taught a ninth-grade Bible class at the Christian international school her children attended. But "my niche," Marietta says, was the English-language classes, including Bible classes, she taught as a church-outreach program.
Teaching Bible stories—and working in everyday English material—at a public middle school on Saturday afternoons for two semesters was particularly rewarding, she recalls. The school promoted the program as a way for its students to gain more familiarity with English, she points out, saying there's still "a strong drive for English learning" on Taiwan.
Another high point, she notes, was teaching an English/Bible class to middle school teachers, a banker and other professionals from 2007-09 and seeing adult students meet the challenge of grasping biblical material that was new to most of them.
Help along the way
"There were always new challenges" in teaching, says Marietta, but the Taiwanese people have been welcoming and she and her husband's co-workers have always been supportive. That included mentorship by their predecessors on the island, who helped with the Sawatzkys' adjustment to the culture and the Taiwanese dialect. Learning the language was difficult, she concedes, but since most foreigners speak Mandarin Chinese, the locals' ears "perk up" when they hear their dialect, allowing closer contacts to form.
Still serving
The Sawatzkys retired from the Mennonite Mission Network (MMN) in 2009, but the national Taiwan Mennonite Church invited Sheldon to work for the church in the leadership development area. So, until September 2012, they remain as MMN associates on the island, where they have actually lived for about 31 years. That excludes periodic furloughs and other time spent back in the United States for additional schooling and administrative jobs, including, in Marietta's case, 10 years as part-time MMN Prayer Network facilitator.
Over the years, they've witnessed considerable change on Taiwan—where they once saw water buffaloes and now see high-speed rail transportation, Marietta says—but not a change in their relationship with the island.
Keeping them in the mission field there was "our commitment to God's call, and that seemed to be directed to Taiwan," she says.