Hey.... Now I release some scripts It's table.php, which makes designing for gesior aac veeery simple Ofcourse you need to learn how to use it first too
Also I will release Feedback System ! Where players can send in their ideas about server, and you can comment back etc... Same as in The Otserver - Feedback
table.php (if you want feedback script you need it too)
Now the feedback script. I have to inform you that it is A LITTLE bit "not-perfect". But it won't affect you that unless you are really picky!
Features:
Then you need those functions (place in config-and-functions.php):
Database table:
Images needed (should be in folder specified in script): icons.rar
Anything to ask, tell me I might have missed something !
Also I will release Feedback System ! Where players can send in their ideas about server, and you can comment back etc... Same as in The Otserver - Feedback
table.php (if you want feedback script you need it too)
PHP:
<?php
/*--------------------------*/
##############################
// @Title: Table Classes //
// @Version: 1.2.7 //
// @Author: Colandus //
##############################
/*--------------------------*/
class AttributeList {
private $attributes = array();
function add($k, $v) {
if(!(string)$k && !(string)$v)
return false;
$this->attributes[$k] = $v;
return true;
}
function find($k) {
return $this->attributes[$k];
}
function get($k = false) {
if($k) {
if(!is_string($k))
return false;
return $attributes[$k];
}
return $this->attributes;
}
function remove($k) {
if(!$this->attributes[$k])
return false;
unset($this->attributes[$k]);
return true;
}
function to_string() {
foreach($this->attributes as $k => $v) {
$str .= ($k . '="' . $v . '" ');
}
return $str;
}
}
class Table {
private $attributes, $defaultAttributes;
protected $rows;
function __construct() {
$this->rows = array();
$this->attributes = new AttributeList;
$this->defaultAttributes = new AttributeList;
}
function add_row(Row $row = null, $default = false) {
if(!$row)
$row = new Row;
if(!$row || $default) {
while(list($k, $v) = $this->defaultAttributes->iterate())
$row->set_attribute($k, $v);
}
$this->rows[] = $row;
return $row;
}
function set_default_attribute($k, $v) {
return $this->defaultAttributes->add($k, $v);
}
function get_count() {
return count($this->rows);
}
function get_rows($id = false) {
if($id !== false) {
if($row = $this->rows[(int)$id])
return $row;
} else
return $this->rows;
return false;
}
function set_attribute($k, $v) {
return $this->attributes->add($k, $v);
}
function remove_attribute($k) {
return $this->attributes->remove($k);
}
function show() {
if($this->get_count() > 0) {
// Auto colspan.
$maxColumns = 0;
foreach($this->rows as $row)
if($row->get_count() > $maxColumns)
$maxColumns = $row->get_count();
write('<table ' . $this->attributes->to_string() . '>');
foreach($this->rows as $row) {
$columns = $row->get_count();
if(($column = $row->get_columns(1)) && $columns > 0 && $columns < $maxColumns)
$column->set_attribute('colspan', $maxColumns - $columns + 1);
$row->show();
}
write('</table>');
}
return true;
}
}
class Row {
private $columns, $attributes, $defaultAttributes;
function __construct() {
$this->columns = array();
$this->attributes = new AttributeList;
$this->defaultAttributes = new AttributeList;
}
function add_column($val, $default = false) {
if($check = (!$val instanceof Column)) {
if(!is_string($val))
return false;
$val = new Column($val);
}
if(!$check || $default) {
foreach($this->defaultAttributes->get() as $k => $v)
$val->set_attribute($k, $v);
}
$this->columns[] = $val;
return $val;
}
function set_default_attribute($k, $v) {
return $this->defaultAttributes->add($k, $v);
}
function set_attribute($k, $v) {
return $this->attributes->add($k, $v);
}
function get_count() {
return count($this->columns);
}
function get_columns($id = false) {
if($id !== false) {
if(is_numeric($id) && ($column = $this->columns[--$id]))
return $column;
} else
return $this->columns;
return false;
}
function show() {
if($this->get_count() > 0) {
write('<tr ' . $this->attributes->to_string() . '>');
foreach($this->columns as $column)
$column->show();
write('</tr>');
return true;
}
return false;
}
}
class Column {
protected $text;
private $attributes;
function __construct($text) {
$this->set_text($text);
$this->attributes = new AttributeList;
}
function set_text($text) {
if(!is_string($text))
return false;
$this->text = $text;
return true;
}
function put_text($text) {
return $this->set_text($this->text . $text);
}
function set_attribute($k, $v) {
return $this->attributes->add($k, $v);
}
function show() {
write('<td ' . $this->attributes->to_string() . '>' . $this->text . '</td>');
return true;
}
}
class OTSTable extends Table {
function __construct($text = false) {
parent::__construct();
$this->set_attribute('align', 'center');
$this->set_attribute('border', 0);
$this->set_attribute('cellspacing', 1);
$this->set_attribute('cellpadding', 4);
$this->set_attribute('width', '100%');
if($text !== false)
$this->add_title_row($text);
}
function add_title_row($text) {
$row = parent::add_row(new OTSRow);
$row->set_attribute('bgcolor', get_title_color());
$column = $row->add_column('<b>' . $text . '</b>');
$column->set_attribute('align', 'center');
$column->set_attribute('class', 'white');
$column->set_attribute('style', 'font-weight: bold;');
OTSRow::$i--;
return $row;
}
function add_row(Row $row = null) {
if(!$row)
$row = new OTSRow;
return parent::add_row($row);
}
}
class OTSRow extends Row {
public static $i = 0;
function __construct() {
parent::__construct();
$this->set_attribute('bgcolor', get_color(OTSRow::$i++));
}
function add_column($val) {
if($val instanceof Column)
return parent::add_column($val);
elseif(is_string($val))
return parent::add_column(new OTSColumn($val));
return false;
}
}
class OTSColumn extends Column {
private $icons;
function __construct($text) {
parent::__construct($text);
$this->icons = array();
}
function add_icon($image, $align = 'left', $title = false, $url = false) {
if(($align != 'left' && $align != 'right') || !is_string($image) || !file_exists($image))
return false;
$this->icons[] = array($image, $align, $title, $url);
return count;
}
function remove_icon($id) {
if(!is_numeric($id))
return false;
if(!$this->icons[--$id])
return false;
unset($this->icons[$id]);
return true;
}
function get_icons() {
return count($this->icons);
}
function show() {
$text = $this->text;
$indent = array();
$this->text = '<div style="position: relative">' . $text;
foreach($this->icons as $icon) {
list($image, $align, $title, $url) = $icon;
if(!isset($indent[$align]))
$indent[$align] = 0;
if(is_string($url))
$this->text .= '<a href="' . $link . '">';
$this->text .= '<img ' . (is_string($title) ? 'title="' . $title . '" ' : '') . 'style="position: absolute; ' . $align . ': ' . (4 + 25 * $indent[$align]) . 'px;" src="' . $image . '" />';
if(is_string($url))
$this->text .= '</a>';
$indent[$align]++;
}
$this->text .= '</div>';
parent::show();
$this->text = $text;
}
}
?>
Now the feedback script. I have to inform you that it is A LITTLE bit "not-perfect". But it won't affect you that unless you are really picky!
Features:
- Use BBCode tags (bold, italic, underline, center)
- Choose feedback type (Suggestion, Complaint etc, you can add your own ones too!)
- If you're logged in already, you will choose character from list, otherwise you will write any other name there
- Ability to preview feedback before sending
- Ability to see feedbacks sent by your IP address
- Admin Panel
- Set statuses of feedbacks (unread, accepted etc...)
- Delete feedbacks
- Comment to feedbacks (poster of feedback will be able to review your comment but not reply to it)
- See IP address of poster
PHP:
<?php
/*--------------------------*/
##############################
// @Title: Feedback Form //
// @Version: 1.4 //
// @Author: Colandus //
##############################
/*--------------------------*/
//////////////||\\\\\\\\\\\\\\
//..........CONFIG..........\\
##############################
$image_path = 'images/icons/';
$textarea_cols = 60; // Edit size of the textareas (where you write) width
$send_interval = 1 * 24 * 60 * 60; // Interval to send posts.
$send_amount = 3; // Amount of posts that can be sent within the interval.
$max_name_length = 14; // Maximum length of character name to be displayed.
$max_title_length = 100 - 3; // Maximum length of title to be sent (- 3 for adding dots).
$min_title_length = 10; // Minimum length of title to be sent.
$min_text_length = 15; // Minimum length of text to be sent.
$statuses = array(
0 => 'unread', // Available feedback statuses.
1 => 'observed', // The rules for adding/removing statuses is same as in types,
2 => 'accepted', // check comments below !
3 => 'completed',
4 => 'rejected'
);
$types = array(
0 => 'suggestion', // Available feedback types. Note that feedback types are stored by array index
1 => 'bug report', // in database, so when you add a new type you have to place it in bottom and
2 => 'complaint', // when removing one, you have to put it in disabled types with same index.
4 => 'other'
);
$disabledTypes = array(
3 => 'application' // Feedback types that once existed but was removed.
);
$tags = array('b', 'i', 'u', 'center'); // BBCode tags usable in text.
##############################
//..........CONFIG..........\\
//////////////||\\\\\\\\\\\\\\
class Feedback {
static function get_status($id) {
return $statuses[$id];
}
static function set_status($id, $status) {
if(!(self::get($id) || self::get_status($status)))
return false;
self::query('UPDATE `feedback` SET `status` = ' . $status . ' WHERE `id` = ' . $id . ';');
}
private function query($sql) {
return $GLOBALS['SQL']->query($sql);
}
static function get($id) {
if(!is_numeric($id))
return false;
$feedback = self::query('SELECT * FROM `feedback` WHERE `id` = ' . $id . ';')->fetch();
return ($feedback['id'] ? $feedback : false);
}
static function delete($id) {
if(!self::get($id))
return false;
self::query('DELETE FROM `feedback` WHERE `id` = ' . $id . ';');
return true;
}
static function show($val) {
if(is_array($val))
$feedback = $val;
elseif(!$feedback = Feedback::get($val))
return false;
$sid = $feedback['status'];
$name = $feedback['name'];
if(strlen($name) > 0) {
if($feedback['self'])
$name = '<a href="?subtopic=characters&name=' . urlencode($name) . '">' . $name . '</a>';
} else
$name = '<i>Unknown Player</i>';
$text = $feedback['text'];
$text = htmlspecialchars($text);
$text = stripslashes($text);
$text = nl2br($text);
global $tags, $image_path, $statuses;
$types = $GLOBALS['types'] + $GLOBALS['disabledTypes'];
foreach($tags as $tag)
$text = preg_replace("/\[$tag\](.*?)\[\/$tag\]/", "<$tag>$1</$tag>", $text);
$status = $statuses[$sid];
$title = $feedback['title'];
$table = new OTSTable(short_text($title, 75));
$table->set_attribute('style', 'margin-bottom: 7px;');
$column = $table->get_rows(0)->get_columns(1);
$column->add_icon($image_path . $status . '_tiny.png', 'left', ucwords($status));
if($feedback['locked'])
$column->add_icon($image_path . 'locked_tiny.png', 'right', 'Locked');
$response = $feedback['response'];
if($response)
$column->add_icon($image_path . 'response.png', 'left', 'Response received');
$row = $table->add_row();
$row->set_default_attribute('align', 'center');
$column = $row->add_column('<b>' . ucwords($types[$feedback['type']]) . '</b>');
$column->set_attribute('width', 120);
$column = $row->add_column('<span title="' . long2ip($feedback['ip']) . '">' . $name . '</span>');
$column = $row->add_column('<span style="font-style: italic; font-size: 11px;">' . date("Y-m-d H:i:s", $feedback['time']) . '</span>');
$column->set_attribute('width', 140);
$row = $table->add_row();
$column = $row->add_column($text);
$column->set_attribute('style', 'padding: 15px; font: normal 11px verdana;');
if($response) {
$response = htmlspecialchars($response);
$response = stripslashes($response);
$response = nl2br($response);
$row = $table->add_row();
$column = $row->add_column('<span style="color: red;"><i>' . $response . '</i></span>');
$column->set_attribute('style', 'padding: 15px; font: normal 11px verdana;');
}
write('</table>');
return $table;
}
static function show_short($id) {
if(!$feedback = Feedback::get($id))
return false;
$title = $feedback['title'];
$title = htmlentities($title);
global $i, $image_path;
$types = $GLOBALS['types'] + $GLOBALS['disabledTypes'];
$row = new OTSRow;
$column = $row->add_column(ucwords($types[$feedback['type']]));
$column->set_attribute('width', 110);
$column->set_attribute('align', 'center');
$column = $row->add_column('<a title="' . $title . '" href="' . get_location(true) . '&id=' . $feedback['id'] . '">' . short_text($title, 50) . '</a>');
$column->set_attribute('align', 'center');
if(strlen($feedback['response']) > 0)
$column->add_icon($image_path . 'response.png', 'left', 'Response received');
$column = $row->add_column('<span style="font-style: italic; font-size: 11px;">' . date("Y-m-d", $feedback['time']) . '</span>');
$column->set_attribute('width', 90);
$column->set_attribute('align', 'center');
return $row;
}
}
write('<span class="header">Feedback</span>');
if($group_id_of_acc_logged >= $config['site']['access_admin_panel']) {
write('
<b><center>This is the Administrator Panel for the Feedbacks.</center></b>
<br /><br />
');
if(isset($_SESSION['write'])) {
write('<i>' . $_SESSION['write'] . '</i><br /><br />');
unset($_SESSION['write']);
}
if(isset($_GET['id'])) {
$fid = (int)$_GET['id'];
if($table = Feedback::show($fid)) {
$table->show();
$feedback = Feedback::get($fid);
write('<form action="' . get_location() . '" method="post">');
$responseTable = new OTSTable('Response');
$responseTable->set_attribute('style', 'margin-bottom: 7px;');
$row = $responseTable->add_row();
$column = $row->add_column('<textarea name="response" rows="6" cols="87">' . stripslashes($feedback['response']) . '</textarea>');
$column->set_attribute('align', 'center');
$row = $responseTable->add_row();
$row->add_column('<input type="submit" value="Save Response" />');
$responseTable->show();
write('</form><div style="border: 1px black solid;">');
$sid = $feedback['status'];
foreach($statuses as $id => $status)
if($id == $sid)
write('<img title="Status is currently: ' . ucwords($status) . '" src="' . $image_path . $status . '_small.png" /> ');
else
write('<a href="?subtopic=' . $_GET['subtopic'] . '&id=' . $fid . '&status=' . $id . '"><img title="Set status to: ' . ucwords($status) . '" src="' . $image_path . $status . '.png" /></a> ');
write('<a href="?subtopic=' . $_GET['subtopic'] . '&id=' . $fid . '&delete"><img style="position: relative; margin-left: 620px;" title="Delete permanently" src="' . $image_path . 'delete.png" /></a></div><br /><br /><br />');
if(isset($_GET['status'])) {
$status = (int)$_GET['status'];
if($statuses[$status]) {
Feedback::set_status($fid, $status);
$_SESSION['write'] = 'Status has successfully been changed to ' . $statuses[$status] . '!';
send_back(true);
}
} elseif(isset($_GET['delete'])) {
Feedback::delete($fid);
$_SESSION['write'] = 'Feedback has been deleted successfully and cannot be restored!';
send_back(true);
} elseif(isset($_POST['response'])) {
// Feedback::update($fid, 'response', $response);
$SQL->query('UPDATE `feedback` SET response = ' . $SQL->quote($_POST['response']) . ' WHERE `id` = ' . $fid . ';');
send_back();
}
} else
error('Invalid feedback ID!<br /><br />');
}
if(isset($_GET['toggle'])) {
$flag = pow(2, $_GET['toggle']);
if(($_SESSION['hid'] & $flag) == $flag)
$_SESSION['hid'] ^= $flag;
else
$_SESSION['hid'] |= $flag;
send_back();
}
$hidden = $_SESSION['hid'];
$table = new OTSTable;
foreach($statuses as $id => $status) {
$flag = pow(2, $id);
$hide = ($hidden & $flag) == $flag;
$row = $table->add_title_row('<b>' . ucwords($status) . ' Feedbacks</b>');
if(!$hide) {
$feedbacks = $SQL->query('SELECT `id` FROM `feedback` WHERE `status` = ' . $id . ' ORDER BY `time` DESC;');
foreach($feedbacks as $feedback)
$ret = $table->add_row(Feedback::show_short($feedback['id']));
if(!$ret) {
$row = $table->add_row();
$column = $row->add_column('<i>There are no ' . $status . ' feedbacks</i>');
$column->set_attribute('align', 'center');
}
}
$table->add_row(new Row)->add_column(new Column(''))->set_attribute('style', 'margin-bottom: 20px;');
}
$table->show();
} else {
write('
<b>Have you ever thought of a great feature that could be added to the game?
Do you know anything that could be improved, or do you have any complaints on things that you dislike, or like less?
Here is the right place to show us what you think should be changed or added!
We wish all of our players to enjoy the game as much as possible. By sending us suggestions, we can make the gameplay more fun for our players!<br /><br />
If you have any complaint or bug report, please try to write as detailed as possible to ease the proccess of solving this issue.
<u>DO NOT REPORT PLAYERS NOR COMPLAIN ON A BANISHMENT HERE!</u></b><br /><br />
');
$longip = ip2long($_SERVER['REMOTE_ADDR']);
$today_feedbacks = $SQL->query('SELECT COUNT(`id`) AS `count` FROM `feedback` WHERE `ip` = ' . $longip . ' AND `time` > ' . (time() - $send_interval) . ';')->fetch();
$today_count = $today_feedbacks['count'];
if($today_count >= $send_amount)
error('You have already sent ' . $send_amount . ' feedbacks today. We highly appreciate it, but to avoid spam we have limited the max amount of messages per day.');
else {
write('
By writing your characters name in the text field (or select it from the list if you are logged into your account), we might reward you for the feedback, depending on how much we need/like it.
<br /><br />
');
$table = new OTSTable('Available BBCode');
$table->set_attribute('width', 350);
foreach($tags as $tag) {
$row = $table->add_row();
$row->add_column('[' . $tag . ']the text[/' . $tag . ']');
$column = $row->add_column('<' . $tag . '>the text</' . $tag . '>');
$column->set_attribute('width', 100);
}
$table->show();
write('<br /><br />');
if(isset($_POST['type'])) {
$type = (int)$_POST['type'];
if($types[$type]) {
$title = $_POST['title'];
if(strlen($title) >= $min_title_length) {
$text = $_POST['text'];
if(strlen($text) >= $min_text_length) {
$name = $_POST['name'];
if(!empty($name)) {
if(check_name($name)) {
$self = !$_POST['self'] ? 0 : 1;
if($self)
if($logged) {
$characters = $account_logged->getPlayersList();
foreach($characters as $character)
if($character->getName() == $name) {
$found = true;
break;
}
if(!$found)
error('Character does not exist in your account!');
} else
error('An unexpected error has occured.');
} else
error('Invalid character name.');
}
if(!isset($ERROR)) {
$title = short_text($title, $max_title_length);
$feedback = array(
"type" => $type,
'title' => $title,
'text' => $text,
'name' => $name,
'self' => $self,
'time' => time()
);
if((int)$_POST['preview'] == 1)
Feedback::show($feedback)->show();
else {
$_SESSION['feedback'] = $feedback;
send_back();
}
}
} else
error('Text must consist of at least ' . $min_text_length . ' characters.');
} else
error('Title must consist of at least ' . $min_title_length . ' characters.');
} else
error('Invalid feedback type.');
write('<br /><br />');
} elseif(isset($_SESSION['feedback'])) {
$feedback = $_SESSION['feedback'];
$title = $SQL->quote($feedback['title']);
$text = $SQL->quote($feedback['text']);
$name = $feedback['name'];
if(strlen($name) > 0)
$name = $SQL->quote($name);
$SQL->query('INSERT INTO `feedback` (`title`, `text`, `name`, `self`, `ip`, `time`, `type`) VALUES(' . $title . ', ' . $text . ', ' . $name . ', ' . $feedback['self'] . ', ' . $longip . ', ' . time() . ', ' . $feedback['type'] . ');');
unset($_SESSION['feedback']);
send_back();
}
$total_feedbacks = $SQL->query('SELECT COUNT(`id`) AS `count` FROM `feedback` WHERE `ip` = ' . $longip . ';')->fetch();
$total_count = max($total_feedbacks['count'], "0");
write('
<i>You have sent <b>' . $today_count . ' / ' . $send_amount . '</b> feedbacks today and <b>' . $total_count . '</b> in total.</i>
<form name="feedback" action="index.php?subtopic=' . $_GET['subtopic'] . '" method="post">
');
$table = new OTSTable('Feedback Form');
$row = $table->add_row();
$row->set_default_attribute('align', 'center');
$column = $row->add_column('Type: <select name="type">');
$column->set_attribute('width', 160);
foreach($types as $id => $type)
$column->put_text('<option ' . (isset($_POST['type']) && $_POST['type'] == $id ? 'selected' : '') . ' value="' . $id . '">' . ucwords($type) . '</option>');
$column->put_text('</select>');
$column = $row->add_column('Title: <input type="text" value="' . $_POST['title'] . '" size="40" name="title" />');
$column = $row->add_column('Character: ');
$column->set_attribute('width', 230);
$hasChar = false;
if($logged) {
$characters = $account_logged->getPlayersList();
$characters->orderBy('level');
if($characters->count() > 0) {
$hasChar = true;
$column->put_text('<select name="name" style="width: 135px;">');
foreach($characters as $character) {
$name = short_text($character->getName(), $max_name_length);
$column->put_text('<option value="' . $character->getName() . '">' . $name . '</option>');
}
$column->put_text('</select>');
}
}
if(!$hasChar)
$column->put_text('
<input type="text" value="' . $_POST['name'] . '" name="name" />
<input type="hidden" name="self" value="' . ($hasChar ? 1 : 0) . '"/>
');
$row = $table->add_row();
$column = $row->add_column('<textarea name="text" rows="20" cols="' . $textarea_cols . '">' . $_POST['text'] . '</textarea>');
$column->set_attribute('align', 'center');
$row = $table->add_row();
$column = $row->add_column('
<input type="hidden" name="preview" value="0" />
<input type="submit" value="Send Feedback" />
<input type="button" onclick="document.feedback.preview.value = 1; document.feedback.submit();" value="Preview" />
');
$column->set_attribute('width', 160);
$column->set_attribute('align', 'center');
$table->show();
write('</form><br /><br />');
if(isset($_GET['id'])) {
$fid = (int)$_GET['id'];
if($feedback = Feedback::get($fid))
if($feedback['ip'] == $longip && $table = Feedback::show($fid))
$table->show();
else
error('Invalid feedback ID!<br /><br />');
}
$feedbacks = $SQL->query('SELECT `id` FROM `feedback` WHERE `ip` = ' . $longip . ' ORDER BY time DESC;');
$table = new OTSTable('Your Feedbacks');
foreach($feedbacks as $feedback)
$table->add_row(Feedback::show_short($feedback['id']));
if($table->get_count() == 0)
$row = $table->add_row()->add_column('You have not sent any feedbacks.');
$table->show();
}
}
function send_back($ignoreID = false) {
header('location: ' . get_location($ignoreID));
}
function get_location($ignoreID = false) {
$location = '?subtopic=' . $_GET['subtopic'];
if(isset($_GET['id']) && !$ignoreID)
$location .= '&id=' . $_GET['id'];
return $location;
}
?>
Then you need those functions (place in config-and-functions.php):
PHP:
function write($text) {
$GLOBALS['main_content'] .= $text;
}
function error($text, $return = null) {
$err = '<span style="color: red; font-style: italic;">' . $text . '</span>';
$GLOBALS['ERROR'] = $err;
if($return === true)
return $err;
elseif($return === null)
write($err);
}
function get_title_color() {
return $GLOBALS['config']['site']['vdarkborder'];
}
function get_color($set = false) {
static $i = 0;
if($set !== false)
$i = $set;
return $GLOBALS['config']['site'][($i++ % 2 ? 'light' : 'dark') . 'border'];
}
Database table:
Code:
CREATE TABLE IF NOT EXISTS `feedback` (
`id` int(11) NOT NULL auto_increment,
`title` varchar(100) NOT NULL,
`text` text NOT NULL,
`name` varchar(50) NOT NULL,
`self` int(1) NOT NULL default '0',
`ip` int(10) NOT NULL,
`time` int(10) NOT NULL,
`status` int(1) NOT NULL default '0',
`type` tinyint(2) NOT NULL default '0',
`response` text NOT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=161 ;
Images needed (should be in folder specified in script): icons.rar
Anything to ask, tell me I might have missed something !
Last edited: