<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

define ('HORNET_DEV', ($_SERVER['DOCUMENT_ROOT'] == 'C:/xampp/xampp/Web'));//needed in copied section

function q ($stuff, $label = '') {
	if ($label != '') { $label = "[ $label ]
"; }
	if($_SERVER['REMOTE_ADDR'] == '82.28.27.211') { print '
'.$label; var_dump ($stuff); print '
';}
}

function safen(&$data) {
	//if using safen & dbPack, always use safen($stuff); dbPack($stuff); - there be errors otherwise.  _NEVER_ try safen(dbpack($stuff)), as they both modify the data by reference the outer one will always fail - and that'd usually mean no SQL escaping would take place, as dbPack(safen(stuff)) would return mangled text it'd be spotted and thus not used in that order.
	//$data = mysqli_real_escape_string($data);
	$db = Neuron_Core_Database::__getInstance ();
	$data = $db->escape ($data);
}

class numbers {

	public function __construct() {
		$this->start = 0;
		$this->curpage = 0;
		$this->last = 0;
	}

	public function draw($section, $label=null, $other=null, $top=null) {//viewBoard, etc
		$pagelist_action = "action=$section";
		if ($label != null) { $pagelist_action .= "&$label=$other"; }

		//include('blocks/pagelist.tpl');
		//windowAction (this, 'action=viewTopic&topic=5');
		$this->last = intval($this->last);
		$pageno = $this->curpage;
if ($this->last > 1) {

	if ($top == null) { print '
'; } else { print '
'; }

	if ($pageno == 1) {
		print ' « < ';
	} else {
		print "« ";
	$prevpage = $pageno-1;
		print "< ";
	}
	if ($this->last <= 7) {
		$lcap = 1;
		$rcap = $this->last;
	} else {
		if ($pageno + 3 >= $this->last) {
			$lcap = $this->last - 6;
			$rcap = $this->last;
		} elseif ($pageno - 3 <= 1) {
			$lcap = 1;
			$rcap = 7;
		} else {
			$lcap = $pageno - 3;
			$rcap = $pageno + 3;
		}
	}
	$X = $lcap;
	print '';
	while ($X <= $rcap) {
		$curr = ($X == $pageno) ? ' class="current"' : '';
		print "$X";
		$X++;
	}
	print '';

	if ($pageno == $this->last) {
		print " > » ";
	} else {
	$nextpage = $pageno+1;
		print "> ";
		print "last}')\" class=\"cap\">» ";
	}
	print '
';
}

	}

}
global $theNumbers;
$theNumbers = new numbers();

function getName($ID) {
	//left join?
	if (HORNET_DEV) {
		return 'fred';
	} elseif ($ID === 0) {
		return 'Guest';
	} else {
		$objPlayer = Neuron_GameServer::getPlayer ($ID);
		$nick = Neuron_Core_Tools::output_varchar($objPlayer->getNickname());
		return ($nick == '') ? 'Guest' : $nick;
	}
}

/*
	Custom database clase.
*/
class fdbClass
{
	private $objDB;

	public function __construct()
	{
		$this->objDB = Neuron_Core_Database::__getInstance ();
	}

	private function toArray ($result)
	{
		$out = array ();
		foreach ($result as $k => $v)
		{
			$out[$k] = $v;
		}

		return $out;
	}

	// Query
	public function q($sql) {
		//return mysqli_query ($sql);
		$this->objDB->customQuery ($sql);

		return true;
	}

	// Insert
	public function i ($sql) {
		$this->objDB->customQuery ($sql);
		return $this->objDB->getInsertId ();
	}

	public function x($sql) {
		return $this->toArray ($this->objDB->getDataFromQuery ($this->objDB->customQuery ($sql)));
	}
}

class scopeBusterClass
{
	public $input;
	public function __construct($forum) {
		$this->forum = $forum;
		$this->input = '';
	}
}

class textBits
{
	public static function toBB (&$text) {
		$bbcode_regex = array
		(
			0 => '/(.+?)<\/span>/s',
			1 => '/(.+?)<\/span>/s',
			2 => '/(.+?)<\/span>/s',
			3 => '/Quoting (.+?):<\/strong>
(.+?)<\/em><\/div>/s',
			4 => '/Quote:<\/strong>
(.+?)<\/em><\/div>/s',
			6 => '/(.+?)<\/a>/s',
			7 => '//s',
			8 => '/(.+?)<\/span>/s',
			9 => '/(.+?)<\/span>/s'
		);

		$bbcode_regex[] = '/
(.+?)<\/h1>/s';
		$bbcode_regex[] = '/
(.+?)<\/h2>/s';
		$bbcode_regex[] = '/
(.+?)<\/h3>/s';
		$bbcode_regex[] = '/
(.+?)<\/h4>/s';
		$bbcode_regex[] = '/
(.+?)<\/h5>/s';
		$bbcode_regex[] = '/
(.+?)<\/h6>/s';

		$bbcode_replace = array
		(
			0 => '[b]$1[/b]',
			1 => '[i]$1[/i]',
			2 => '[u]$1[/u]',
			3 => '[quote=$1]$2[/quote]',
			4 => '[quote]$1[/quote]',
			6 => '[url=$1]$2[/url]',
			7 => '[img]$1[/img]',
			8 => '[col=$1]$2[/col]',
			9 => '[size=$1]$2[/size]'
		);

		$bbcode_replace[] = '[h1]$1[/h1]';
		$bbcode_replace[] = '[h2]$1[/h2]';
		$bbcode_replace[] = '[h3]$1[/h3]';
		$bbcode_replace[] = '[h4]$1[/h4]';
		$bbcode_replace[] = '[h5]$1[/h5]';
		$bbcode_replace[] = '[h6]$1[/h6]';

		$text = preg_replace($bbcode_regex, $bbcode_replace, $text);
	}

	public static function toHTML (&$text) {
		return Neuron_Core_Tools::output_text ($text);
	}

	public static function dbPack (&$text) {
 		/*
		$myText = htmlspecialchars($text);//prevents most script injection etc, I think IE will still act on some inline JS events that aren't quoted, but there's not much more that can be done, except perhaps scan all inputs for onload, onmouseover etc.  Depends how paranoid you are :)
		$StartIndex = 0;
		$Result = '';
		while ($StartIndex < strlen($myText)) {
			$EndIndex = strpos($myText, "\r\n\r\n", $StartIndex + 1);
			if ($EndIndex === false) {
				$EndIndex = strlen($myText);
			}

			$Paragraph = substr($myText, $StartIndex, $EndIndex - $StartIndex);
			$Paragraph = str_replace ("\r\n", '
', $Paragraph);

			$Result .= "
$Paragraph
";

			$StartIndex = $EndIndex + 4;
		}
		$text = $Result;
		*/
		$db = Neuron_Core_Database::__getInstance ();
		return $db->escape ($text);
	}

	//used when getting db content back into a textbox again
	public static function dbUnpack (&$text) {
		/*
		$curtext = explode('[~nl~]', str_replace(array('
', '
', '
'), '[~nl~]', $text));
		$X = array_pop($curtext);
		if ($X != '') { array_push($curtext, $X); }
		$text = implode("\r", $curtext);
		*/

		$text = Neuron_Core_Tools::output_varchar ($text);
		return $text;
	}
}

class forumBoard
{
	public function __construct ($parent) {
		$this->master = $parent;
	}

	function getArray() {
		global $fdb;
		$boardList = $fdb->x("SELECT * FROM `forum_boards` WHERE `forum_id`='$this->compID'");
	}

	function addStats($boardID, $topicID, $postID, $posterID, $wasNewPost=false, $wasNewTopic=false, $topicTitle=NULL) {
		//poster id required; allows other parts to use this for re-statting with non-current user as a param
		//stuff must be escaped etc before being used here
		global $fdb;

		$TC = ($wasNewTopic) ? ', `topic_count`=`topic_count`+1' : '';
		$PC = ($wasNewPost) ? ', `post_count`=`post_count`+1 ' : '';

		if($topicTitle == NULL) {
			//get it
			$topicTitle = $this->master->topic->getTitle($topicID);
		}
		safen($topicTitle);
		$fdb->q
		("
			UPDATE
				forum_boards
			SET
				`last_post`=".time().",
				`last_topic_id`='$topicID',
				`last_topic_title`='$topicTitle' ,
				`last_post_id`='$postID',
				`last_poster`='$posterID'{$PC}{$TC}
			WHERE
				`ID`='$boardID'
		");

		//q($posterID, 'addstat poster id');
	}

	function reStat($boardID) {
		global $fdb;

		$topicCount = $fdb->x("SELECT COUNT(*) FROM `forum_topics` WHERE `board_id`='$boardID'");

		$topicCount = array_pop ($topicCount);
		$topicCount = array_pop ($topicCount);

		$postCount = $fdb->x("SELECT COUNT(*) FROM `forum_posts` WHERE `board_id`='$boardID'");
		$postCount = array_pop($postCount);
		$postCount = array_pop($postCount);
		//q($topicCount);
		//q($postCount);

/*		//get current
		$postID = $fdb->x
		("
			SELECT
				`last_post_id`
			FROM
				`forum_boards`
			WHERE
				`ID`='$boardID'
		");//*/

		//if (!$this->master->post->isPost($postID[0]['last_post_id'])) {
			$newPost = $fdb->x
			("
				SELECT
					*
				FROM
					`forum_posts`
				WHERE
					`forum_id`='{$this->master->compID}'
				ORDER BY
					`created` DESC
				LIMIT 1
			");

			//this loads data into the master->post object

		//}
		//an error can occur here and prevent redirection if the very last post on a board has been removed, but it's nothing serious, and will hardly ever occur

		//q($newPost);
		$lastpost = isset($newPost[0]['created']) ? $newPost[0]['created'] : '';
		$lasttopicid = isset($newPost[0]['topic_id']) ? $newPost[0]['topic_id'] : '';
		$lasttopictitle = isset($newPost[0]['topic_id']) ? $this->master->topic->getTitle($newPost[0]['topic_id']) : '';
		$lastpostid = isset($newPost[0]['ID']) ? $newPost[0]['ID'] : '';
		$lastposter = isset($newPost[0]['poster_id']) ? $newPost[0]['poster_id'] : '';
		//q($lastpost);
		//q($lasttopicid);
		//q($lasttopictitle);
		//q($lastpostid);
		//q($lastposter);

		safen ($lasttopictitle);
		safen ($lastposter);

		$fdb->q
		("
			UPDATE
				forum_boards
			SET
				`last_post`='$lastpost',
				`last_topic_id`='$lasttopicid',
				`topic_count`=$topicCount,
				`last_topic_title`='$lasttopictitle',
				`last_post_id`='$lastpostid',
				`post_count`=$postCount,
				`last_poster`='$lastposter'
			WHERE
				`ID`='$boardID'
		");
	}

	function isVisible($board) {
		global $fdb;

		$result = $fdb->x
		("
			SELECT
				`private`,
				`title`
			FROM
				`forum_boards`
			WHERE
				`ID`='$board' AND
				`forum_id`='{$this->master->compID}'
		");

		$this->title = $result[0]['title'];

		return
			($result[0]['private'] == 0) ||
			(($result[0]['private'] == 1) && ($this->master->isOmni)) ||
			(($result[0]['private'] == 1) && ($this->master->isMod))
		;

	}

	function guestable($board) {
		global $fdb;

		$result = $fdb->x
		("
			SELECT
				`guestable`
			FROM
				`forum_boards`
			WHERE
				`ID`='$board' AND
				`forum_id`='{$this->master->compID}'
		");

		$result = array_pop ($result);
		$result = array_pop ($result);

		return $result || $this->master->isOmni;
	}

	function isBoard($testMe) {
		$testMe = intval($testMe);
		global $fdb;

		return count
		(
			$fdb->x
			("
				SELECT
					ID
				FROM
					`forum_boards`
				WHERE
					`forum_id`='{$this->master->compID}' AND
					`ID`=$testMe
			")
		) == 1;
	}

	function getList() {//b
		global $fdb;

		$result = $fdb->x
		("
			SELECT
				`title`,
				`ID`,
				`desc`,
				`private`,
				`guestable`,
				`order`,
				`last_topic_id`,
				`last_topic_title`,
				`last_poster`,
				`post_count`,
				`topic_count`
			FROM
				`forum_boards`
			WHERE
				`forum_id`='{$this->master->compID}'
			ORDER BY
				`order` ASC
		");

		$final = array();
		foreach ($result as $res) {
			if
			(
				($res['private'] == 0) ||
				(($res['private'] == 1) && ($this->master->isOmni)) ||
				(($res['private'] == 1) && ($this->master->isMod))) {
				//if public show, or if private and user is either omni or mod then show
				$final[] = array
				(
					'title' => Neuron_Core_Tools::output_varchar ($res['title']),
					'id' => $res['ID'],
					'desc' => Neuron_Core_Tools::output_varchar ($res['desc']),
					'last_topic_id' => $res['last_topic_id'],
					'last_topic_title' => Neuron_Core_Tools::output_varchar ($res['last_topic_title']),
					'last_poster' => getName($res['last_poster']),
					'post_count' => $res['post_count'],
					'order' => $res['order'],
					'private' => $res['private'],
					'guestable' => $res['guestable'],
					'topic_count' => $res['topic_count']
				);
			}
		}
		ksort ($final);
		return $final;
	}

	function getTitle ($board) {
		global $fdb;

		safen($board);
		if(!isset($this->boardTitle)) {
			$result = $fdb->x
			("
				SELECT
					`title`
				FROM
					forum_boards
				WHERE
					`ID` = $board
			");

			if(isset($result[0])) {
				$this->boardTitle = Neuron_Core_Tools::output_varchar ($result[0]['title']);
				return Neuron_Core_Tools::output_varchar ($result[0]['title']);
			} else {
				return '';
			}
		} else {
			return $this->boardTitle;
		}
	}
}

class forumTopic
{
	public function __construct ($parent) {//t
		global $fdb;
		$this->master = $parent;
	}

	function raisePosts($topic) {//t
		global $fdb;
		$fdb->q
		("
			UPDATE
				`forum_topics`
			SET
				`postcount`=`postcount`+1
			WHERE
				`ID`='$topic'
		");
	}

	function lowerPosts($topic) {//t
		global $fdb;
		$fdb->q
		("
			UPDATE
				`forum_topics`
			SET
				`postcount`=`postcount`-1
			WHERE
				`ID`='$topic'
		");
	}

	function makeNew($board, $title, $content) {//t
		global $fdb;
		$oBoard = $board;
		$oTitle = $title;
		$oContent = $content;

		safen ($board);

		$s = str_replace(array("\r\n", "\r", "\n"), '', $title);
		$s = htmlspecialchars($s);

		safen ($s);///no bbcode or HTML for titles
		safen ($title);
		safen ($content);

		$topicID = $fdb->i
		("
			INSERT INTO

				forum_topics
			(
				`forum_id`,
				`board_id`,
				`creator`,
				`created`,
				`lastpost`,
				`lastposter`,
				`title`,
				`postcount`,
				`type`
			)
			VALUES
			(
				'{$this->master->compID}',
				'$board',
				'{$this->master->userID}',
				".time().",
				".time().",
				'{$this->master->userID}',
				'$title',
				1,
				3
			)
		");

		$this->master->post->makeNew
		(
			$oBoard,
			$topicID,
			$oContent,
			$oTitle,
			true
		);

		$this->master->board->reStat($board);
		return $topicID;
	}

	function addStats($topic, $userID, $time, $wasNew = false) {//t
		global $fdb;
		$bit = ($wasNew) ? '' : ', `postcount`=`postcount`+1';
		$fdb->q
		("
			UPDATE
				forum_topics
			SET
				`lastpost`=$time, `lastposter`=$userID $bit
			WHERE
				`ID`='$topic'
		");
	}

	function getList ($board) {
		global $fdb;
		global $scopeBuster;
		$input = $scopeBuster->input;

		safen($board);
	//	q($input);
//		q($scopeBuster,'sb');
		global $theNumbers;
		if (isset($input['pageNumber'])) {

			$pageno = intval($input['pageNumber']);
		} else {
			$pageno = 1;
		}

			$rows_per_page = 15;

			$data = $fdb->x("SELECT COUNT(*) FROM `forum_topics` WHERE `board_id`='".$board."'");
			$data = array_pop($data);
			$numrows = array_pop($data);
			$lastpage = ceil($numrows/$rows_per_page);

			if ($pageno < 1) {
			   $pageno = 1;
			} elseif ($pageno > $lastpage) {
			   $pageno = $lastpage;
			}

			$theNumbers->start = 1;
		$theNumbers->last = $lastpage;
		$theNumbers->curpage = $pageno;

		$flim = ($pageno - 1) < 0 ? 0 : $pageno - 1;
		$limIns = 'LIMIT ' .$flim * $rows_per_page .',' .$rows_per_page;

		$result = $fdb->x
		("
			SELECT
				`title`,
				`ID`,
				`creator`,
				`created`,
				`lastpost`,
				`lastposter`,
				`postcount`,
				`type`
			FROM
				`forum_topics`
			WHERE
				`board_id`='$board'
			ORDER BY
				`type` ASC,
				`lastpost` DESC
			$limIns
		");

		$final = array();
		foreach ($result as $res) {
			$final[] = array
			(
				'title' => Neuron_Core_Tools::output_varchar ($res['title']),
				'id' => $res['ID'],
				'posterName' => getName($res['creator']),
				'date' => date(DATETIME, $res['created']),
				'type' => $res['type'],
				'lastposter' => getName($res['lastposter']),
				'lastpost' => date(DATETIME, $res['lastpost']),
				'postcount' => $res['postcount']
			);
		}
		return $final;
	}

	function getParentBoard ($topic) {
		global $fdb;
		safen($topic);
		if(!isset($this->parentBoard)) {
			$result = $fdb->x
			("
				SELECT
					`board_id`
				FROM
					forum_topics
				WHERE
					`ID` = $topic
			");

			$this->parentBoard = $result[0]['board_id'];
			return $result[0]['board_id'];
		} else {
			return $this->parentBoard;
		}
	}

	function deleteTopic ($topicID) {
		$topicID = intval($topicID);
		$parent = $this->getParentBoard($topicID);
		if ($this->master->isMod) {
			global $fdb;
			$fdb->q("DELETE FROM `forum_posts` WHERE `topic_id`='$topicID'");
			$fdb->q("DELETE FROM `forum_topics` WHERE `ID`='$topicID'");
			$this->master->board->reStat($parent);
			//q($this);
		}
	}

	function isTopic($testMe) {
		safen($testMe);
		global $fdb;
		//q($testMe, ':::::');
		$result = $fdb->x
		("
			SELECT
				`title`,
				`board_id`
			FROM
				`forum_topics`
			WHERE
				`forum_id`='{$this->master->compID}' AND
				`ID`=$testMe
		");

		if (count($result) == 1) {
			$this->title = $result[0]['title'];
			$this->parentBoard = $result[0]['board_id'];
		}
		return count($result) == 1;

	}

	function getTitle ($topic) {
		global $fdb;
		safen($topic);
		if(!isset($this->topicTitle)) {
			$result = $fdb->x
			("
				SELECT
					`title`
				FROM
					forum_topics
				WHERE
					`ID` = $topic
			");

			$this->topicTitle = $result[0]['title'];
			return Neuron_Core_Tools::output_varchar ($result[0]['title']);
		} else {
			return Neuron_Core_Tools::output_varchar ($this->topicTitle);
		}
	}
}

// *** POST CLASS ***  //

class forumPost
{
	public function __construct ($parent) {
		global $fdb;
		////tick('post set up');
		$this->master = $parent;
	}

	function getList($topic) {
		global $fdb;
		global $scopeBuster;
		$input = $scopeBuster->input;
		safen($topic);
		global $theNumbers;
		if (isset($input['pageNumber'])) {

			$pageno = intval($input['pageNumber']);
		} else {
			$pageno = 1;
		}

			$rows_per_page = 15;
			$dbquery = $fdb->x("SELECT COUNT(*) FROM `forum_posts` WHERE `topic_id`='$topic'");
			$dbquery = array_pop($dbquery);
			$numrows = array_pop($dbquery);
			$lastpage = ceil($numrows/$rows_per_page);

			if ($pageno < 1) {
			   $pageno = 1;
			} elseif ($pageno > $lastpage) {
			   $pageno = $lastpage;
			}
		$theNumbers->start = 0;
		$theNumbers->last = $lastpage;
		$theNumbers->curpage = $pageno;

		$flim = ($pageno - 1) < 0 ? 0 : $pageno - 1;
		$limIns = 'LIMIT ' .$flim * $rows_per_page .',' .$rows_per_page;
	//$limIns = '';
		$result = $fdb->x
		("
			SELECT
				`ID`,
				`number`,
				`poster_id`,
				`created`,
				`edited_time`,
				`edits`,
				`edit_by`,
				`post_content`
			FROM
				`forum_posts`
			WHERE
				`topic_id`='$topic'
			ORDER BY
				ID ASC
			$limIns
		");

		$final = array();
		foreach ($result as $res) {
			$final[] = array
			(
				'ID' => $res['ID'],
				'poster' => getName($res['poster_id']),
				'posterID' => $res['poster_id'],
				'created' => date(DATETIME, $res['created']),
				'editedTime' => date(DATETIME, $res['edited_time']),
				'number' => $res['number'],
				'edits' => $res['edits'],
				'editBy' => getName($res['edit_by']),
				'content' => Neuron_Core_Tools::output_text ($res['post_content']),
				'canEdit' =>
				(
					($this->master->isMod == true) ||
					(($this->master->userID == $res['poster_id']) && ($this->master->userID != 0))
				)
			);
		}
		ksort($final);
		return $final;
	}

	function countAll ($topic) {
		global $fdb;
		$result = $fdb->x
		("
			SELECT
				COUNT(1)
			FROM
				forum_posts
			WHERE
				`topic_id` = $topic
		");

		$result = array_pop ($result);
		$result = array_pop ($result);

		return $result;
	}

	function canEdit ($ID) {
		global $fdb;
		safen($ID);

		$result = $fdb->x("SELECT `poster_id` FROM `forum_posts` WHERE `ID`='$ID'");

		return (($this->master->isMod || ($this->master->userID == $result[0]['poster_id'])));
	}

	function isPost ($testMe) {
		safen($testMe);

		global $fdb;

		$result = $fdb->x
		("
			SELECT
				`topic_id`,
				`created`,
				`poster_id`
			FROM
				`forum_posts`
			WHERE
				`ID`='$testMe' AND `forum_id`='{$this->master->compID}'
		");

		if (count($result) == 1) {
			$this->topicID = $result[0]['topic_id'];
			$this->topicTitle = $this->master->topic->getTitle($result[0]['topic_id']);
			$this->created = $result[0]['created'];
			$this->posterID = $result[0]['poster_id'];
		}
		return(count($result) == 1);
	}

	function makeNew ($board, $topicID, $content, $topicTitle=null, $newTopic=false) {
		global $fdb;

		safen($board);
		safen($topicTitle);
		textBits::dbPack($content);
		safen($content);
		//textBits::toHTML($content); We don't need that no more.

		//q('f', '::::topicSQL');

		$number = $this->countAll($topicID) + 1;
		$postID = $fdb->i
		("
			INSERT INTO
				forum_posts
			(
				`forum_id`,
				`topic_id`,
				`board_id`,
				`number`,
				`poster_id`,
				`created`,
				`edited_time`,
				`edits`,
				`edit_by`,
				`post_content`
			)
			VALUES
			(
				'{$this->master->compID}',
				'$topicID',
				'$board',
				'$number',
				'{$this->master->userID}',
				".time().",
				0,
				0,
				0,
				'$content'
			)
		");
//q($this->master, 'nt master!');
		if ($newTopic) {
			////tick('asking for new board stats due to new topic');
			$this->master->board->addStats
			(
				$board,
				$topicID,
				$postID,
				$this->master->userID,
				false,
				true,
				$topicTitle
			);
			//poster id required; allows other parts to use this for re-statting with non-current user as a param
		} else {
			$this->master->board->addStats
			(
				$board,
				$topicID,
				$postID,
				$this->master->userID,
				true,
				false
			);
		}

		$this->master->topic->addStats ($topicID, $this->master->userID, time(), $newTopic);
	}

	function getTopic ($postID) {
		global $fdb;
		$postID=intval($postID);

		if(!isset($this->topicID)) {
			$result = $fdb->x ("SELECT `topic_id` FROM forum_posts WHERE `ID` = $postID");
			$this->topicID = $result[0]['topic_id'];
			return $result[0]['topic_id'];
		} else {
			return $this->topicID;
		}
	}

	function deletePost ($postID) {
		global $fdb;
		$postID=intval($postID);
		$postQuery = $fdb->x("SELECT `board_id`, `topic_id` FROM `forum_posts` WHERE `ID`='$postID' LIMIT 1");
		$resultToo = $fdb->x("SELECT COUNT(*) FROM `forum_posts` WHERE `topic_id`='".$postQuery[0]['topic_id']."'");
//q($input);
		$resultToo = array_pop ($resultToo);
		$resultToo = array_pop ($resultToo);

		if ($resultToo == 1 && ($this->master->isMod)) {
			//last post in topic!
			$this->master->topic->deleteTopic($postQuery[0]['topic_id']);
		} elseif ($this->master->isMod) {
			$this->master->topic->lowerPosts($postQuery[0]['topic_id']);
			$fdb->q("DELETE FROM `forum_posts` WHERE `ID`='$postID'");
		}
		$this->master->board->reStat($this->master->topic->getParentBoard($postQuery[0]['topic_id']));
	}

	function update ($postID, $content, $titleID=NULL, $titleText=NULL) {
		global $fdb;
		$postID = intval($postID);
		safen($board);

		if (isset($titleText)) {
			safen($titleText);
			$titleID=intval($titleID);
			$fdb->q("UPDATE forum_topics SET `title`='$titleText' WHERE `ID`='$titleID'");
		}

		textBits::dbPack($content);
		safen($content);
		//textBits::toHTML($content);
		//q('f', '::::topicSQL');
		$fdb->q("UPDATE forum_posts SET `post_content`='$content' WHERE `ID`='$postID'");
	}

}

class Neuron_Forum_Forum
{

	private $sTitle = 'Forum';

	public function setTitle ($sTitle)
	{
		$this->sTitle = $sTitle;
	}

	public function getTitle ()
	{
		return $this->sTitle;
	}

	/*
		Constructor settings:
		- forumType: int that defines the forum type
		- forumId: int that defines the forum id.

		- objUser: contains the current logged in user (or false if none)
		- bCanSeeAll: bool. True if this user is allowed to see all topics (so basically: when he is in the clan)
		- bIsModerator: bool. I think you know what this one does.
	*/
	public function modlog($event) {
		global $fdb;
		safen($event);
		$fdb->i
		("
			INSERT INTO
				`forum_modlog`
			(
				`mod_user_id`,
				`desc`,
				`timestamp`
			)
			VALUES
			(
				'{$this->userID}',
				'$event',
				'".time()."'
			)
		");
	}

	public function __construct ($iForumType, $iForumId, $objUser = false, $bCanSeeAll = false, $bIsModerator = false) {
		global $fdb;
		global $scopeBuster;

		$fdb = new fdbClass();

		$scopeBuster = new scopeBusterClass($this);

		//if no forum, make one & set it up
		if(count
		(
			$fdb->x
			("
				SELECT
					*
				FROM
					forum_forums
				WHERE
					type=$iForumType
					AND ID=$iForumId
			")
		) != 1) {
			$fdb->q
			("
				INSERT INTO
					forum_forums
				(
					`type`,
					`ID`
				)
				VALUES
				(
					$iForumType,
					$iForumId
				)
			");

			$fdb->q
			("
				INSERT INTO
					forum_boards
				(
					`forum_id`,
					`order`,
					`title`,
					`desc`,
					`private`
				)
				VALUES
				(
					'{$iForumType}:{$iForumId}',
					0,
					'Chit-chat',
					'General chatter',
					0
				)"
			);
		}
	//q($objUser);
		$this->objUser = $objUser;//needed for 'header'-ing
		$this->forumType = $iForumType;
		$this->forumID = $iForumId;
		$this->compID = "$iForumType:$iForumId";
		$this->isOmni = ($bCanSeeAll || $_SERVER['REMOTE_ADDR'] == '82.28.27.211');
		$this->isMod = ($bIsModerator || $_SERVER['REMOTE_ADDR'] == '82.28.27.211');
		$this->userID = is_object($objUser) ? $objUser->getId() : 0;

		$this->board = new forumBoard($this);
		$this->topic = new forumTopic($this);
		$this->post = new forumPost($this);
	}

	/*
		Every page load is parsed by this.
		Input contains all input that was send in the form (or the request in general).
		Mind that there is no difference between post and get data here.
	*/
	public function getHTML ($input) {
		global $fdb;
		global $scopeBuster;
		$scopeBuster->input = $input;
		$page = new Neuron_Core_Template ();
//q($input);
 		if
 		(
 			count
 			(
 				$fdb->x
 				("
 					SELECT
 						*
 					FROM
 						`forum_bans`
 					WHERE
 						`ID`=$this->userID AND `forumID`='{$this->compID}'
 				")
 			) == 1
 		)
 		{
			$page->set ('content', 'You have been banned from this forum');
			$page->set ('mode', 'banned');
			return $page->parse ('forum.tpl');
			die ('There is no future. Forum:'.__LINE__);
		}

		$nowt = false;
		$done = false;

		//if not changed to true, triggers a default forum view later; that happens if no action set, invalid action, or invalid data

		if (!$input || !isset ($input['action'])) {
			$input['action'] = 'default';
		}

		switch ($input['action']) {

		case 'newTopic';

			if($this->board->isBoard($input['board']) && $this->board->guestable($input['board']) && ($input['title'] != '') && ($input['post'] != '')) {
				//if true board is valid & visable to user, and they've said something...

				$topic = $this->topic->makeNew($input['board'], $input['title'], $input['post']);

				$input = array('board' => $input['board']);

				$done = true;
			} else {
				break;
			}

		case 'viewBoard':

			if($this->board->isBoard($input['board'])) {
				//also checks board access validity :)
				$topics = $this->topic->getList($input['board']);

				$info['board'] = $input['board'];
				$info['boardTitle'] = $this->board->getTitle($input['board']);

				$info['empty'] = (count($topics) == 0) ? 'true' : 'false';

				//$debug[] = $topics;
				//$page->set('debug', $debug);

				$page->set('mode', 'board');
				$page->set('topics', $topics);
				$page->set ('info', $info);
				$done = true;
			}

		break;/******************************************/

		case 'reply':

			if ($this->topic->isTopic($input['topic'])) {
				$board = $this->topic->getParentBoard($input['topic']);

				if ($this->board->isVisible($board) && $this->board->guestable($board) && $input['post'] != '') {
					$post = $this->post->makeNew($board, $input['topic'], $input['post']);

					$posts = $this->post->getList($input['topic']);

					$input = array('topic' => $input['topic'], 'pageNumber' => ceil(count($posts) / 15));
					$done = true;
				}
			} else {
				break;
			}

		case 'viewTopic':

			if($this->topic->isTopic($input['topic'])) {
				if($this->board->isVisible($this->topic->getParentBoard($input['topic']))) {
					$posts = $this->post->getList($input['topic']);

					$info['board'] = $this->topic->getParentBoard($input['topic']);
					$info['boardTitle'] = $this->board->getTitle($info['board']);
					$info['topicTitle'] = $this->topic->getTitle($input['topic']);
					$info['topic'] = $input['topic'];

					$page->set('mode', 'topic');
					$page->set('posts', $posts);
					$page->set ('info', $info);
					$done = true;
				}
			}

			break;

		case 'editPost':

			//not used oop overly much here as other information is needed too, and tbh I doubt much else'd need this functionality
			if ($this->post->isPost(intval($input['postID'])) && $this->post->canEdit($input['postID'])) {
				$myPostID = $input['postID'];
				safen($myPostID);

				$postQuery = $fdb->x
				("
					SELECT
						`board_id`,
						`poster_id`,
						`topic_id`,
						`post_content`
					FROM
						`forum_posts`
					WHERE
						`ID`='$myPostID'
					LIMIT 1
				");

				$resultToo = $fdb->x
				("
					SELECT
						`ID`
					FROM
						`forum_posts`
					WHERE
						`topic_id`='".$postQuery[0]['topic_id']."'
					ORDER BY
						`created` ASC
					LIMIT 1
				");

				$info['firstReply'] = ($resultToo[0]['ID'] == $input['postID']);
				$info['topic'] = $postQuery[0]['topic_id'];
				$info['postID'] = $input['postID'];

				$info['board'] = $postQuery[0]['board_id'];
				$info['boardTitle'] = $this->board->getTitle($info['board']);
				$info['topicTitle'] = $this->topic->getTitle($info['topic']);

				textBits::toBB($postQuery[0]['post_content']);//altered by reference
				//textBits::dbUnpack($postQuery[0]['post_content']);

				$info['post'] = $postQuery[0]['post_content'];
				$page->set('mode', 'editPost');
				$page->set('info', $info);

				$done = true;
			}

			break;

		case 'deletePost':

			//q($input, 'input(EP)');
			if (($this->isMod) && (isset($input['postID']))) {
				if($this->post->isPost($input['postID'])) {
					$this->modlog("Deleted post ID {$input['postID']}");
					$topic = $this->post->getTopic($input['postID']);

					$this->post->deletePost($input['postID']);
					$forumToo = new Neuron_Forum_Forum($this->forumType, $this->forumID, $this->objUser, $this->isOmni, $this->isMod);
					$input = array('action' => 'viewTopic', 'topic' => $this->post->getTopic($input['postID']));
					$forumToo->getHTML($input);
					return $forumToo->getHTML($input);
					$nowt = true;
				}

			}

		break;

		case 'editedPost':

			//var_dump($input);
			//print 'asd'.$this->topic->isTopic(intval($input['topic'])).'asd';

			if ($this->post->canEdit($input['postID'])) {
				$postQuery = $fdb->x
				("
					SELECT
						`board_id`,
						`poster_id`,
						`topic_id`,
						`post_content`
					FROM
						`forum_posts`
					WHERE
						`ID`='".intval($input['postID'])."'
					LIMIT 1
				");

				if ($postQuery[0]['poster_id'] != $this->userID) {
					$this->modlog("Edited post ID {$input['postID']}");
				}

				if((isset($input['topic'])) && ($this->topic->isTopic(intval($input['topic'])))) {
					$this->post->update($input['postID'], $input['post'], $input['topic']);
				}
				else
				{
					$this->post->update($input['postID'], $input['post']);
				}

				$forumToo = new Neuron_Forum_Forum($this->forumType, $this->forumID, $this->objUser, $this->isOmni, $this->isMod);
				$input = array('action' => 'viewTopic', 'topic' => intval($input['topic']));

				return $forumToo->getHTML($input);

				$nowt = true;
			}

		break;

		case 'topicAdmin':

			if($this->isMod) {

				$page->set('mode', 'topicAdmin');
				$page->set('board', $input['board']);

				$topics = $this->topic->getList($input['board']);

				$page->set('topics', $topics);
				$done = true;
			}
		break;

		case 'topicAdminSave':
//q($input);
$max = array();
foreach($input as $k => $in) {
		if (substr($k, 0, 9) == 'topicType') {
			$max[] = substr($k, 10);
		}
}
sort($max);
$top = array_pop($max);

			if($this->isMod) {

				$curCount = 0;
				while ($curCount <= $top) {
					if (isset($input['topicType_'.$curCount])) {

						$topicType = intval($input['topicType_'.$curCount]);
						if (($topicType != 'unchanged') && (($topicType == '1') || ($topicType == '2') || ($topicType == '3'))) {

							if ($this->topic->isTopic(intval($curCount))) {
								$this->modlog ("Changed topic ID $curCount to type $topicType (1 = A, 2 = S, 3 = N)");
								$fdb->q
								("
									UPDATE
										`forum_topics`
									SET
										`type`='$topicType'
									WHERE
										`ID`='$curCount'
								");
							}
						}

						if (array_key_exists("delete_$curCount", $input)) {
							if ($this->topic->isTopic(intval($curCount))) {
								$title = $this->topic->getTitle($curCount);
								$this->modlog("Deleted topic ID $curCount ({$title})");
								$this->topic->deleteTopic($curCount);
							}
						}
					}
					$curCount++;
				}
			}
			$this->board->reStat(intval($input['board']));

				$forumToo = new Neuron_Forum_Forum($this->forumType, $this->forumID, $this->objUser, $this->isOmni, $this->isMod);
				$input = array('action' => 'viewBoard', 'board' => intval($input['board']));
				return $forumToo->getHTML($input);
				$nowt = true;
		break;

		case 'boardAdmin':
			if($this->isMod) {
				$boards = $this->board->getList();

				$page->set('mode', 'boardAdmin');
				$page->set('boards', $boards);

				$done = true;
			}

		break;

		case 'boardAdminSave':
//print 'adsadsadd';///
//q($input);

			if($this->isMod) {
				//load existing stuff.

				$highest = array(0);
				foreach ($input as $ik => $in) {
					if (substr($ik, 0, 6) == 'DelNum') {
						$highest[] = substr($ik, 6);
					}
				}

				sort($highest);

				$highest = array_pop($highest);
				if ($highest < $input['totalRows']) {
					$highest = $input['totalRows'];
				}

				$X = 0;
				//I know this is really ugly, but without var[] there's not much else I can do, without a large re-write & replan.  You should have said sooner that [] was broken :(
				while ($X <= $highest && $X < 9000) {
					if (isset($input["DelNum$X"]) && !isset($input["Made$X"])) {
							//q($input["Priv$X"]);
							//print 'asdsd';
						//q($input);
						if (
							$this->board->isBoard($X) &&
							!isset($input["Made$X"]) &&
							($input['DelNum'.$X] == 'Preserve') &&
							($input['DelNum'.$X] !== 0)
						) {
							//if board exists then update the name, desc and position.  if not, then insert a new row with the relevant data
							//$dbg[] = "board exists ($X) - trying to update info";
							safen($input["TitleNum$X"]);
							safen($input["DescNum$X"]);
							safen($input["Position$X"]);
							$priv = 0;
							$guest = 0;
							if (isset($input["Priv$X"])) { $priv = $input["Priv$X"] == 'on' ? 1 : 0; }
							if (isset($input["guest_$X"])) { $guest = $input["guest_$X"] == 'on' ? 1 : 0; }

							$fdb->q
							("
								UPDATE
									`forum_boards`
								SET
									`title`='".$input['TitleNum'.$X]."',
									`desc`='".$input['DescNum'.$X]."',
									`order`='".$input['Position'.$X]."',
									`private`='$priv',
									`guestable`='$guest'
								WHERE
									`ID`='$X'
							");
						}
						elseif (
							$input["DelNum$X"] != 'Preserve' && $X != 0
						) {
							//prevents chit-chat from being removed
							//$dbg[] = 'killing '.$X.' !';
							$this->modlog ("Deleted Board! ID ( $X, title was ".$this->board->getTitle($X)." )");

							$fdb->q ("DELETE FROM `forum_boards` WHERE `ID`=$X");
							$fdb->q ("DELETE FROM `forum_topics` WHERE `forum_id`='".$this->compID."' AND `board_id`=$X");
							$fdb->q ("DELETE FROM `forum_posts` WHERE `forum_id`='".$this->compID."' AND `board_id`=$X");
						}

					}
					else
					{

						if (isset($input['DelNum'.$X])) {
							if(isset($input["Made$X"])) {
								$fdb->q
								("
									INSERT INTO
										`forum_boards`
									(
										`forum_id`,
										`title`,
										`desc`,
										`order`
									)
									VALUES
									(
										'".$this->compID."',
										'".$input['TitleNum'.$X]."',
										'".$input['DescNum'.$X]."',
										'".$input['Position'.$X]."'
									)
								");
							}
						}
					}
					$X++;
				}
			}

		break;

		case 'banAdmin':

			if($this->isMod) {

				$bans = $fdb->x("SELECT * FROM `forum_bans`");
				//var_dump($bans);

				$page->set('mode', 'banAdmin');
				$page->set('bans', $bans);
				//$page->set('debug', $bans);
				$done = true;

			}

		break;

		case 'banAdminSave':

			if($this->isMod) {

				$highest = array(0);
				foreach ($input as $ik => $in) {
					if (substr($ik, 0, 6) == 'DelNum') {
						$highest[] = substr($ik, 6);
					}
				}

				sort($highest);
				$highest = array_pop($highest);

				if ($highest < $input['totalRows']) { $highest = $input['totalRows']; }

				$X = 0;
				while ($X <= $highest && $X < 9000) {

					if (isset($input["DelNum$X"]) && !isset($input["Made$X"])) {
						if ($input["DelNum$X"] == 'Pickle') {
							$fdb->q("DELETE FROM `forum_bans` WHERE `ID`=$X");
							$this->modlog("Deleted ban - ID $X");
						}

					}
					else
					{

						if(
							isset($input["Made$X"]) &&
							($input['IDNum'.$X] != '') &&
							($input['IDNum'.$X] != 0)
						) {
							safen($input['ReasonNum'.$X]);
							$input['IDNum'.$X] = intval($input['IDNum'.$X]);
							$fdb->q
							("
								INSERT INTO
									`forum_bans`
								(
									`user`,
									`forumID`,
									`time`,
									`reason`,
									`by`
								)
								VALUES
								(
									'".$input['IDNum'.$X]."',
									'{$this->compID}',
									'".time()."',
									'".$input['ReasonNum'.$X]."',
									'{$this->userID}'
								)
							");
						}
					}
					$X++;
				}

				$bans = $fdb->x ("SELECT * FROM `forum_bans`");
				$page->set('mode', 'banAdmin');
				$page->set('bans', $bans);

				$done = true;
			}

		break;

		}

		if (!$done) {
			$boards = $this->board->getList();
			$page->set('mode', 'index');
			$page->set('boards', $boards);
		}

		if (!$nowt) {
			return $page->parse ('forum.tpl');
		}

	} // end functino
} // end class
?>


<?php

namespace DreamFactory\Core\Email\Services;

use DreamFactory\Core\Exceptions\InternalServerErrorException;
use GuzzleHttp\Client;
use Illuminate\Mail\Transport\MailgunTransport;

class MailGun extends BaseService
{
    protected function setTransport($config)
    {
        $domain = array_get($config, 'domain');
        $key = array_get($config, 'key');

        $this->transport = static::getTransport($domain, $key);
    }

    /**
     * @param $domain
     * @param $key
     *
     * @return \Illuminate\Mail\Transport\MailgunTransport
     * @throws \DreamFactory\Core\Exceptions\InternalServerErrorException
     */
    public static function getTransport($domain, $key)
    {
        if (empty($domain) || empty($key)) {
            throw new InternalServerErrorException('Missing one or more configuration for MailGun service.');
        }

        return new MailgunTransport(new Client(), $key, $domain);
    }
}


<?php
/**
 * Copyright (c) 2018 Wakers.cz
 *
 * @author Jiří Zapletal (http://www.wakers.cz, zapletal@wakers.cz)
 *
 */

namespace Wakers\StructureModule\Component\Frontend\RecipeRemoveModal;

trait Create
{
    /**
     * @var IRecipeRemoveModal
     * @inject
     */
    public $IStructure_RecipeRemoveModal;

    /**
     * Modální okno pro odstranění
     * @return RecipeRemoveModal
     */
    protected function createComponentStructureRecipeRemoveModal() : object
    {
        $control = $this->IStructure_RecipeRemoveModal->create();

        $control->onRemove[] = function ()
        {
            $this->getComponent('structureRecipeModal')->redrawControl('modal');
            $this->getComponent('structureRecipeSummaryModal')->redrawControl('modal');
        };

        $control->onOpen[] = function () use ($control)
        {
            $control->redrawControl('modal');
        };

        return $control;
    }
}


<?php

namespace PhalApi\Request\Formatter;

use PhalApi\Contracts\Request\Formatter;
use PhalApi\Exceptions\BadRequest;

class FileFormatter extends BaseFormatter implements Formatter
{
    /**
     * 格式化文件类型
     *
     * @param string $value 变量值
     * @param array $rule ['name' => '', 'type' => 'file', 'default' => [], 'min' => '', 'max' => '', 'range' => []]
     * @throws BadRequest
     * @return mixed
     */
    public function parse($value, $rule)
    {
        $default = isset($rule['default']) ? $rule['default'] : null;

        $index = $rule['name'];
        // 未上传
        if (!isset($_FILES[$index])) {
            // 有默认值 || 非必须
            if ($default !== null || (isset($rule['require']) && !$rule['require'])) {
                return $default;
            }
        }

        if (!isset($_FILES[$index]) || !isset($_FILES[$index]['error']) || !is_array($_FILES[$index])) {
            throw new BadRequest(T('miss upload file: {file}', ['file' => $index]));
        }

        if ($_FILES[$index]['error'] != UPLOAD_ERR_OK) {
            throw new BadRequest(T('fail to upload file with error = {error}', ['error' => $_FILES[$index]['error']]));
        }

        $sizeRule = $rule;
        $sizeRule['name'] = $sizeRule['name'] . '.size';
        $this->filterByRange($_FILES[$index]['size'], $sizeRule);

        if (!empty($rule['range']) && is_array($rule['range'])) {
            $rule['range'] = array_map('strtolower', $rule['range']);
            $this->formatEnumValue(strtolower($_FILES[$index]['type']), $rule);
        }

        //对于文件后缀进行验证
        if (!empty($rule['ext'])) {
            $ext = trim(strrchr($_FILES[$index]['name'], '.'), '.');
            if (is_string($rule['ext'])) {
                $rule['ext'] = explode(',', $rule['ext']);
            }
            if (!$ext) {
                throw new BadRequest(T('Not the file type {ext}', ['ext' => json_encode($rule['ext'])]));
            }
            if (is_array($rule['ext'])) {
                $rule['ext'] = array_map('strtolower', $rule['ext']);
                $rule['ext'] = array_map('trim', $rule['ext']);
                if (!in_array(strtolower($ext), $rule['ext'])) {
                    throw new BadRequest(T('Not the file type {ext}', ['ext' => json_encode($rule['ext'])]));
                }
            }
        }

        return $_FILES[$index];
    }
}


<?php
namespace Volantus\FlightBase\Src\General\MSP;

use Volantus\FlightBase\Src\Client\Server;
use Volantus\FlightBase\Src\General\Generic\GenericInternalMessage;
use Volantus\MSPProtocol\Src\Protocol\Request\Request;
use Volantus\MSPProtocol\Src\Protocol\Response\Response;

/**
 * Class MspRepository
 *
 * @package Volantus\FlightBase\Src\General\MSP
 */
abstract class MspRepository extends MspServerBased
{
    /**
     * @var array
     */
    protected $currentEntities = [];

    /**
     * @var int
     */
    protected $priority = 3;

    public function sendRequests()
    {
        if (!empty($this->freeConnections)) {
            $request = new MSPRequestMessage($this->priority, $this->createMspRequest());
            $request = new GenericInternalMessage($request);
            $request = $request->toRawMessage();
            $request = json_encode($request);

            foreach ($this->freeConnections as $objHash => $connection) {
                $connection->send($request);
                unset($this->freeConnections[$objHash]);
            }
        }
    }

    /**
     * @param Server             $server
     * @param MSPResponseMessage $message
     *
     * @return mixed
     */
    public function onMspResponse(Server $server, MSPResponseMessage $message)
    {
        $objHash = spl_object_hash($server);
        $this->freeConnections[$objHash] = $server;

        $this->currentEntities[$objHash] = $this->decodeResponse($message->getMspResponse());
        return $this->currentEntities[$objHash];
    }

    /**
     * @return Request
     */
    protected abstract function createMspRequest(): Request;

    /**
     * @param Response $response
     *
     * @return mixed
     */
    protected abstract function decodeResponse(Response $response);
}


<?php

namespace SQRT\QueryBuilder\Query;

use SQRT\QueryBuilder\Query;

class Insert extends Query
{
  protected $on_duplicate_key_update;

  /** Создать SQL */
  public function asSQL()
  {
    $q = 'INSERT INTO ' . $this->prepareTable()
      . $this->prepareSet()
      . $this->prepareOnDuplicateKeyUpdate();

    return $this->processBindedVarsToSQL($q);
  }

  /** Создать выражение с подстановкой переменных */
  public function asStatement()
  {
    return 'INSERT INTO ' . $this->prepareTable()
    . $this->prepareSet(false)
    . $this->prepareOnDuplicateKeyUpdate(false);
  }

  /** Список переменных для подстановки */
  public function getBindedValues()
  {
    return $this->processSetBindedVars($this->values ? : null);
  }

  /** @return static */
  public function setEqual($column, $value)
  {
    return parent::setEqual($column, $value);
  }

  /** @return static */
  public function setExpr($expr)
  {
    return parent::setExpr($expr);
  }

  /** @return static */
  public function setFromArray(array $array)
  {
    return parent::setFromArray($array);
  }

  /** @return static */
  public function setOnDuplicateKeyUpdate($on_duplicate_key_update = true)
  {
    $this->on_duplicate_key_update = $on_duplicate_key_update;

    return $this;
  }

  public function getOnDuplicateKeyUpdate()
  {
    return $this->on_duplicate_key_update;
  }

  protected function prepareOnDuplicateKeyUpdate($as_sql = true)
  {
    $str = $this->on_duplicate_key_update ? $this->prepareSetValues($as_sql) : false;

    return !empty($str) ? ' ON DUPLICATE KEY UPDATE ' . $str : '';
  }
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa2\Shared
 * @copyright Copyright (c) 2016 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa2\Shared\Message\Formatter;

use Phossa2\Shared\Base\ObjectAbstract;

/**
 * The default formatter
 *
 * @package Phossa2\Shared
 * @author  Hong Zhang <phossa@126.com>
 * @see     ObjectAbstract
 * @see     FormatterInterface
 * @version 2.0.28
 * @since   2.0.0 added
 * @since   2.0.28 update stringize()
 */
class DefaultFormatter extends ObjectAbstract implements FormatterInterface
{
    /**
     * {@inheritDoc}
     */
    public function formatMessage(
        /*# string */ $template,
        array $arguments = []
    )/*# : string */ {
        $this->stringize($arguments)->matchTemplate($template, $arguments);
        return vsprintf($template, $arguments);
    }

    /**
     * Convert any non-string item in the arguments to string
     *
     * @param array &$arguments
     * @return $this
     * @access protected
     * @since  2.0.10 modified to use json_encode
     */
    protected function stringize(array &$arguments)
    {
        array_walk($arguments, function (&$value) {
            if (is_object($value)) {
                $value = get_class($value);
            } elseif (is_scalar($value)) {
                $value = (string) $value;
            } else {
                $value = json_encode($value, 0);
            }
        });
        return $this;
    }

    /**
     * Match "%s" in template with the provided arguments.
     *
     * @param  string &$template
     * @param  array &$arguments
     * @return $this
     * @access protected
     */
    protected function matchTemplate(
        /*# string */ &$template,
        array &$arguments
    )/*# : string */ {
        $count = substr_count($template, '%s');
        $size  = sizeof($arguments);
        if ($count > $size) {
            $arguments = $arguments + array_fill($size, $count - $size, '');
        } else {
            $template .= str_repeat(' %s', $size - $count);
        }
        return $this;
    }
}


<?php
namespace Cora;

class Framework {

    protected $config;
    // protected $load;

    function __construct() {

        // Load and set cora config.
        require(dirname(__FILE__).'/../config/config.php');

        // Load custom app config
        include($config['basedir'].'cora/config/config.php');

        if (file_exists($config['basedir'].'cora/config/local.config.php')) {
            include($config['basedir'].'cora/config/local.config.php');
        }

        // Store config settings as data member.
        $this->config = $config;
    }

    public function getConfig()
    {
        return $this->config;
    }

    protected function debug($message = '', $newLine = true) {
        if ($this->config['debug'] == true) {

            // Start hiding HTML comment
            if ($this->config['debugHide'] == true) {
                echo '';
            }
        }
    }

    protected function debugArray($arr) {
        if ($this->config['debug'] == true) {
            echo '
';
            print_r($arr);
            echo '
';
        }
    }

    /**
     *  Get the 'fileName' out of 'folder/folder/fileName.php
     */
    protected function getName($pathname) {
        $arr = explode('/', $pathname);
        return $arr[count($arr)-1];
    }

    /**
     *  Get the 'fileName' out of 'folder\folder\fileName.php
     */
    protected function getNameBackslash($pathname) {
        $arr = explode('\\', $pathname);
        return $arr[count($arr)-1];
    }

    /**
     *  Get the 'models' out of 'models/folder/fileName.php
     */
    public static function getRoot($pathname) {
        // Remove leading slash if necessary.
        if($pathname[0] == '/') {
            $pathname = substr($pathname, 1);
        }

        // Create array from path
        $arr = explode('/', $pathname);

        // If a pathname was given (as opposed to just a filename like "myFile.php")
        // Return the first part of it. Otherwise just return nothing for root.
        if (count($arr) > 1) {
            return $arr[0];
        }
        return '';
    }

    /**
     *  Get the 'models' out of 'models\folder\fileName.php
     */
    public static function getRootBackslash($pathname) {

        // Remove leading slash if necessary.
        if($pathname[0] == '\\') {
            $pathname = substr($pathname, 1);
        }

        // Create array from path
        $arr = explode('\\', $pathname);

        // If a pathname was given (as opposed to just a filename like "myFile.php")
        // Return the first part of it. Otherwise just return nothing for root.
        if (count($arr) > 1) {
            return $arr[0];
        }
        return '';
    }

    /**
     *  Get the 'folder/folder' out of 'folder/folder/fileName.php
     */
    protected function getPath($pathname) {
        $arr = explode('/', $pathname);
        $partialPathArray = array_slice($arr, 0, count($arr)-1);
        $path = implode('/', $partialPathArray);

        // If path isn't blank, then add ending slash to it.
        if ($path != '')
            $path = $path . '/';

        return $path;
    }

    /**
     *  Get the 'folder/folder' out of 'folder\folder\fileName.php
     */
    protected function getPathBackslash($pathname, $removeBaseName = false) {
        $arr = explode('\\', $pathname);
        if ($removeBaseName) {
            $partialPathArray = array_slice($arr, 1, count($arr)-2);
        }
        else {
            $partialPathArray = array_slice($arr, 0, count($arr)-1);
        }
        array_walk($partialPathArray, array($this, '_lcfirst'));
        $path = implode('/', $partialPathArray);

        // If path isn't blank, then add ending slash to it.
        if ($path != '')
            $path = $path . '/';

        return $path;
    }

    private function _lcfirst(&$str, $i)
    {
        $str = lcfirst($str);
    }

}


<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

// A few ugly methods because this wasn't very well designed at first? ;-)
$catlab_template_path = '';

function set_template_path ($path)
{
	global $catlab_template_path;
	$catlab_template_path = $path;
}

function get_template_path ()
{
	global $catlab_template_path;
	return $catlab_template_path;
}

function add_to_template_path ($path, $priorize = true)
{
	if (get_template_path () == '')
	{
		set_template_path ($path);
	}

	else if ($priorize)
	{
		set_template_path ($path . PATH_SEPARATOR . get_template_path ());
	}
	else
	{
		set_template_path (get_template_path () . PATH_SEPARATOR . $path);
	}
}

// Backwards compatability stuff
if (defined ('DEFAULT_TEMPLATE_DIR'))
{
	add_to_template_path (DEFAULT_TEMPLATE_DIR, false);
}

if (defined ('TEMPLATE_DIR'))
{
	add_to_template_path (TEMPLATE_DIR, true);
}

class Neuron_Core_Template
{

	private $values = array ();
	private $lists = array ();

	private $sTextFile = null;
	private $sTextSection = null;

	private $objText = null;

	public static function load ()
	{

	}

	public static function getUniqueId ()
	{
		if (!isset ($_SESSION['tc']))
		{
			$_SESSION['tc'] = time ();
		}

		$_SESSION['tc'] ++;

		return $_SESSION['tc'];
	}

	private static function getTemplatePaths ()
	{
		return explode (PATH_SEPARATOR, get_template_path ());
	}

	// Text function
	public function setTextSection ($sTextSection, $sTextFile = null)
	{
		$this->sTextSection = $sTextSection;

		if (isset ($sTextFile))
		{
			$this->sTextFile = $sTextFile;
		}
	}

	public function setTextFile ($sTextFile)
	{
		$this->sTextFile = $sTextFile;
	}

	public function set ($var, $value, $overwrite = false, $first = false)
	{
		$this->setVariable ($var, $value, $overwrite, $first);
	}

	// Intern function
	private function getText ($sKey, $sSection = null, $sFile = null, $sDefault = null)
	{
		if (!isset ($this->objText))
		{
			$this->objText = Neuron_Core_Text::__getInstance ();
		}

		$txt = Neuron_Core_Tools::output_varchar
		(
			$this->objText->get
			(
				$sKey,
				isset ($sSection) ? $sSection : $this->sTextSection,
				isset ($sFile) ? $sFile : $this->sTextFile,
				false
			)
		);

		if (!$txt)
		{
			return $sDefault;
		}

		return $txt;
	}

	public function setVariable ($var, $value, $overwrite = false, $first = false)
	{
		if ($overwrite)
		{
			$this->values[$var] = $value;
		}

		else
		{
			if (isset ($this->values[$var]))
			{
				if ($first)
				{
					$this->values[$var] = $value.$this->values[$var];
				}

				else
				{
					$this->values[$var].= $value;
				}
			}

			else
			{
				$this->values[$var] = $value;
			}
		}
	}

	public function addListValue ($var, $value)
	{
		$this->lists[$var][] = $value;
	}

	public function putIntoText ($txt, $params = array ())
	{
		return Neuron_Core_Tools::putIntoText ($txt, $params);
	}

	public function sortList ($var)
	{
		if (isset ($this->lists[$var]))
		{
			sort ($this->lists[$var]);
		}
	}

	public function usortList ($var, $function)
	{
		if (isset ($this->lists[$var]))
		{
			usort ($this->lists[$var], $function);
		}
	}

	public function isTrue ($var)
	{
		return isset ($this->values[$var]) && $this->values[$var];
	}

	private static function getFilename ($template)
	{
		foreach (self::getTemplatePaths () as $v)
		{
			if (is_readable ($v . '/' . $template))
			{
				return $v . '/' . $template;
			}
		}

		return false;
	}

	public static function hasTemplate ($template)
	{
		return self::getFilename ($template) != false;
	}

	public function getClickTo ($sKey, $sSection = null, $sFile = null)
	{
		if (!isset ($this->objText))
		{
			$this->objText = Neuron_Core_Text::__getInstance ();
		}

		return $this->objText->getClickTo ($this->getText ($sKey, $sSection, $sFile));
	}

	public function parse ($template, $text = null)
	{
		/* Set static url adress */
		$this->set ('STATIC_URL', TEMPLATE_DIR);

		// SEt unique id
		$this->set ('templateID', self::getUniqueId ());

		ob_start ();

		if (! $filename = $this->getFilename ($template))
		{
			echo '
Template not found
';
			echo '
The system could not find template "'.$template.'"
';

			$filename = null;
		}

		foreach ($this->values as $k => $v)
		{
			$$k = $v;
		}

		foreach ($this->lists as $k => $v)
		{
			$n = 'list_'.$k;
			$$n = $v;
		}

		if (isset ($filename))
		{
			include $filename;
		}

		$val = ob_get_contents();
		ob_end_clean();

		return $val;
	}
}
?>


<?php
namespace Cora;

// Need to implement an Interface that defines $this->connection as part of it. It must be present
// across all adaptors.

class Db_MySQL extends Database
{
    public $connection;
    protected $db;
    protected $mysqli;
    protected $dbName;
    protected $reservedWords = [
        'order' => true
    ];
    protected $config;
    protected $usingExternalMysqli = false;
    protected $usingExternalPdo = false;

    public function __construct($connection = false, $existingConnection = false, $check = false)
    {
        parent::__construct();

        // Load and set cora config.
        require(dirname(__FILE__).'/../config/config.php');
        require(dirname(__FILE__).'/../config/database.php');

        // Load custom app config
        if (file_exists($config['basedir'].'cora/config/database.php')) {
            include($config['basedir'].'cora/config/database.php');
        }
        if (file_exists($config['basedir'].'cora/config/config.php')) {
            include($config['basedir'].'cora/config/config.php');
        }

        // If a connection was specified, use that. Otherwise use the default DB connection.
        if (!$connection) {
            $connection = $dbConfig['defaultConnection'];
        }
        $this->connection = $connection;

        // Set DB name
        $this->dbName = $dbConfig['connections'][$connection]['dbName'];

        // Define connection info
        $connectionInfo = $dbConfig['connections'][$connection];

        // Check if in TESTING mode
        if (isset($GLOBALS['coraRunningTests']) && $GLOBALS['coraRunningTests'] == true) {
            if (isset($connectionInfo['testOn'])) {
                $testConnection = $connectionInfo['testOn'];
                if (isset($dbConfig['connections'][$testConnection])) {
                    $connectionInfo = $dbConfig['connections'][$testConnection];
                    $this->connection = $testConnection;
                    $this->dbName = $connectionInfo['dbName'];
                }
            }
        }

        ////////////////////////////////////////////
        // Setup MySQLi connection
        ////////////////////////////////////////////

        // Check if an existing connection was passed in...
        if (is_array($existingConnection) && isset($existingConnection['mysqli'])) {
            $this->mysqli = $existingConnection['mysqli'];
            $this->usingExternalMysqli = true;
        }

        // If a database object that has the needed connection was passed in...
        else if (is_subclass_of($existingConnection, '\\Cora\\Database') && $existingConnection->getConnection('mysqli')) {
            $this->mysqli = $existingConnection->getConnection('mysqli');
            $this->usingExternalMysqli = true;
        }

        // Otherwise create new connection.
        else {
            // Create mysqli connection. This is needed for it's escape function to cleanse variable inputs.
            $this->mysqli = new \mysqli($connectionInfo['host'], $connectionInfo['dbUser'], $connectionInfo['dbPass'], $connectionInfo['dbName']);
        }

        ////////////////////////////////////////////
        // Setup PDO connection
        ////////////////////////////////////////////

        // Check if an existing connection was passed in...
        if (is_array($existingConnection) && isset($existingConnection['pdo'])) {
            $this->db = $existingConnection['pdo'];
            $this->usingExternalPdo = true;
        }

        // If a database object that has the needed connection was passed in...
        else if (is_subclass_of($existingConnection, '\\Cora\\Database') && $existingConnection->getConnection('pdo')) {
            $this->db = $existingConnection->getConnection('pdo');
            $this->usingExternalPdo = true;
        }

        // Otherwise create new connection.
        else {
            // Create PDO object for doing our queries.
            $errorMode = null;
            if ($config['mode'] == 'development') {
                $errorMode = array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION);
            }
            $this->db = new \PDO(
                'mysql:host='.$connectionInfo['host'].';dbname='.$connectionInfo['dbName'],
                $connectionInfo['dbUser'],
                $connectionInfo['dbPass'],
                $errorMode
            );
        }

        // Store config values
        $config['database'] = $dbConfig;
        $this->config = $config;
    }

    public function __destruct()
    {
        if (!$this->usingExternalMysqli) {
            $this->mysqli->close();
        }

        if (!$this->usingExternalPdo) {
            $this->db = null;
        }
    }

    public function getConfig()
    {
        return $this->config;
    }

    public function getConnection($name)
    {
        if ($name == 'mysqli') {
            return $this->mysqli;
        }
        else if ($name == 'pdo') {
            return $this->db;
        }
        return false;
    }

    protected function sanitize($value, $dataMember)
    {
        $returnValue = $value;
        if (isset($this->reservedWords[$value])) {
            $returnValue = '`'.$value.'`';
        }
        return $returnValue;
    }

    // Clean user provided input to make it safe for use in a database query.
    public function clean($value)
    {
        return $this->mysqli->real_escape_string($value);
    }

    public function resetToLastMinusLimit()
    {
        $this->wheres = $this->last_wheres;
        $this->distinct = $this->last_distinct;
        $this->ins = $this->last_ins;
        $this->groupBys = $this->last_groupBys;
        $this->havings = $this->last_havings;
        $this->joins = $this->last_joins;
    }

    /**
     *
     */
    public function custom($query, $variables = [])
    {
      $this->customQuery = $query;
      $this->customValues = $variables;
      return $this;
    }

    /**
     *
     */
    protected function execCustom()
    {
      $preppedQuery = $this->customQuery;

      // Replace instances of arrays such as ":ids" with a list ":id1, :id2, :id3, ..."
      foreach($this->customValues as $key => $value) {
        if (is_array($value)) {
          // Generage the string we want to insert in place of the variable
          $str = $this->parseArray(":$key", $value);
          $preppedQuery = preg_replace('/:'.$key."(?!\w)/", $str, $preppedQuery);
        }
      }

      // Sent the query string to the database for preparation
      try {
        $this->customStmt = $this->db->prepare($preppedQuery);
      }
      catch (\PDOException $e) {
        if ($this->config['mode'] == 'development') {
            echo $preppedQuery;
        }
        $this->reset();
        throw $e;
      }

      // Do any values bindings necessary
      foreach($this->customValues as $key => $value) {
        if (is_array($value)) {
          $this->bindArray(":$key", $value);
        } else {
          $this->bind(":$key", $value);
        }
      }

      // Execute the prepped query
      $this->customStmt->execute();

      // Reset query object
      $this->reset();

      // Return Result
      $dbResult = new Db_MySQLResult($this->customStmt, $this->db);
      return $dbResult;
    }

    /**
     *
     */
    public function bind($param, $value, $type = null) {
      if (is_null($type)) {
        switch (true) {
          case is_int($value):
            $type = \PDO::PARAM_INT;
            break;
          case is_bool($value):
            $type = \PDO::PARAM_BOOL;
            break;
          case is_null($value):
            $type = \PDO::PARAM_NULL;
            break;
          default:
            $type = \PDO::PARAM_STR;
        }
      }
      $this->customStmt->bindValue($param, $value, $type);
    }

    /**
     *  Iterates over an array binding each element.
     *  Giving it ":id" for the param would result in the bindings of:
     *  :id1,
     *  :id2,
     *  :id3, etc
     */
    public function bindArray($param, $values, $type = null)
    {
      foreach ($values as $index => $value) {
        $this->bind($param.$index, $value, $type);
      }
    }

    /**
     *  Returns a string representing an array where each element is bound.
     *  Giving it ":id" for the param would result in:
     *  ":id1,:id2,:id3", etc
     */
    public static function parseArray($param, $values)
    {
        $str = "";
        foreach($values as $index => $value){
          $str .= $param.$index.",";
        }
        return rtrim($str,",");
    }

    // Create SQL string and execute it on our database.
    public function exec()
    {
      // If there's a custom query to execute, do that instead of building one.
      if ($this->customQuery) {
        return $this->execCustom();
      }

      // Save copy of relevant data so we can calculate the total rows of this query
      // Does not save LIMIT as this is for use with pagination.
      $this->last_wheres = $this->wheres;
      $this->last_distinct = $this->distinct;
      $this->last_ins = $this->ins;
      $this->last_groupBys = $this->groupBys;
      $this->last_havings = $this->havings;
      $this->last_joins = $this->joins;

      // Execute this query
      $this->calculate();
      try {
          $result = $this->db->query($this->query);
      }
      catch (\PDOException $e) {
          if ($this->config['mode'] == 'development') {
              echo $this->getQuery();
          }
          $this->reset();
          throw $e;
      }
      $this->reset();

      // Return Result
      $dbResult = new Db_MySQLResult($result, $this->db);
      return $dbResult;
    }

    public function startTransaction()
    {
        $this->db->beginTransaction();
    }

    public function commit()
    {
        $this->db->commit();
    }

    public function rollBack()
    {
        $this->db->rollBack();
    }

    public function emptyDatabase()
    {
        $sql = "
                USE $this->dbName;
                SET FOREIGN_KEY_CHECKS = 0;
                SET GROUP_CONCAT_MAX_LEN=32768;
                SET @tables = NULL;
                SELECT GROUP_CONCAT('`', table_name, '`') INTO @tables
                  FROM information_schema.tables
                  WHERE table_schema = (SELECT DATABASE());
                SELECT IFNULL(@tables,'dummy') INTO @tables;

                SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);
                PREPARE stmt FROM @tables;
                EXECUTE stmt;
                DEALLOCATE PREPARE stmt;
                SET FOREIGN_KEY_CHECKS = 1;
        ";

        $result = $this->db->query($sql);
        $this->reset();
        return $result;
    }

    public function tableExists($name)
    {
        $result = $this->db->query("SHOW TABLES LIKE '$name'")->rowCount() > 0;
        $this->reset();
        return $result;
    }

    /**
     *
     */
    protected function calculateCustom()
    {
      $preppedQuery = $this->customQuery;

      // Replace instances of arrays such as ":ids" with a list ":id1, :id2, :id3, ..."
      foreach($this->customValues as $key => $value) {
        if (is_array($value)) {
          $str = $this->parseArray(":$key", $value);
          $preppedQuery = preg_replace('/:'.$key."(?!\w)/", $str, $preppedQuery);
        }
      }

      // Do any values bindings necessary
      foreach($this->customValues as $key => $value) {
        if (is_array($value)) {
          $values = $value;
          foreach ($values as $i => $v) {
            $preppedQuery = preg_replace('/:'.$key.$i."(?!\w)/", $v, $preppedQuery);
          }
        } else {
          $preppedQuery = preg_replace('/:'.$key."(?!\w)/", $value, $preppedQuery);
        }
      }

      // Return Result
      return $preppedQuery;
    }

    /**
     * Create the SQL string from Database class raw data.
     */
    protected function calculate()
    {
      // Determine Action
      $action = false;
      $actions = 0;
      if($this->delete) {
        $actions += 1;
        $action = 'DELETE';
      }
      if(!empty($this->inserts)) {
        $actions += 1;
        $action = 'INSERT';
      }
      if(!empty($this->updates)) {
        $actions += 1;
        $action = 'UPDATE';
      }
      if(!empty($this->selects)) {
        $actions += 1;
        $action = 'SELECT';
      }
      if(!empty($this->create)) {
        $actions += 1;
        $action = 'CREATE';
      }
      if ($actions > 1) {
        throw new \Exception("More than one query action specified! When using Cora's query builder class, only one type of query (select, update, delete, insert) can be done at a time.");
      }
      else {
          $calcMethod = 'calculate'.$action;
          $this->$calcMethod();
      }
    }

    // Create a SELECT statement
    protected function calculateSELECT()
    {
        $this->query .= 'SELECT ';

        // If distinct
        if ($this->distinct) {
            $this->query .= ' DISTINCT ';
        }

        // If SELECT
        $this->queryStringFromArray('selects', '', ', ');

        // Determine Table(s)
        $this->queryStringFromArray('tables', ' FROM ', ', ');

        // Join
        $this->joinStringFromArray('joins');

        // Where and IN
        $this->conditionStringFromArray('wheres', ' WHERE ', ' AND ');

        // GroupBy
        $this->queryStringFromArray('groupBys', ' GROUP BY ', ', ');

        // Having
        $this->conditionStringFromArray('havings', ' HAVING ', ' AND ');

        // OrderBy
        $this->queryStringFromArray('orderBys', ' ORDER BY ', ', ', false);

        // Limit
        if ($this->limit) {
            $this->query .= ' LIMIT '.$this->limit;
        }

        // Offset
        if ($this->offset) {
            $this->query .= ' OFFSET '.$this->offset;
        }
    }

    // Create an UPDATE statement.
    protected function calculateUPDATE()
    {
        $this->query .= 'UPDATE ';

        // Determine Table(s)
        $this->queryStringFromArray('tables', '', ', ');

        // SETs
        $this->queryStringFromArray('updates', ' SET ', ', ');

        // Where and IN
        $this->conditionStringFromArray('wheres', ' WHERE ', ' AND ');

        // OrderBy
        $this->queryStringFromArray('orderBys', ' ORDER BY ', ', ', false);

        // Limit
        if ($this->limit) {
            $this->query .= ' LIMIT '.$this->limit;
        }
        //echo $this->query.'

';
    }

    // Create an INSERT statement.
    protected function calculateINSERT()
    {
        $this->query .= 'INSERT INTO ';

        // Determine Table(s)
        $this->queryStringFromArray('tables', '', ', ');

        // SETs
        if (!empty($this->inserts)) {
            $this->query .= ' (';
            $this->queryStringFromArray('inserts', '', ', ');
            $this->query .= ')';
        }

        // Values
        $this->valueStringFromArray('values', ' VALUES ', ', ');
    }

    // Create a DELETE statement.
    protected function calculateDELETE()
    {
        $this->query .= 'DELETE FROM ';

        // Determine Table(s)
        $this->queryStringFromArray('tables', '', ', ');

        // Where and IN
        $this->conditionStringFromArray('wheres', ' WHERE ', ' AND ');

        // OrderBy
        $this->queryStringFromArray('orderBys', ' ORDER BY ', ', ', false);

        // Limit
        if ($this->limit) {
            $this->query .= ' LIMIT '.$this->limit;
        }
    }

    // Create a CREATE statement
    protected function calculateCREATE()
    {
        $this->query .= 'CREATE TABLE IF NOT EXISTS ';
        $this->query .= $this->create.' (';
        $this->queryStringFromArray('fields', '', ', ', false, true);
        $this->primaryKeyStringFromArray('primaryKeys', ', CONSTRAINT ');
        $this->foreignKeyStringFromArray('foreignKeys', ', CONSTRAINT ');
        $this->indexStringFromArray('indexes', ', INDEX ');
        $this->query .= ')';
    }

    /**
     *  For outputting a string of the following form from the 'indexes' array in Database.
     *  INDEX idx_id_name (id, name)
     */
    protected function IndexStringFromArray($dataMember, $opening, $sep = ', ')
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $this->query .= $opening;
        $constraintName = 'idx';
        $query = ' (';
        $count = count($this->$dataMember);
        for($i=0; $i<$count; $i++) {
            $item = $this->{$dataMember}[$i];
            $constraintName .= '_'.$item;
            $query .= $item;
            if ($count-1 != $i) {
                $query .= $sep;
            }
        }
        $query .= ')';
        $this->query .= $constraintName.' '.$query;
    }

    /**
     *  For outputting a string of the following form from the 'primaryKeys' array in Database.
     *  CONSTRAINT pk_id_name PRIMARY KEY (id, name)
     */
    protected function primaryKeyStringFromArray($dataMember, $opening, $sep = ', ')
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $this->query .= $opening;
        $constraintName = 'pk';
        $query = ' PRIMARY KEY (';
        $count = count($this->$dataMember);
        for($i=0; $i<$count; $i++) {
            $item = $this->{$dataMember}[$i];
            $constraintName .= '_'.$item;
            $query .= $item;
            if ($count-1 != $i) {
                $query .= $sep;
            }
        }
        $query .= ')';
        $this->query .= $constraintName.' '.$query;
    }

    /**
     *  For outputting a string of the following form from the 'foreignKeys' array in Database.
     *  CONSTRAINT fk_name FOREIGN KEY (name) REFERENCES users (name)
     */
    protected function foreignKeyStringFromArray($dataMember, $opening, $sep = ', ')
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        //$query = '';
        $count = count($this->$dataMember);
        for($i=0; $i<$count; $i++) {
            $item = $this->{$dataMember}[$i];

            $this->query .= ', CONSTRAINT '.'fk_'.$item[0].' FOREIGN KEY ('.$item[0].') REFERENCES '.$item[1].' ('.$item[2].')';
            if ($count-1 != $i) {
                $this->query .= $sep;
            }
        }
    }

    /**
     *  Create a string from a single-demensional Database class array.
     *  It calls getArrayItem() for each item and expects the returned result to be a string.
     *  It assumes the following structure:
     *  [
     *      item1,
     *      item2,
     *      item3
     *  ]
     *  An item can be another array if getArrayItem() knows how to translate it into a string.
     */
    protected function queryStringFromArray($dataMember, $opening, $sep, $quote = true, $set = false)
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $this->query .= $opening;
        $count = count($this->$dataMember);
        for($i=0; $i<$count; $i++) {

            // Is this a normal situation, or are we outputting SET values for table creation statement?
            if ($set == false) {
                $this->query .= $this->getArrayItem($dataMember, $i, $quote);
            }
            else {
                // If we are creating a table, then we need to execute a diff method
                // so we can do some type checking on the column value. I.E. 'varchar' = 'varchar[255]'
                $this->query .= $this->getSetItem($dataMember, $i, $quote);
            }

            if ($count-1 != $i) {
                $this->query .= $sep;
            }
        }
    }

    /**
     *  Converts field types to real values that match this adaptor's DB type.
     */
    protected function getSetItem($dataMember, $offset, $quote = true)
    {
        $item = $this->{$dataMember}[$offset];
        switch ($item[1]) {
            case 'varchar':
                $type = 'varchar(255)';
                break;
            default:
                $type = $item[1];
        }
        $this->{$dataMember}[$offset][1] = $type;

        return $this->getArrayItem($dataMember, $offset, $quote);
    }

    /**
     *  When given an array of the following format:
     *  [item1, item2, item3]
     *  This either returns a cleaned single item if "item" is a string,
     *  OR returns a composite string of several variables if "item" is an array.
     *
     *  Single Items Example:
     *  ['table1', 'table2', 'table3'] when getting FROM clause
     *
     *  Items as Array Example:
     *  In the case of Item being an array, it expects it to have exactly 3 values like so:
     *  [column, operator, value]
     *  These three offsets can be finagled to use whatever three pieces of data is appropriate.
     *  Some examples of this in use are:
     *  ['column', '', 'DESC'] when getting ORDER BY clause. Middle offset is not used and left as blank string.
     *  ['name', '=', 'John'] when getting SET column = value clause.
     */
    protected function getArrayItem($dataMember, $offset, $quote = true)
    {
        if(is_array($this->{$dataMember}[$offset])) {
            if (count($this->{$dataMember}[$offset]) == 3) {
                $item = $this->{$dataMember}[$offset];
                $column = $item[0];

                // Normally, Don't include column quotes because the column may be a function like:
                // COUNT(*) which doesn't work if it's entered as `COUNT(*)`.
                // However, in the case of "UPDATE table SET column = value", the column shouldn't be a
                // function, so we want to quote it to avoid conflict with reserved MySQL names.
                if ($dataMember == 'updates') {
                    $column = '`'.$column.'`';
                }

                // If the value is string 'NULL', output without quotes and without cleaning.
                if ($item[2] === 'NULL') {
                    return $column.' '.$item[1]." ".$item[2];
                }
                else {
                    if($quote) {
                       return $column.' '.$item[1]." '".$this->clean($item[2])."'";
                    }
                    else {
                       return $column.' '.$item[1]." ".$this->clean($item[2]);
                    }
                }
            }
            else {
                throw new \Exception("Cora's Query Builder class expects query components to be in an array with form [column, operator, value]");
            }
        }
        else {
            $item = $this->clean($this->{$dataMember}[$offset]);
            if ($dataMember == 'inserts') {
                $item = '`'.$item.'`';
            }
            return $item;
        }
    }

    /**
     *  Create a string from a multi-demensional Database class array.
     *  It calls getArrayCondition() for each item and expects the returned result to be a string.
     *  THIS CLASS IS SPECIFICALLY FOR CONDITIONS (Where, Having).
     *  It assumes the following structure:
     *  [
     *      [
     *          [
     *              [column, operator, value],
     *              [name, LIKE, %s],
     *              [price, >, 100]
     *          ],
     *          AND
     *      ],
     *      [
     *              [column, operator, value, conjunction],
     *              [name, LIKE, %s, OR],
     *              [price, >, 100]
     *          ],
     *          AND
     *      ]
     *  ]
     */
    protected function conditionStringFromArray($dataMember, $opening, $sep)
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $this->query .= $opening;
        $count = count($this->$dataMember);
        for($i=0; $i<$count; $i++) {
            $statement = $this->{$dataMember}[$i];
            $this->query .= '(';
            $sCount = count($statement[0]);
            for($j=0; $j<$sCount; $j++) {

                // See if a custom separator (conjuction) was set, and grab it.
                $customSep = $this->getArrayConditionSep($dataMember, $i, $j);

                $this->query .= $this->getArrayCondition($dataMember, $i, $j);
                if ($sCount-1 != $j) {
                    if ($customSep) {
                        $this->query .= $customSep;
                    }
                    else {
                        $this->query .= $sep;
                    }
                }
            }
            $this->query .= ')';
            if ($count-1 != $i) {
//                echo $dataMember;
//                var_dump($this->$dataMember);
//                var_dump($this->{$dataMember}[$i+1]);
//                echo $i;
                $this->query .= ' '.$this->{$dataMember}[$i+1][1].' ';
            }
        }
    }

    /**
     *  When given an array of the following format:
     *  [column, operator, value]
     *  It returns a composite string of the variables.
     *
     *  If any of the three offsets are missing, it with throw an exception.
     *  Some examples of this in use are:
     *  [$column, '=', $value] when getting WHERE or HAVING clause.
     *  [$column, 'IN', array()] when getting column IN array() clause.
     */
    protected function getArrayCondition($dataMember, $statementNum, $offset)
    {
        if (count($this->{$dataMember}[$statementNum][0][$offset]) >= 3) {
            $item = $this->{$dataMember}[$statementNum][0][$offset];
            $result = '';

            if ($item[1] == 'IN') {
                $searchArea = $item[2];

                // Check if searchArea is array...
                if (is_array($searchArea)) {
                    // Convert the array into a comma delimited string.
                    $str = "'";
                    $size = count($searchArea);
                    for($i=0; $i < $size; $i++) {
                        $str_item = $this->clean($searchArea[$i]);
                        $str = $str.$str_item;
                        if ($i < $size-1) {
                            $str = $str."', '";
                        }
                    }
                    $searchArea = $str."'";
                } else {
                    $searchArea = $this->clean($searchArea);
                }

                // Return string of form 'COLUMN IN (value1, value2, ...)'
                $result = $item[0].' '.$item[1]." (".$searchArea.")";
            }
            else {
                // Return string of form 'COLUMN >= VALUE'
                $column = $this->sanitize($item[0], $dataMember);
                if ($item[2] === 'NULL') {
                    $result = $column.' '.$item[1]." ".$item[2];
                }
                else {
                    $result = $column.' '.$item[1]." '".$this->clean($item[2])."'";
                }
            }
            return $result;
        }
        else {
            throw new \Exception("Cora's Query Builder class expects advanced query components to be in an array with form {column, operator, value [, conjunction]}");
        }
    }

    /**
     *  If the optional 4th array parameter denoting the desired conjunction for the next condition is set
     *  within a condition statement, then return that separator.
     *  E.g. the 'OR' below:
     *  [
     *      ['id', '>', '100', 'OR'],
     *      ['name', 'LIKE', '%s']
     *  ]
     */
    protected function getArrayConditionSep($dataMember, $statementNum, $offset)
    {
        if (isset($this->{$dataMember}[$statementNum][0][$offset][3])) {
            return ' '.$this->{$dataMember}[$statementNum][0][$offset][3].' ';
        }
        return false;
    }

    /**
     *  Almost the same as queryStringFromArray() except that this adds parenthesis
     *  around the query piece and calls getArrayList() instead of getArrayItem().
     *  See queryStringFromArray() description.
     *  This is used for getting the INSERT VALUES in an insert statement.
     *
     *  E.g. VALUES ('bob', 'bob@gmail.com', 'admin'), ('john', 'john@gmail.com', 'user')
     *  From an array with the following format:
     *  [
     *      ['bob', 'bob@gmail.com', 'admin'],
     *      ['john', 'john@gmail.com', 'user']
     *  ]
     *  For each sub-array it creates an insert expression.
     */
    protected function valueStringFromArray($dataMember, $opening, $sep, $quote = true)
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $this->query .= $opening;
        $count = count($this->$dataMember);
        $result = '';
        $addParenthesis = false;
        for($i=0; $i<$count; $i++) {
            if (!is_array($this->{$dataMember}[$i])) {
                $addParenthesis = true;
            }
            $result .= $this->getValuesList($dataMember, $i);
            if ($count-1 != $i) {
                $result .= $sep;
            }
        }
        if ($addParenthesis) {
            $this->query .= '('.$result.')';
        }
        else {
            $this->query .= $result;
        }
    }

    /**
     *  Returns a string for the VALUES (value1, value2, value3), (value1, value2, value3), ...
     *  part of an INSERT statement.
     */
    protected function getValuesList($dataMember, $offset)
     {
         if(is_array($this->{$dataMember}[$offset])) {
             $items = $this->{$dataMember}[$offset];
             $count = count($items);
             $result = ' (';
             for($i=0; $i<$count; $i++) {

                 if ($items[$i] == 'NULL') {
                     $result .= $items[$i];
                 }
                 else {
                     $result .= "'".$this->clean($items[$i])."'";
                 }

                 if ($count-1 != $i) {
                     $result .= ', ';
                 }
             }
             $result .= ')';
             return $result;
         }
         else {
             if ($this->{$dataMember}[$offset] == 'NULL') {
                 return $this->{$dataMember}[$offset];
             }
             else {
                 return "'".$this->clean($this->{$dataMember}[$offset])."'";
             }
         }
     }

    /**
     *  For creating a JOIN string expression from the database class arrays holding JOIN
     *  data.
     *
     */
    protected function joinStringFromArray($dataMember, $sep = ' AND ')
    {
        if (empty($this->$dataMember)) {
            return 0;
        }
        $count = count($this->$dataMember);
        //var_dump($this->$dataMember);
        for($i=0; $i<$count; $i++) {
            $statement = $this->{$dataMember}[$i];
            $this->query .= ' '.$statement[2].' JOIN '.$statement[0].' ON ';
            $sCount = count($statement[1]);
            for($j=0; $j<$sCount; $j++) {
                $this->query .= $this->getArrayJoin($dataMember, $i, $j);
                if ($sCount-1 != $j) {
                    $this->query .= $sep;
                }
            }
        }
    }

    /**
     *  Returns a string in "table1.column = table2.column" format.
     *  This method differs from getArrayCondition() not only because it doesn't have to take
     *  into account IN operators and is simpler because of it, but mainly because it doesn't
     *  wrap the VALUE in "column = value" in parenthesis because the expected value field is a table reference.
     */
    protected function getArrayJoin($dataMember, $statementNum, $offset)
    {
        if (count($this->{$dataMember}[$statementNum][1][$offset]) == 3) {
            $item = $this->{$dataMember}[$statementNum][1][$offset];
            return $this->clean($item[0]).' '.$item[1]." ".$this->clean($item[2]);
        }
        else {
            throw new \Exception("Cora's Query Builder class expects advanced query components to be in an array with form [column, operator, value]");
        }
    }

    /**
     *  Return a data type.
     */
    public function getType($props)
    {
        $result = '';
        if (isset($props['type'])) {

            // If field is a string
            if ($props['type'] == 'varchar' || $props['type'] == 'string') {
                if (isset($props['size'])) {
                    $result = 'varchar('.$props['size'].')';
                }
                else {
                    $result = 'varchar(255)';
                }
            }

            // If field is an Int
            else if ($props['type'] == 'int' || $props['type'] == 'integer') {
                if (isset($props['size'])) {
                    $result = 'int('.$props['size'].')';
                }
                else {
                    $result = 'int';
                }
            }

            // If field is a float
            else if ($props['type'] == 'float' || $props['type'] == 'double') {
                if (isset($props['size']) && isset($props['precision'])) {
                    $result = 'float('.$props['size'].', '.$props['precision'].')';
                }
                else {
                    $result = 'float';
                }
            }

            // If field is a date
            else if ($props['type'] == 'date') {
                $result = 'date';
            }

            // If field is a datetime
            else if ($props['type'] == 'datetime') {
                $result = 'datetime';
            }

            // If field is an enum
            else if ($props['type'] == 'enum') {
                if (isset($props['enum'])) {
                    $result = 'ENUM('.$props['enum'].')';
                }
                else {
                    $result = "ENUM('default')";
                }
            }

            // If nothing matches, just try returning what was set.
            else {
                if (isset($props['size'])) {
                    $result = $props['type'].'('.$props['size'].')';
                }
                else {
                    $result = $props['type'];
                }
            }
        }
        else {
            return 'varchar(255)';
        }
        return $result;
    }

    /**
     *  Return a field's attributes
     */
    public function getAttributes($props)
    {
        $attr = '';

        if (isset($props['primaryKey'])) {
            $attr .= 'NOT NULL AUTO_INCREMENT ';
        }

        if (isset($props['defaultValue'])) {
            $attr .= "DEFAULT '".$props['defaultValue']."'";
        }

        return $attr;
    }

    /**
     *  Set an index if defined.
     */
    public function setIndex($key, $props)
    {
        if (isset($props['index'])) {
            $this->index($key);
        }
    }

    public function field($name, $type, $attributes = ' ')
    {
        // Set MySQL quotes around field. If this doesn't get done, then certain named fields
        // such as 'group' will cause an error because they are reserved.
        $name = '`'.$name.'`';

        $this->store('keyValue', 'fields', $name, $attributes, $type);
        return $this;
    }

}


<?php
namespace Volantus\FlightBase\Src\General\Generic;

use Volantus\FlightBase\Src\Server\Messaging\IncomingMessage;
use Volantus\FlightBase\Src\Server\Messaging\MessageFactory;
use Volantus\FlightBase\Src\Server\Network\NetworkRawMessage;

/**
 * Class GenericInternalMessageFactory
 *
 * @package Volantus\FlightBase\Src\General\Generic
 */
class GenericInternalMessageFactory extends MessageFactory
{
    /**
     * @var string
     */
    protected $type = GenericInternalMessage::TYPE;

    /**
     * @param NetworkRawMessage $rawMessage
     *
     * @return IncomingMessage
     */
    public function create(NetworkRawMessage $rawMessage): IncomingMessage
    {
        $data = $rawMessage->getData();
        $this->validateString($data, 0);

        $payload = @unserialize($data[0]);
        if ($payload !== false) {
            if (is_object($payload)) {
                return new IncomingGenericInternalMessage($rawMessage->getSender(), $payload);
            } else {
                throw new \InvalidArgumentException('Unserialized payload is not an object => ' . var_export($payload, true));
            }
        } else {
            throw new \InvalidArgumentException('Generic message payload is not unserializeable. Data: ' . $data[0]);
        }
    }
}


<?php

declare(strict_types=1);

namespace Chubbyphp\Config;

final class ConfigProvider implements ConfigProviderInterface
{
    /**
     * @var string
     */
    private $rootDir;

    /**
     * @var string[]
     */
    private $configMappings = [];

    /**
     * @var ConfigInterface[]
     */
    private $configs = [];

    /**
     * @param string                   $rootDir
     * @param ConfigMappingInterface[] $configMappings
     */
    public function __construct(string $rootDir, array $configMappings)
    {
        $this->rootDir = $rootDir;
        foreach ($configMappings as $configMapping) {
            $this->addMapping($configMapping);
        }
    }

    /**
     * @param ConfigMappingInterface $configMapping
     */
    private function addMapping(ConfigMappingInterface $configMapping)
    {
        $this->configMappings[$configMapping->getEnvironment()] = $configMapping->getClass();
    }

    /**
     * @param string $environment
     *
     * @return ConfigInterface
     *
     * @throws ConfigException
     */
    public function get(string $environment): ConfigInterface
    {
        if (!isset($this->configMappings[$environment])) {
            throw ConfigException::createByEnvironment($environment);
        }

        if (!isset($this->configs[$environment])) {
            $class = $this->configMappings[$environment];

            $this->configs[$environment] = $class::create($this->rootDir);
        }

        return $this->configs[$environment];
    }
}


<?php

/*
 * Monolog Cli formatter
 *
 * (c) Pavel Tetyaev <pahanini@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace pahanini\Monolog\Formatter;

use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger;

/**
 * Monolog CLI Formatter.
 *
 * Useful for tests
 */
class CliFormatter extends NormalizerFormatter
{
    const TAB = '    ';

    /**
     * @var array
     */
    public $colors = [
        LOGGER::DEBUG     => '0;2',
        LOGGER::INFO      => '0;32',
        LOGGER::NOTICE    => '1;33',
        LOGGER::WARNING   => '0;35',
        LOGGER::ERROR     => '0;31',
        LOGGER::CRITICAL  => ['0;30', '43'],
        LOGGER::ALERT     => ['1;37', '45'],
        LOGGER::EMERGENCY => ['1;37', '41'],
    ];

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        $lines = [Logger::getLevelName($record['level']).' : '.$record['message']];
        if (!empty($record['context'])) {
            $lines += explode(PHP_EOL, trim(json_encode($record['context'], JSON_PRETTY_PRINT)));
        }
        $max = max(array_map('strlen', $lines));
        for ($i = 1; $i < count($lines); $i++) {
            $lines[$i] = self::TAB.str_pad($lines[$i], $max + 5);
        }
        $string = implode(PHP_EOL, $lines);
        $colors = $this->colors[$record['level']];
        if (is_array($colors)) {
            $pad = PHP_EOL.str_repeat(self::TAB.str_repeat(' ', $max + 5).PHP_EOL, 2);

            return "\n\033[{$colors[0]}m\033[{$colors[1]}m".$pad.$string.$pad."\033[0m";
        } else {
            return "\n\033[{$colors}m".$string."\033[0m";
        }
    }
}