Example #1
0
 private static function dbconnect()
 {
     if (!self::$db) {
         self::$db = Database::get_instance();
     }
     return self::$db;
 }
Example #2
0
 public function create_user()
 {
     // If there are no users then let's create one.
     $db = Database::get_instance();
     $db->query('SELECT * FROM `users` LIMIT 1');
     if ($db->has_rows() && !Auth::get_instance()->logged_in()) {
         Flash::set('<p class="flash validation">Sorry but to create new users, you must be logged in.</p>');
         Core_Helpers::redirect(WEB_ROOT . 'login/');
     }
     $validator = Error::instance();
     if (isset($_POST['email'])) {
         $validator->email($_POST['email'], 'email');
         $validator->blank($_POST['username'], 'username');
         $validator->blank($_POST['password'], 'password');
         $validator->passwords($_POST['password'], $_POST['confirm_password'], 'confirm_password');
         $user = new Users();
         if ($user->select(array('username' => $_POST['username']))) {
             $validator->add('username', 'The username <strong>' . htmlspecialchars($_POST['username']) . '</strong> is already taken.');
         }
         if ($validator->ok()) {
             $user = new Users();
             $user->load($_POST);
             $user->level = 'admin';
             $user->insert();
             Flash::set('<p class="flash success">User created successfully.</p>');
             Core_Helpers::redirect(WEB_ROOT . 'login/');
         }
     }
     $this->data['error'] = $validator;
     $this->load_template('create_user');
 }
Example #3
0
 /**
  * Obtenemos una noticia a mostrar.
  */
 public static function get_active()
 {
     $id = Database::get_instance()->query('SELECT id FROM noticia WHERE estado = ? LIMIT 1', self::ESTADO_VISIBLE)->get_var(Database_Query::FIELD_INT);
     if ($id !== NULL) {
         return new Model_Noticia($id);
     } else {
         return NULL;
     }
 }
Example #4
0
 public function __construct()
 {
     foreach (Database::get_instance()->query("select * from server order by name asc")->fetchAll() as $row) {
         self::$servers[$row->id] = $row->name;
     }
     $this->navi = new Template('navigation');
     $this->navi->load_data('servers', self::$servers);
     $this->navi->load_data('extended', array());
 }
Example #5
0
 /**
  * Cantidad de comentarios en post y fotos.
  * @param int $estado
  * @return int
  */
 public static function cantidad($estado = NULL)
 {
     if ($estado === NULL) {
         $c = Database::get_instance()->query('SELECT COUNT(*) FROM post_comentario')->get_var(Database_Query::FIELD_INT);
         $c += Database::get_instance()->query('SELECT COUNT(*) FROM foto_comentario')->get_var(Database_Query::FIELD_INT);
     } else {
         $c = Database::get_instance()->query('SELECT COUNT(*) FROM post_comentario WHERE estado = ?', $estado)->get_var(Database_Query::FIELD_INT);
         $c += Database::get_instance()->query('SELECT COUNT(*) FROM foto_comentario WHERE estado = ?', $estado)->get_var(Database_Query::FIELD_INT);
     }
     return $c;
 }
Example #6
0
 public static function find_this_query($sql, $params = array())
 {
     $database = Database::get_instance();
     $dbh = $database->get_connection();
     $results_array = array();
     $result = $database->query($sql, $params);
     for ($i = 0, $length = count($result); $i < $length; $i++) {
         $results_array[] = self::instantiation($result[$i]);
     }
     return $results_array;
 }
 public static function create($aspect_type = '', $aspect_data = '')
 {
     $output_object = null;
     if (is_numeric($aspect_type)) {
         // a number got passed in, so we'll try to go from aspect_type_id
         // aha, it looks like we'll need to look up what the name should be
         // if we get passed an ID only.
         $db = Database::get_instance();
         $sql = "SELECT id, aspect_name FROM aspect_types WHERE id = :id";
         $stmt = $db->prepare($sql);
         $stmt->bindParam(':id', $aspect_type, PDO::PARAM_STR);
         if ($stmt->execute()) {
             $row = $stmt->fetchObject();
             $cleaned_class_name = code_safe_name($row->aspect_name);
             $class_name = $cleaned_class_name . 'Aspect';
             if (class_exists($class_name)) {
                 // a custom class DOES exist, so create one.
                 $new_aspect = new $class_name();
                 $new_aspect->aspect_type = $aspect_type;
             } else {
                 $new_aspect = new Aspect();
                 $new_aspect->aspect_type = $aspect_type;
             }
         } else {
             return false;
         }
     } else {
         // we got a string, so we'll try to create a custom aspect of that type,
         // if such a class is defined.
         $db = Database::get_instance();
         $sql = "SELECT id, aspect_name FROM aspect_types WHERE aspect_name = :name";
         $stmt = $db->prepare($sql);
         $stmt->bindParam(':name', $aspect_type, PDO::PARAM_STR);
         if ($stmt->execute()) {
             $row = $stmt->fetchObject();
             $cleaned_class_name = code_safe_name($row->aspect_name);
             $class_name = $cleaned_class_name . 'Aspect';
             if (class_exists($class_name)) {
                 // a custom class DOES exist, so create one.
                 $new_aspect = new $class_name();
                 $new_aspect->aspect_type = $row->id;
             } else {
                 $new_aspect = new Aspect();
                 $new_aspect->aspect_type = $row->id;
             }
         } else {
             return false;
         }
     }
     if ($aspect_data != '') {
         $new_aspect->aspect_data = $aspect_data;
     }
     return $new_aspect;
 }
Example #8
0
 public function load_full_subjects_array()
 {
     $db = Database::get_instance();
     $query = $db->prepare("SELECT id FROM subject_types");
     if ($query->execute()) {
         while ($row = $query->fetch()) {
             $new_subject = new SubjectType();
             $new_subject->load($row['id']);
             $this->full_subjects_array[$new_subject->id] = $new_subject->parent_id;
         }
     }
 }
Example #9
0
 private function __construct()
 {
     session_set_cookie_params(7200, "/");
     // 2 hours session time
     session_start();
     if (!empty($_SESSION['username'])) {
         self::$is_logged_in = true;
         self::$logged_user = array('id' => $_SESSION['user_id'], 'username' => $_SESSION['username']);
     }
     $this->table = 'users';
     $db_object = Database::get_instance();
     $this->dbConn = $db_object::get_db();
 }
Example #10
0
 /**
  * This implementation does not handle AND connectives between players.
  * TODO: rewrite the whole crap
  */
 public function results($uniqid = false, $page = 1)
 {
     session_start();
     if (empty($_POST)) {
         if (isset($_SESSION['post'][$uniqid])) {
             $_POST = $_SESSION['post'][$uniqid];
         }
     } else {
         $uniqid = uniqid();
         $_SESSION['post'][$uniqid] = $_POST;
     }
     if (!empty(array_filter($_POST['player']))) {
         $params = array();
         $server_join = "";
         if (isset($_POST['server']) && $_POST['server']) {
             $params[":srv"] = $_POST['server'];
             $server_join .= "RIGHT OUTER JOIN server AS s " . "ON s.id = g.server AND s.id = :srv ";
         }
         $where = array();
         foreach ($_POST['player'] as $idx => $kw) {
             $idx = (int) $idx;
             // injection attempts shall only f**k up the results
             if ($kw[0] === '"' && $kw[strlen($kw) - 1] === '"') {
                 $kw = substr($kw, 1, -1);
                 $kw = str_replace("%", "\\%", $kw);
             }
             $param = ":like" . $idx;
             $where[] = " p.name LIKE " . $param;
             $params[$param] = $kw;
         }
         $sql = "SELECT SQL_CALC_FOUND_ROWS DISTINCT g.* " . "FROM player AS p INNER JOIN game AS g ON g.id = p.game " . $server_join . "WHERE " . implode(" OR ", $where) . " ORDER BY g.starttime DESC LIMIT :offset, :max";
         $db = Database::get_instance();
         $sth = $db->prepare($sql);
         // $params[':offset'] = ($page - 1) * Game::$limit;
         // $params[':max'] = Game::$limit;
         // $sth->execute($params); // LIMIT params need type info :/
         $sth->bindParam(':max', Game::$limit, PDO::PARAM_INT);
         $sth->bindValue(':offset', ($page - 1) * Game::$limit, PDO::PARAM_INT);
         foreach ($params as $key => $value) {
             $sth->bindValue($key, $value);
         }
         $sth->execute();
         $total = (int) $db->query("SELECT FOUND_ROWS() AS t")->fetch()->t;
         $resultview = new Template('gamelist', array('list' => $sth->fetchAll(PDO::FETCH_CLASS, "Game"), 'pagination' => gamelist::pagination($page, $total, App()->site_url("search/results/{$uniqid}"))));
         $this->form($_POST);
         $resultview->render();
     } else {
         App()->redirect("search");
     }
 }
Example #11
0
 public function authenticate()
 {
     $db = Database::get_instance();
     $pwdField = static::$passwordField;
     $usernameField = static::$usernameField;
     $pass = $db->fetch_array($db->query("SELECT " . static::$passwordField . " FROM " . static::$tableName . " WHERE " . static::$usernameField . "='" . $this->{$usernameField} . "' LIMIT 1"));
     if ($this->{$pwdField} == $pass[0][0]) {
         $result_id = $db->fetch_array($db->query("SELECT ID FROM " . static::$tableName . " WHERE " . static::$usernameField . "='" . $this->user . "' LIMIT 1"));
         $this->id = $result_id[0][0];
         return true;
     } else {
         return false;
     }
 }
Example #12
0
 public function aspect_flavors()
 {
     $output = '';
     $db = Database::get_instance();
     $query = $db->prepare("SELECT DISTINCT flavor from aspect_types ORDER BY flavor ASC");
     if ($query->execute()) {
         foreach ($query->fetchAll() as $row) {
             $output .= '<option value="' . $row['flavor'] . '">' . $row['flavor'] . '</option>';
         }
         return $output;
     } else {
         return false;
     }
 }
Example #13
0
 public function print_last_logs($number = '5')
 {
     $output = '<ul>';
     $db = Database::get_instance();
     $query = $db->prepare("SELECT * FROM log ORDER BY id DESC LIMIT 10");
     $data = array($number);
     if ($query->execute($data)) {
         while ($row = $query->fetch()) {
             $output .= '<li>' . $row['message'] . ' - logged at ' . $row['time'] . '</li>';
         }
     }
     $output .= '</ul>';
     return $output;
 }
Example #14
0
 public static function install($app)
 {
     if (file_exists(DOC_ROOT . 'apps/' . $app . '/tables.sql')) {
         if (is_writable(DOC_ROOT . 'apps/' . $app . '/tables.sql')) {
             // Create tables
             $sql = file_get_contents(DOC_ROOT . 'apps/' . $app . '/tables.sql');
             // Do this to split up creations to one per query.
             $queries = explode('#', $sql);
             $db = Database::get_instance();
             foreach ($queries as $query) {
                 $db->query($query);
             }
             rename(DOC_ROOT . 'apps/' . $app . '/tables.sql', DOC_ROOT . 'apps/' . $app . '/tables.sql.bak');
         } else {
             die('<h1>You have not installed this app, either run <strong>' . DOC_ROOT . 'apps/' . $app . '/tables.sql' . '</strong> manually and delete the file or change chmod this file so that it is writable by PHP.</h1>');
         }
     }
 }
