Логирование действий пользователей (всплывающее окно на AJAX)

Логирование действий пользователей (всплывающее окно на AJAX) 1.0.0

Совместимость
не проверялся на совместимость
Изменения в БД
не требуются
Дополнительные требования
sqlite3
Автор
frost444
Общественное достояние
да
Описание: добавляет логирование действий пользователей, их точное месторасположение на трекере.

Возможности:
  • Запись лога перемещения пользователя по трекеру
  • Живой вывод тех кто смотрит топик или форум
  • Использование AJAX и sqlite3
Инструкция по установке
PHP:
Автор мода: frost444

####[ОТКРЫТЬ]----- config.php
-----[найти]-----

    'bb_login_err'   => array('filecache',   array()),

-----[добавить ниже]-----

    'buf_where'      => array('db_sqlite',   array('columns' => 'user_ip INT, username TEXT, user_id INT, user_rank INT, user_opt INT, page_id INT, id INT, title TEXT, mode TEXT, url TEXT, time INT')),

-----[добавить в конец]-----
$bb_cfg['bots_conf'] = array(
    'id' => '-777',
);
$bb_cfg['bots'] = array (
    'AdsBot-Google' => 'AdsBot [Google]',
    'ia_archiver' => 'Alexa [Bot]',
    'Scooter/' => 'Alta Vista [Bot]',
    'Ask Jeeves' => 'Ask Jeeves [Bot]',
    'Baiduspider+(' => 'Baidu [Spider]',
    'Exabot/' => 'Exabot [Bot]',
    'FAST Enterprise Crawler' => 'FAST Enterprise [Crawler]',
    'FAST-WebCrawler/' => 'FAST WebCrawler [Crawler]',
    'http://www.neomo.de/' => 'Francis [Bot]',
    'Gigabot/' => 'Gigabot [Bot]',
    'Mediapartners-Google' => 'Google Adsense [Bot]',
    'Google Desktop' => 'Google Desktop',
    'Feedfetcher-Google' => 'Google Feedfetcher',
    'Googlebot' => 'Google [Bot]',
    'heise-IT-Markt-Crawler' => 'Heise IT-Markt [Crawler]',
    'heritrix/1.' => 'Heritrix [Crawler]',
    'ibm.com/cs/crawler' => 'IBM Research [Bot]',
    'ICCrawler - ICjobs' => 'ICCrawler - ICjobs',
    'ichiro/' => 'ichiro [Crawler]',
    'MJ12bot/' => 'Majestic-12 [Bot]',
    'MetagerBot/' => 'Metager [Bot]',
    'msnbot-NewsBlogs/' => 'MSN NewsBlogs',
    'msnbot/' => 'MSN [Bot]',
    'msnbot-media/' => 'MSNbot Media',
    'NG-Search/' => 'NG-Search [Bot]',
    'http://lucene.apache.org/nutch/' => 'Nutch [Bot]',
    'NutchCVS/' => 'Nutch/CVS [Bot]',
    'OmniExplorer_Bot/' => 'OmniExplorer [Bot]',
    'online link validator' => 'Online link [Validator]',
    'psbot/0' => 'psbot [Picsearch]',
    'Seekbot/' => 'Seekport [Bot]',
    'Sensis Web Crawler' => 'Sensis [Crawler]',
    'SEO search Crawler/' => 'SEO Crawler',
    'Seoma [SEO Crawler]' => 'Seoma [Crawler]',
    'SEOsearch/' => 'SEOSearch [Crawler]',
    'Snappy/1.1 ( http://www.urltrends.com/ )' => 'Snappy [Bot]',
    'http://www.tkl.iis.u-tokyo.ac.jp/~crawler/' => 'Steeler [Crawler]',
    'SynooBot/' => 'Synoo [Bot]',
    '[email protected]' => 'Telekom [Bot]',
    'TurnitinBot/' => 'TurnitinBot [Bot]',
    'voyager/1.0' => 'Voyager [Bot]',
    'W3 SiteSearch Crawler' => 'W3 [Sitesearch]',
    'W3C-checklink/' => 'W3C [Linkcheck]',
    'W3C_*Validator' => 'W3C [Validator]',
    'http://www.WISEnutbot.com' => 'WiseNut [Bot]',
    'yacybot' => 'YaCy [Bot]',
    'Yahoo-MMCrawler/' => 'Yahoo MMCrawler [Bot]',
    'Yahoo! DE Slurp' => 'Yahoo Slurp [Bot]',
    'Yahoo! Slurp' => 'Yahoo [Bot]',
    'YahooSeeker/' => 'YahooSeeker [Bot]',
    'Yandex/1.01.001 (compatible; Win16; I)' => 'Яндекс БОТ',
    'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)' => 'Яндекс [Bot]',
    'bingbot/' => 'Bing [Bot]',
);

$bb_cfg['where_user'] = true;

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- ajax.php
-----[найти]-----

        'index_data'        => array('guest'),

-----[добавить ниже]-----

        'UserStats'         => array('user'),
       
-----[найти последнюю скобку и перед ней добавить]-----

    function UserStats()
    {
        require(AJAX_DIR .'UserStats.php');
    }

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- lang_main.php
-----[в конец]-----

// Online/Offline
$lang['OFFLINE'] = 'Вне форума';
$lang['ONLINE'] = 'На форуме';
$lang['HIDDEN'] = 'Скрыт';
$lang['ON_OFF_STATUS'] = 'Статус';
// Online/Offline

$lang['LAST_TYPE'] = 'Последнее действие';
$lang['ONLINE_USERS_WHERE'] = '<b>%1$d</b> человек просматривают эту страницу: <b>%2$d</b><sup title="С 1-го аккаунта сидят несколько человек"><b>[%3$d]</b></sup> зарегистрированных, <b>%4$d</b> скрытых, <b>%5$d</b> гостей, <b>%6$d</b> ботов';

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- index.php
-----[найти]-----

$template->assign_vars(array(
    'SHOW_FORUMS'           => $forums_count,

-----[добавить выше]-----

where_user(array('page_id' => PAGE_FORUM, 'id' => '0', 'mode' => '0', 'url' => str_replace($bb_cfg['script_path'], "", $_SERVER['REQUEST_URI']), 'title' => $lang['FORUM']));

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- viewtopic.php
-----[найти]-----

$template->assign_vars(array(
    'PAGE_URL'            => $pg_url,
   
-----[добавить выше]-----

where_user(array('page_id' => PAGE_VIEWTOPIC, 'id' => $topic_id, 'mode' => '0', 'url' => str_replace($bb_cfg['script_path'], "", $_SERVER['REQUEST_URI']), 'title' => $t_data['topic_title']), true);
   
-----[найти]-----

$template->assign_vars(array(
    'PAGE_URL'            => $pg_url,

-----[добавить ниже]-----

    'WHO_ONLINE_LIST'      => who_online_list(PAGE_VIEWTOPIC, $topic_id),

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- functions.php
-----[найти]-----

function profile_url($data)
{
    ...
}

-----[заменить]-----

function profile_url($data, $popupon = false)
{
    global $bb_cfg, $lang, $datastore;

    if (!$ranks = $datastore->get('ranks'))
    {
        $datastore->update('ranks');
        $ranks = $datastore->get('ranks');
    }

    $user_rank = !empty($data['user_rank']) ? $data['user_rank'] : 0;

    if(isset($ranks[$user_rank]))
    {
        $title = $ranks[$user_rank]['rank_title'];
        $style = $ranks[$user_rank]['rank_style'];
    }
    if(empty($title)) $title = $lang['USER'];
    if(empty($style)) $style = 'colorUser';

    if(!$bb_cfg['color_nick']) $style = '';

    $username = !empty($data['username']) ? $data['username'] : $lang['GUEST'];
    $user_id = (!empty($data['user_id']) && $username != $lang['GUEST']) ? $data['user_id'] : ANONYMOUS;
    if($popupon)
    {
        $profile = "&nbsp;<span onclick=\"user_stats(".$user_id.", 'popup');\" title=\"Просмотр профиля\" class=\"UserPopupsImg clickable\"><span class=\"pad_6\"></span></span>";
        $profile = '<span title="'. $title .'" class="'. $style .'">'. $username .'</span>'.$profile.'';
    }else{
        $profile = '<span title="'. $title .'" class="'. $style .'">'. $username .'</span>';
    }
   
    if(!in_array($user_id, array('', ANONYMOUS, BOT_UID)) && $username && !$popupon)
    {
        $popup = "&nbsp;<span onclick=\"user_stats(".$user_id.", 'popup');\" title=\"Просмотр профиля\" class=\"UserPopupsImg clickable\"><span class=\"pad_6\"></span></span>";
        $profile = '<a href="'. make_url(PROFILE_URL . $user_id, true) .'">'. $profile .'</a>'.$popup.'';
    }

    return $profile;
}


-----[добавить в конец]-----

function who_online_list ($page_id, $id = false, $mode = false)
{
    global $bb_cfg, $lang, $userdata;

    $id = ($id) ? "AND id = {$id}" : '';
    $mode = ($mode) ? "AND mode = {$mode}" : '';
    $where_time = (TIMENOW - 300);
    $sql = CACHE('buf_where')->fetch_rowset("
    SELECT username, user_rank, user_opt, user_id, min(user_ip) as user_ip FROM buf_where
        WHERE page_id = {$page_id}
        $id
        $mode
        AND time > $where_time
        GROUP BY user_ip
        having min(user_ip) = max(user_ip)
    ");
    $id_user = $id_user_hidden = $id_anon = $id_bot = $user = $count_all = array();
    foreach ($sql as $row)
    {   
        $count_all[] = $row['user_ip'];
        if($row['user_id'] != ANONYMOUS && $row['user_id'] != $bb_cfg['bots_conf']['id'])
        {
            $id_user[] = $row['user_id'];
            $user[] = profile_url(array('username' => $row['username'], 'user_id' => $row['user_id'], 'user_rank' => $row['user_rank']));
        }
        else if($row['user_id'] != ANONYMOUS && $row['user_id'] != $bb_cfg['bots_conf']['id'] && bf($row['user_opt'], 'user_opt', 'allow_viewonline'))
        {
            $id_user_hidden[] = $row['user_id'];
        }
        else if($row['user_id'] == ANONYMOUS)
        {
            $id_anon[] = $row['user_id'];
        }
        else if($row['user_id'] == $bb_cfg['bots_conf']['id'])
        {
            $id_bot[] = $row['user_id'];
        }
    }
    $alls = count($count_all);
    $users = count(array_unique($id_user));
    $hiddens = count(array_unique($id_user_hidden));
    $anons = count($id_anon);
    $bots = count($id_bot);
    $duble = ($alls - $users - $hiddens - $anons - $bots);
    $online_count = sprintf($lang['ONLINE_USERS_WHERE'], $alls, $users, $duble, $hiddens, $anons, $bots);
    $online_list = $online_count . '<br /><br />' . join(",\n", array_unique($user));
   
    return $online_list;
}

function where_user($data, $quest = false)
{
    global $bb_cfg, $lang, $userdata;

    if(!$bb_cfg['where_user']) return;
    if(IS_GUEST && !$quest) return;

    $where_time = (TIMENOW - 300);
    $buf = CACHE('buf_where')->fetch_row("
            SELECT time FROM buf_where
            WHERE page_id    = {$data['page_id']}
                AND mode      = '{$data['mode']}'
                AND user_ip  = '". USER_IP ."'
                AND time     > $where_time
                AND id       = {$data['id']}
            ORDER BY time DESC");
    $insert = true;
    if($buf) $insert = false;

    $sql['user_ip']    = USER_IP;
    $sql['username']   = $userdata['username'];
    $sql['user_id']    = $userdata['user_id'];

    if(IS_GUEST)
    {
        $user_browser = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'not browser';

        foreach ($bb_cfg['bots'] as $bot => $name)
        {
            if(strstr($user_browser, $bot))
            {
                $sql['username'] = $name;
                $sql['user_id']  = $bb_cfg['bots_conf']['id'];
            }
        }
    }

    $sql['user_rank']    = $userdata['user_rank'];
    $sql['user_opt']    = $userdata['user_opt'];
    $sql['time']        = TIMENOW;
    $sql['page_id']        = @$data['page_id'];
    $sql['id']            = @$data['id'];
    $sql['mode']        = @$data['mode'];
    $sql['url']            = @$data['url'];
    $sql['title']        = @htmlCHR($data['title']);

    $sql_insert = DB()->build_array('INSERT', $sql);
    if($insert) CACHE('buf_where')->query("INSERT INTO buf_where $sql_insert");
}

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- init_bb.php
-----[найти]-----

define('POST_USERS_URL',  'u');

-----[добавить ниже]-----

//[START] Where user
define('PAGE_REGISTER',                -1);
define('PAGE_LOGIN',                0);
define('PAGE_INDEX',                1);
define('PAGE_FORUM',                2);
define('PAGE_VIEWFORUM',            3);
define('PAGE_VIEWTOPIC',            4);
define('PAGE_POSTING',                5);
define('PAGE_PROFILE',                6);
define('PAGE_PRIVMSGS',                7);
define('PAGE_SEARCH',                8);
define('PAGE_TRACKER',                9);
define('PAGE_VIEWONLINE',            10);
define('PAGE_VIEWMEMBERS',            11);
define('PAGE_GROUPCP',                12);
define('PAGE_FAQ',                    13);
define('PAGE_REPORT',                14);
define('PAGE_PORTAL',                15);
define('PAGE_ORDER',                16);
define('PAGE_POINTSCP',                17);
define('PAGE_QUESTBOOK',            18);
define('PAGE_RADIO',                19);
define('PAGE_PRESENTS',                20);
define('PAGE_VIEWCHEATER',            21);
define('PAGE_WARNINGS',                22);
define('PAGE_MYTOP',                22);
////(BLOG)(START) Where user
define('PAGE_BLOG',                    100);
define('PAGE_BLOG_ALLENTRIES',        101);
define('PAGE_BLOG_BLOCKED',            102);
define('PAGE_BLOG_CFG',                103);
define('PAGE_BLOG_CONTRIBUTORS',    104);
define('PAGE_BLOG_ENTRY',            105);
define('PAGE_BLOG_FRIENDS',            106);
define('PAGE_BLOG_FPOSTING',        107);
define('PAGE_BLOG_RSS',                108);
define('PAGE_BLOGS',                109);
define('PAGE_BLOGS_NEWS',            110);
////(BLOG)(END) Where user
////(GRABBER)(START) Where user
define('PAGE_RUTOR',                200);
define('PAGE_RUTORREGISTER',        201);
define('PAGE_RELEASE',                202);
define('PAGE_GRAB_INDEX',            203);
define('PAGE_QUOTE',                204);
////(GRABBER)(END) Where user
//[END] Where user
           
####[СОХРАНИТЬ_ФАЙЛ]####
####[ОТКРЫТЬ]----- init_bb.php
-----[найти]-----

                    case 'db_sqlite':
                        if (!isset($this->obj[$cache_name]))
                        {
                            $cache_cfg['pconnect']     = $this->cfg['pconnect'];
                            $cache_cfg['db_file_path'] = $this->get_db_path($cache_name, $cache_cfg, '.sqlite.db');
                            $cache_cfg['table_name']   = $cache_name;
                            $cache_cfg['table_schema'] = $this->get_table_schema($cache_cfg);

                            $this->obj[$cache_name] = new sqlite_common($cache_cfg);
                        }
                        $this->ref[$cache_name] =& $this->obj[$cache_name];
                        break;

-----[заменить]-----

                    case 'db_sqlite':
                        if (!isset($this->obj[$cache_name]))
                        {
                            $cache_cfg['pconnect']     = $this->cfg['pconnect'];
                            $cache_cfg['db_file_path'] = $this->get_db_path($cache_name, $cache_cfg, '.sqlite.db');
                            $cache_cfg['table_name']   = $cache_name;
                            $cache_cfg['table_schema'] = $this->get_table_schema($cache_cfg);
                            $cache_cfg['file_name']    = $cache_name.'.sqlite.db';
                            $cache_cfg['dir']             = $this->cfg['db_dir'];

                            $this->obj[$cache_name] = new sqlite_common($cache_cfg);
                        }
                        $this->ref[$cache_name] =& $this->obj[$cache_name];
                        break;
                       
-----[найти]-----

class sqlite_common extends cache_common
{
    var $cfg = array(
            'db_file_path' => 'sqlite.db',
            'table_name'   => 'table_name',
            'table_schema' => 'CREATE TABLE table_name (...)',
            'pconnect'     => true,
            'con_required' => true,
            'log_name'     => 'SQLite',
            'shard_type'   => 'none',     #  none, string, int (тип перевичного ключа для шардинга)
            'shard_val'    => 0,          #  для string - кол. начальных символов, для int - делитель (будет использован остаток от деления)
        );
    var $engine    = 'SQLite';
    var $dbh       = null;
    var $connected = false;
    var $shard_val = false;

    var $table_create_attempts = 0;

    function sqlite_common ($cfg)
    {
        $this->cfg = array_merge($this->cfg, $cfg);
        $this->dbg_enabled = sql_dbg_enabled();
    }

    function connect ()
    {
        $this->cur_query = ($this->dbg_enabled) ? ($this->cfg['pconnect'] ? 'p' : '') .'connect to: '. $this->cfg['db_file_path'] : 'connect';
        $this->debug('start');

        $connect_type = ($this->cfg['pconnect']) ? 'sqlite_popen' : 'sqlite_open';

        if ($this->cfg['shard_type'] != 'none' && $this->shard_val === false)
        {
            trigger_error("cannot shard: shard_val not defined for {$this->cfg['db_file_path']}", E_USER_ERROR);
        }

        if (@$this->dbh = $connect_type($this->cfg['db_file_path'], 0666, $sqlite_error))
        {
            $this->connected = true;
        }

        if (!$this->connected && $this->cfg['con_required'])
        {
            trigger_error($sqlite_error, E_USER_ERROR);
        }

        $this->debug('stop');
        $this->cur_query = null;
    }

    function create_table ()
    {
        $this->table_create_attempts++;
        return sqlite_query($this->dbh, $this->cfg['table_schema']);
    }

    function shard ($name)
    {
        $type = $this->cfg['shard_type'];

        if ($type == 'none') return;
        if (is_array($name))  trigger_error('cannot shard: $name is array', E_USER_ERROR);

        // define shard_val
        if ($type == 'string')
        {
            $shard_val = substr($name, 0, $this->cfg['shard_val']);
        }
        else
        {
            $shard_val = $name % $this->cfg['shard_val'];
        }
        // все запросы должны быть к одному и тому же шарду
        if ($this->shard_val !== false)
        {
            if ($shard_val != $this->shard_val)
            {
                trigger_error("shard cannot be reassigned. [{$this->shard_val}, $shard_val, $name]", E_USER_ERROR);
            }
            else
            {
                return;
            }
        }
        $this->shard_val = $shard_val;
        $this->cfg['db_file_path'] = str_replace('*', $shard_val, $this->cfg['db_file_path']);
    }

    function query ($query)
    {
        if (!$this->connected) $this->connect();

        $this->cur_query = $query;
        $this->debug('start');

        if (!$result = @sqlite_unbuffered_query($this->dbh, $query, SQLITE_ASSOC))
        {
            if (!$this->table_create_attempts && !sqlite_num_rows(sqlite_query($this->dbh, "PRAGMA table_info({$this->cfg['table_name']})")))
            {
                if ($this->create_table())
                {
                    $result = sqlite_unbuffered_query($this->dbh, $query, SQLITE_ASSOC);
                }
            }
            if (!$result)
            {
                $this->trigger_error($this->get_error_msg());
            }
        }

        $this->debug('stop');
        $this->cur_query = null;

        $this->num_queries++;

        return $result;
    }

    function fetch_row ($query)
    {
        $result = $this->query($query);
        return is_resource($result) ? sqlite_fetch_array($result, SQLITE_ASSOC) : false;
    }

    function fetch_rowset ($query)
    {
        $result = $this->query($query);
        return is_resource($result) ? sqlite_fetch_all($result, SQLITE_ASSOC) : array();
    }

    function changes ()
    {
        return is_resource($this->dbh) ? sqlite_changes($this->dbh) : 0;
    }

    function escape ($str)
    {
        return sqlite_escape_string($str);
    }

    function get_error_msg ()
    {
        return 'SQLite error #'. ($err_code = sqlite_last_error($this->dbh)) .': '. sqlite_error_string($err_code);
    }

    function rm ($name = '')
    {
        if ($name)
        {
            $this->db->shard($this->prefix . $name);
            $result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_name = '". sqlite_escape_string($this->prefix . $name) ."'");
        }
        else
        {
            $result = $this->db->query("DELETE FROM ". $this->cfg['table_name']);
        }
        return (bool) $result;
    }

    function gc ($expire_time = TIMENOW)
    {
        $result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_expire_time < $expire_time");
        return ($result) ? sqlite_changes($this->db->dbh) : 0;
    }

    function trigger_error ($msg = 'DB Error')
    {
        if (error_reporting()) trigger_error($msg, E_USER_ERROR);
    }
}

-----[заменить]-----

class sqlite_common extends cache_common
{
    var $cfg = array(
                 'db_file_path' => 'sqlite.db',
                 'table_name'   => 'table_name',
                 'table_schema' => 'CREATE TABLE table_name (...)',
                 'pconnect'     => true,
                 'con_required' => true,
                 'log_name'     => 'SQLite3',
                 'shard_type'   => 'none',     #  none, string, int (тип перевичного ключа для шардинга)
                 'shard_val'    => 0,          #  для string - кол. начальных символов, для int - делитель (будет использован остаток от деления)
                 'file_name'    => 'sqlite.db',
                 'dir'            => null,
               );
    var $engine    = 'SQLite3';
    var $dbh       = null;
    var $connected = false;
    var $shard_val = false;

    var $table_create_attempts = 0;

    function sqlite_common ($cfg)
    {
        $this->cfg = array_merge($this->cfg, $cfg);
        $this->dbg_enabled = sql_dbg_enabled();
    }

    function connect ()
    {
        $this->cur_query = ($this->dbg_enabled) ? ($this->cfg['pconnect'] ? 'p' : '') .'connect to: '. $this->cfg['db_file_path'] : 'connect';
        $this->debug('start');

        if ($this->cfg['shard_type'] != 'none' && $this->shard_val === false)
        {
            trigger_error("cannot shard: shard_val not defined for {$this->cfg['db_file_path']}", E_USER_ERROR);
        }
        $this->dbh = new SQLite3($this->cfg['db_file_path']);

        if ($this->dbh)
        {
            $this->connected = true;
        }
       
        if (!$this->connected && $this->cfg['con_required'])
        {
            trigger_error('Error', E_USER_ERROR);
        }

        $this->debug('stop');
        $this->cur_query = null;
    }

    function create_table ()
    {
        $this->table_create_attempts++;
        return $this->dbh->exec($this->cfg['table_schema']);
    }

    function shard ($name)
    {
        $type = $this->cfg['shard_type'];

        if ($type == 'none') return;
        if (is_array($name))  trigger_error('cannot shard: $name is array', E_USER_ERROR);

        // define shard_val
        if ($type == 'string')
        {
            $shard_val = substr($name, 0, $this->cfg['shard_val']);
        }
        else
        {
            $shard_val = $name % $this->cfg['shard_val'];
        }
        // все запросы должны быть к одному и тому же шарду
        if ($this->shard_val !== false)
        {
            if ($shard_val != $this->shard_val)
            {
                trigger_error("shard cannot be reassigned. [{$this->shard_val}, $shard_val, $name]", E_USER_ERROR);
            }
            else
            {
                return;
            }
        }
        $this->shard_val = $shard_val;
        $this->cfg['pconnect'] = str_replace('*', $shard_val, $this->cfg['db_file_path']);
    }

    function query ($query, $single = false)
    {
        if (!$this->connected) $this->connect();

        $this->cur_query = $query;
        $this->debug('start');
        $queryIns = ($single) ? 'querySingle':'query';
        $mode = ($single) ? @$this->dbh->$queryIns($query,true) : @$this->dbh->$queryIns($query);
        if (!$result = @$mode)
        {
            if (!$this->table_create_attempts && !$this->fetch_column_types($this->cfg['table_name']))
            {
                if ($this->create_table())
                {
                    $result = $this->dbh->exec($query);
                }
            }
        }
        $this->debug('stop');
        $this->cur_query = null;

        $this->num_queries++;

        return $result;
    }

    function fetch_row ($query)
    {
        $result = $this->query($query, true);
       
        return !empty($result) ? $result : false;
    }

    function fetch_rowset ($query)
    {
        $rows = array();
        $result = $this->query($query);
        $i = 0;
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
            $rows[$i]=$row;
            $i++;
        }
       
        return !empty($result) ? $rows : array();
    }
       
    function changes ()
    {
        return ($this->dbh) ? $this->dbh->changes() : 0;
    }
   
    function prepare($row)
    {
        return ($this->dbh) ? $this->dbh->prepare($row) : 0;
    }
   
    function escape ($str)
    {
        return $this->dbh->escapeString($str);
    }

    function get_error_msg ()
    {
        return 'SQLite error #'. ($err_code = $this->dbh->lastErrorMsg()) .': '. $this->dbh->lastErrorCode();
    }

    function rm ($name = '')
    {
        if ($name)
        {
            $this->db->shard($this->prefix . $name);
            $result = $this->db->exec("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_name = '". $this->dbh->prepare($this->prefix . $name) ."'");
        }
        else
        {
            $result = $this->db->exec("DELETE FROM ". $this->cfg['table_name']);
        }
        return (bool) $result;
    }

    function gc ($expire_time = TIMENOW)
    {
        $result = $this->db->exec("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_expire_time < $expire_time");
        return ($result) ? $result->changes() : 0;
    }

    function trigger_error ($msg = 'DB Error')
    {
        if (error_reporting()) trigger_error($msg, E_USER_ERROR);
    }
   
    function fetch_column_types($table_name)
    {
        $col_types = array();
        $col_info_res  = $this->dbh->query( "PRAGMA table_info('". $table_name . "')");

        while ($col_info = $col_info_res->fetchArray(SQLITE3_ASSOC))
        {
            $column_name = $col_info['name'];
            $column_type = $col_info['type'];
            $col_types[$column_name] = $column_type;
        }
        $col_info_res->finalize();
        return $col_types;
    }
}
   
####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- tpl_config.tpl
-----[найти]-----

$_lang = $_main . basename('lang_'. $bb_cfg['default_lang']) .'/';

-----[добавить ниже]-----

$images['icon_online']           = $_lang .'user-online.png';
$images['icon_offline']        = $_lang .'user-offline.png';
$images['icon_hidden']            = $_lang .'user-hidden.png';
   
####[СОХРАНИТЬ_ФАЙЛ]####


####[ОТКРЫТЬ]----- page_geader.tpl
-----[найти]-----

<script type="text/javascript" src="{SITE_URL}misc/js/main.js?v={$bb_cfg['js_ver']}"></script>

-----[добавить ниже]-----

<script type="text/javascript" src="{SITE_URL}misc/js/opt.js?v={$bb_cfg['js_ver']}"></script>
<link rel="stylesheet" href="{TPL_DIR}/popup.css?v={$bb_cfg['css_ver']}" type="text/css">
<link rel="stylesheet" href="{TPL_DIR}/popup-user.css?v={$bb_cfg['css_ver']}" type="text/css">
<link rel="stylesheet" href="{TPL_DIR}/AjaxPopup.css?v={$bb_cfg['css_ver']}" type="text/css">

-----[найти]-----

<body>

-----[добавить ниже]-----

<span id="user_popup"></span>

####[СОХРАНИТЬ_ФАЙЛ]####

####[ОТКРЫТЬ]----- viewtopic.tpl
-----[найти]-----

</table><!--/pagination-->
   
-----[добавить ниже]-----

<div class="category row1 border bw_TRBL mrg_8 pad_4">{WHO_ONLINE_LIST}</div>
   
####[СОХРАНИТЬ_ФАЙЛ]####
  • Снимок.JPG
    Снимок.JPG
    32.6 KB · Просмотры: 169
Автор
Exile
Скачивания
34
Просмотры
345
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя Exile

Сверху