Example #15
0
 public function build()
 {
     $db = Database::get_instance();
     $values = $this->current_object->get_fields();
     $options = array();
     foreach ($values as $value) {
         $res = $db->query('SELECT `' . $value . '` FROM ' . $this->table)->result;
         $type = mysql_field_type($res, 0);
         $extra = mysql_field_flags($res, 0);
         $notnullsearch = strpos($extra, 'not_null');
         // If value can not be NULL lets add blank as a error check
         if ($notnullsearch === false) {
             $options['validation'] = '';
         } else {
             $options['validation'] = 'blank';
         }
         $options['type'] = $type === 'blob' ? 'htmleditor' : 'text';
         $options['type'] = $type === 'timestamp' ? 'timestamp' : $options['type'];
         $options['type'] = $value === 'password' ? 'password' : $options['type'];
         // Grab rows where field name matches
         $value_info = new Field_Information(array('table' => $this->table, 'name' => $value));
         if ($value_info->type !== NULL) {
             $options['type'] = $value_info->type;
             if ($options['type'] === 'file') {
                 // shouldn't validate for blank if it's a file.... TODO: Come up with a way to validate files
                 $options['validation'] = '';
             }
         }
         if ($value_info->options !== NULL) {
             $exploded_options = explode("\n", $value_info->options);
             foreach ($exploded_options as $option) {
                 if (!empty($option)) {
                     $option_temp = explode(',', $option);
                     $options['options'][$option_temp[0]] = $option_temp[1];
                 }
             }
         }
         $options['value'] = $this->current_object->{$value};
         $this->add_field($value, $options);
     }
 }
Example #16
0
 /**
  * Aplicamos una migracion.
  * @param int $numero Número de migración a aplicar.
  */
 public static function migrar($numero)
 {
     // Path de la migracion a aplicar.
     $f_migracion = SHELL_PATH . DS . 'migraciones' . DS . $numero . '_migracion.php';
     // Verificamos exista la migración.
     if (!file_exists($f_migracion)) {
         throw new Exception('No existe la migración ' . $numero, 202);
     }
     // Intentamos aplicarla.
     $rst = (include $f_migracion);
     if ($rst) {
         // Guardamos la migracion.
         list(, $c) = Database::get_instance()->insert('INSERT INTO migraciones (numero, fecha) VALUES (?, ?)', array($numero, date('Y/m/d H:i:s')));
         if ($c < 0) {
             throw new Exception('No se pudo guardar el estado de la migracion en la base de datos.', 203);
         }
         return TRUE;
     } else {
         throw new Exception('El resultado de la migracion es inesperado.', 204);
     }
 }
Example #17
0
<?php

/**
 * Modificaciones de las categorias. Se juntan e implementan para post, fotos y comunidades.
 */
// Cambiamos campo comunidades.
Database::get_instance()->update('ALTER TABLE `comunidad` CHANGE `comunidad_categoria_id` `categoria_id` INT NOT NULL');
// Quitamos categorias comunidades.
Database::get_instance()->update('DROP TABLE `comunidad_categoria`');
// Renombramos la tabla de categorias.
Database::get_instance()->update("RENAME TABLE `post_categoria` TO `categoria`");
// Renombramos el campo de las categorias de los posts.
Database::get_instance()->update('ALTER TABLE `post` CHANGE `post_categoria_id` `categoria_id` INT NOT NULL');
// Agregamos categoria a las fotos.
Database::get_instance()->update('ALTER TABLE `foto` ADD `categoria_id` INT NOT NULL');
Example #18
0
<?php

/**
 * Modificaciones de los rangos de los usuarios.
 */
// Orden en el rango.
Database::get_instance()->update('ALTER TABLE `usuario_rango` ADD COLUMN `orden` int(11) NOT NULL DEFAULT 0');
// Indice UNIQUE al orden de los rangost.
Database::get_instance()->update('ALTER TABLE `usuario_rango` ADD UNIQUE(`orden`)');
// Actualizo el nombre de la tabla de suspensiones de usuario.
Database::get_instance()->update("RENAME TABLE `usuario_suspencion` TO `usuario_suspension`");
// Clave UNIQUE para suspensiones de usuario.
Database::get_instance()->update('ALTER TABLE `usuario_suspension` ADD UNIQUE (`usuario_id`)');
Example #19
0
<?php

/**
 * Permitimos cerrar comentarios en posts.
 */
// Creamos la tabla para denunciar fotos.
Database::get_instance()->update('ALTER TABLE `post` ADD `comentar` BIT NOT NULL DEFAULT 1');
Example #20
0
 public function return_aspect_group_name()
 {
     $output = false;
     $db = Database::get_instance();
     $query = $db->prepare("SELECT group_name FROM aspect_groups WHERE id=?");
     $data = array($this->return_aspect_type_id());
     if ($query->execute($data)) {
         foreach ($query->fetch() as $row) {
             $output = $row['group_name'];
         }
         return $output;
     } else {
         return false;
     }
 }
Example #21
0
    //
    private function __construct()
    {
        $this->_mysqli = new mysqli('localhost', 'root', '', 'xapp_base');
        //echo 'connected';
    }
    public function query($sql)
    {
        if ($this->_query = $this->_mysqli->query($sql)) {
            while ($row = $this->_query->fetch_object()) {
                $this->_results[] = $row;
            }
            $this->_count = $this->_query->num_rows;
        }
        return $this;
    }
    public function results()
    {
        return $this->_results;
    }
    public function count()
    {
        return $this->_count;
    }
}
$users = Database::get_instance()->query("SELECT * FROM users LIMIT 10");
if ($users->count()) {
    foreach ($users->results() as $user) {
        echo $user->name . "<br/>";
    }
}
Example #22
0
$datos[] = array("Links", "links", "link.png");
$datos[] = array("Linux", "linux", "tux.png");
$datos[] = array("Mac", "mac", "mac.png");
$datos[] = array("Manga y Anime", "mangayanime", "manga.png");
$datos[] = array("Mascotas", "mascotas", "pet.png");
$datos[] = array("Música", "musica", "music.png");
$datos[] = array("Noticias", "noticias", "newspaper.png");
$datos[] = array("Off Topic", "offtopic", "comments.png");
$datos[] = array("Recetas y Cocina", "recetasycocina", "cake.png");
$datos[] = array("Salud y Bienestar", "saludybienestar", "heart.png");
$datos[] = array("Solidaridad", "solidaridad", "salva.png");
$datos[] = array("Prueba", "prueba", "tscript.png");
$datos[] = array("Turismo", "turismo", "brujula.png");
$datos[] = array("TV, Peliculas y series", "tvpeliculasyseries", "tv.png");
$datos[] = array("Videos On-line", "videosonline", "film.png");
// Ejecutamos modificaciones.
foreach ($datos as $dt) {
    list(, $c) = Database::get_instance()->insert($sql, $dt);
    if ($c < 0) {
        throw new Database_Exception("Error insertando categoria: '{$dt[0]}'");
    }
}
// Largo contraseña.
if (Database::get_instance()->update('ALTER TABLE `usuario` CHANGE `password` `password` VARCHAR( 60 ) NOT NULL')) {
    throw new Database_Exception("No se pudo modificar el largo de la contraseña del usuario.");
}
// Nueva clave usuario_perfil.
if (Database::get_instance()->update('ALTER TABLE `usuario_perfil` DROP PRIMARY KEY, ADD PRIMARY KEY(`usuario_id`,`campo`)')) {
    throw new Database_Exception("No se pudo modificar la clave del perfil del usuario.");
}
return TRUE;
Example #23
0
 public function select_many($sql = NULL, $extra_columns = array())
 {
     $db = Database::get_instance();
     $tmp_obj = new $this->class_name();
     // Also, it needs to be a subclass of Db_Object...
     if (!is_subclass_of($tmp_obj, 'Db_Object')) {
         return false;
     }
     if (is_null($sql) || empty($sql)) {
         $sql = "SELECT * FROM `{$tmp_obj->table_name}`";
     }
     // So you want to do select * but don't want to have to type it, just add %select%
     $sql = str_replace('%select%', "SELECT * FROM `{$tmp_obj->table_name}`", $sql);
     $objs = array();
     $rows = $db->get_rows($sql);
     foreach ($rows as $row) {
         $o = new $this->class_name();
         $o->load($row);
         $objs[$o->id] = $o;
         foreach ($extra_columns as $c) {
             $o->add_column($c);
             $o->{$c} = isset($row[$c]) ? $row[$c] : NULL;
         }
     }
     return $objs;
 }
Example #24
0
<?php

/**
 * Coldreader 
 *
 * PHP version 5
 *
 * LICENSE: There's plenty of third-party libs in use, 
 * and nothing here should be interpreted to change or 
 * contradict anything that is stipulated in the licenses 
 * for those components.  As for my code, it's Creative 
 * Commons Attribution-NonCommercial-ShareAlike 3.0 
 * United States. (http://creativecommons.org/licenses/by-nc-sa/3.0/us/).  
 * For more information, contact Ian Monroe: ian@ianmonroe.com
 *
 * @author     Ian Monroe <*****@*****.**>
 * @copyright  2016
 * @version    0.1 ALPHA UNSTABLE
 * @link       http://www.ianmonroe.com
 * @since      File included in initial release
 *
 */
// bootstrap the rest of the codebase.
require_once '../config.php';
$db = Database::get_instance();
setcookie('auth', '', time() + 3600, '/');
setcookie('nonce', '', time() + 3600, '/');
Example #25
0
 public function tables($info)
 {
     $db = Database::get_instance();
     $result = $db->query('SHOW TABLES');
     while ($row = mysql_fetch_array($result)) {
         $obj_name = uc_slug($row[0], '_');
         if (class_exists($obj_name)) {
             $info['options'][$row[0]] = $row[0];
         }
     }
     $out = $this->dropdown($info);
     return $out;
 }
Example #26
0
 public function delete()
 {
     $db = Database::get_instance();
     $sql = "DELETE FROM " . static::$tableName . ' WHERE id=' . $this->id;
     if ($db->query($sql)) {
         Log::log_action("Entry deleted from " . static::$tableName . " (id=" . $this->id . ")");
         return true;
     } else {
         return false;
     }
 }
Example #27
0
 private function attempt_login($un, $pw)
 {
     $db = Database::get_instance();
     // We SELECT * so we can load the full user record into the user Db_Object later
     $row = $db->get_row('SELECT * FROM users WHERE username = '******'password']) {
         return FALSE;
     }
     $this->id = $row['id'];
     $this->username = $row['username'];
     $this->level = $row['level'];
     // Load any additional user info into db_object
     $this->user = new Users();
     $this->user->id = $row['id'];
     $this->user->load($row);
     $this->store_session_data($un, $pw);
     $this->logged_in = TRUE;
     return TRUE;
 }
Example #28
0
 /**
  * Contructor de la clase. Automáticamente cargamos la base de datos.
  * De esta forma puede realizar las consultas de forma facil.
  * @author Ignacio Daniel Rostagno <*****@*****.**>
  */
 public function __construct()
 {
     // Cargo la base de datos.
     $this->db = Database::get_instance();
 }
Example #29
0
 * Modificaciones para implementar la administración y moderación de posts y fotos.
 */
// Creamos tabla para eventos de moderación y administración de posts.
Database::get_instance()->update('
CREATE TABLE `post_moderado` (
  `post_id` INTEGER NULL DEFAULT NULL,
  `usuario_id` INTEGER NOT NULL,
  `tipo` INTEGER NOT NULL,
  `padre_id` INTEGER NULL DEFAULT NULL,
  `razon` TEXT NULL DEFAULT NULL,
  PRIMARY KEY (`post_id`),
  FOREIGN KEY (usuario_id) REFERENCES `usuario` (`id`),
  FOREIGN KEY (post_id) REFERENCES `post` (`id`),
  FOREIGN KEY (padre_id) REFERENCES `post` (`id`)
);');
/**
 * usuario_id: ID del moderador que realiza la acción.
 * post_id:    POST que es moderado.
 * tipo:       TIPO de advertencia. Por ejemplo: spam.
 * padre_id:   Post que se crea para que el usuario revise.
 *             Si el post debe ser editado, se crea otro como borrador. El ID de
 *             ese borrador es el colocadó aquí.
 * razon:      En caso de ser un motivo no especificado, se colocá un texto para explicar.
 */
// Agregamos la posibilidad de cerrar comentarios de fotos.
Database::get_instance()->update('ALTER TABLE `foto` ADD `comentar` BIT NOT NULL');
// Parámetros de visitas para poder representar que no muestre visitas.
Database::get_instance()->update('ALTER TABLE `foto` CHANGE `visitas` `visitas` INT( 11 ) NULL DEFAULT NULL');
// Comentarios vacios para denuncias post.
Database::get_instance()->update('ALTER TABLE `post_denuncia` CHANGE `comentario` `comentario` TEXT NULL DEFAULT NULL');
Example #30
0
 private function run($args)
 {
     $argfields = array("servers", "notservers", "players", "notplayers");
     foreach ($argfields as $key) {
         if (!isset($args[$key]) || !$args[$key]) {
             $args[$key] = array();
         }
     }
     $params = array();
     $sql = "";
     $sql_where = array();
     $cb4player = function ($phrase) use(&$params) {
         if ($phrase[0] === '"' && $phrase[strlen($phrase) - 1] === $phrase[0]) {
             $phrase = str_replace("%", "\\%", substr($phrase, 1, -1));
         }
         $param = uniqid(":");
         $params[$param] = $phrase;
         return "player.name LIKE " . $param;
     };
     $sql = "SELECT SQL_CALC_FOUND_ROWS DISTINCT g.* FROM game AS g ";
     foreach ($args['players'] as $player) {
         if (!$player) {
             continue;
         }
         $tbl = uniqid("tbl");
         $sql .= "INNER JOIN (SELECT DISTINCT game AS gid FROM player " . "WHERE " . implode(" OR ", array_map($cb4player, $player)) . ") AS {$tbl} ON {$tbl}.gid = g.id ";
     }
     foreach (array_values($args['notplayers']) as $key => $player) {
         if (!$player) {
             continue;
         }
         $alias = "exclude" . $key;
         $sql .= "LEFT OUTER JOIN (SELECT DISTINCT game AS gid FROM player " . "WHERE " . implode(" OR ", array_map($cb4player, $player)) . ") AS {$alias} ON {$alias}.gid = g.id ";
         $sql_where[] = $alias . ".gid IS NULL ";
     }
     $cb4srvid = function ($srvid) use(&$params) {
         $param = uniqid(":");
         $params[$param] = $srvid;
         return "server.id = " . $param;
     };
     $srvids = array_filter(array_map("intval", $args["servers"]));
     $notsrvids = array_filter(array_map("intval", $args["notservers"]));
     $sql_srvids = implode(" OR ", array_map($cb4srvid, $srvids));
     $sql_notsrvids = implode(" OR ", array_map($cb4srvid, $notsrvids));
     $sql .= "RIGHT OUTER JOIN server ON server.id = g.server " . ($sql_srvids ? " AND (" . $sql_srvids . ")" : "") . ($sql_notsrvids ? " AND NOT (" . $sql_notsrvids . ")" : "");
     $sql .= "WHERE g.id IS NOT NULL";
     if ($sql_where) {
         $sql .= " AND " . implode(" AND ", $sql_where);
     }
     $sql .= " ORDER BY g.endtime DESC ";
     if (isset($args['max'])) {
         $sql .= " LIMIT ";
         if (isset($args['offset'])) {
             $sql .= ":offset, ";
             $params[":offset"] = $args["offset"];
         }
         $sql .= ":max";
         $params[":max"] = $args["max"];
     }
     $db = Database::get_instance();
     $sth = $db->prepare($sql);
     foreach ($params as $key => $value) {
         $sth->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
     }
     $sth->execute();
     return (object) array("sth" => $sth, "total" => (int) $db->query("SELECT FOUND_ROWS() AS t")->fetch()->t);
 }