View file app/Classes/Metrika.php

File size: 18.35Kb
<?php

namespace App\Classes;

use App\Models\Counter;
use App\Models\Counter24;
use App\Models\Counter31;
use App\Models\Online;
use Illuminate\Database\Capsule\Manager as DB;

class Metrika
{
    /**
     * Генерирует счетчик
     *
     * @return void
     */
    public function getCounter()
    {
        // -------------------- Вывод статистики ------------------------------//
        $week_day = date('w');
        $arr_week = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'];

        if (file_exists(STORAGE . '/temp/counter.dat')) {
            $count = json_decode(file_get_contents(STORAGE . '/temp/counter.dat'));
        } else {
            $count = (object) ['dayhosts' => 0, 'dayhits' => 0];
        }

        if (file_exists(STORAGE . '/temp/online.dat')) {
            $online = last(json_decode(file_get_contents(STORAGE . '/temp/online.dat')));
        } else {
            $online = 0;
        }

        if (file_exists(STORAGE . '/temp/counter7.dat')) {
            $host_data = json_decode(file_get_contents(STORAGE . '/temp/counter7.dat'));
        } else {
            $host_data = array_fill(0, 6, 0);
        }

        $host_data[] = $count->dayhosts;
        // ----------------------------------------------------------------------//
        $img    = imagecreatefrompng(HOME . '/assets/img/images/counter.png');
        $color  = imagecolorallocate($img, 0, 0, 0);
        $color2 = imagecolorallocate($img, 102, 102, 102);

        $pos = 65;
        if ($online >= 10 && $online < 100) $pos = 52;
        if ($online >= 100 && $online < 200) $pos = 44;
        if ($online >= 200 && $online < 1000) $pos = 40;

        $colors = [
            [191, 109, 232],
            [87,  164, 246],
            [0,   203, 189],
            [0,   199, 68],
            [149, 217, 0],
            [255, 255, 0],
            [255, 181, 0]
        ];

        $max = max($host_data);

        if ($max == 0) {
            $max = 1;
        }

        $per_host = [];
        foreach ($host_data as $value) {
            $per_host[] = $value * 0.90 / $max;
        }

        $coll = 11;
        $im   = 14;
        $x1   = 2;
        $y2   = 15;
        $x2   = $x1 + $coll;

        foreach ($per_host as $key => $percent) {
            $week_day++;

            if ($week_day > 6) {
                $week_day -= 7;
            }

            $y1 = round($im - $im * $percent + 1);

            if (!empty($percent)) {
                $col = imagecolorallocate($img, $colors[$key][0], $colors[$key][1], $colors[$key][2]);
                imagefilledrectangle($img, $x1-1, $y1, $x2-2, $y2, $col);
            }

            imagettftext($img, 6, 0, $x1, 15, $color, HOME . '/assets/fonts/font.ttf', $arr_week[$week_day]);

            $x1 += $coll;
            $x2 += $coll;
        }

        imagettftext($img, 6, 0, 13, 23, $color2, HOME . '/assets/fonts/font4.ttf', formatShortNum($count->dayhosts));
        imagettftext($img, 6, 0, 13, 29, $color2, HOME . '/assets/fonts/font4.ttf', formatShortNum($count->dayhits));
        imagettftext($img, 12, 0, $pos, 29, $color2, HOME . '/assets/fonts/font7.ttf', $online);

        imagepng($img, UPLOADS . '/counters/counter_new.png');
        imagedestroy($img);

        rename(UPLOADS . '/counters/counter_new.png', UPLOADS . '/counters/counter.png');
    }

    /**
     * Выводит счетчик за день
     *
     * @return string
     */
    public function getCounterDay()
    {
        $imageCache = '/uploads/counters/counter24.gif';
        if (!file_exists($imageCache) || dateFixed(@filemtime($imageCache), "dmYH") != dateFixed(SITETIME, "dmYH")){

            $hours = floor((gmmktime(date("H"), 0, 0, date("m"), date("d"), date("Y")) - gmmktime((date("Z") / 3600), 0, 0, 1, 1, 1970)) / 3600);

            $counts = Counter24::query()->orderBy('hour', 'desc')->get();

            $arrhits   = [];
            $arrhosts  = [];
            $hits_data = [];
            $host_data = [];

            foreach ($counts as $val) {
                $arrhits[$val['hour']]  = $val['hits'];
                $arrhosts[$val['hour']] = $val['hosts'];
            }

            for ($i = 0, $tekhours = $hours; $i < 24; $tekhours -= 1, $i++) {
                $hits_data[] = $arrhits[$tekhours] ?? 0;
                $host_data[] = $arrhosts[$tekhours] ?? 0;
            }
            // --------------------------------------------------//
            $maxhit = 0;
            $max_index = 0;
            foreach ($hits_data as $index => $value) {
                if ($value > $maxhit) {
                    $maxhit = $value;
                    $max_index = $index;
                }
            }
            $maxhost = max($host_data);
            if ($maxhit == 0) {
                $maxhit = 1;
            }
            // процентное соотношение хитов
            $per_hit = [];
            foreach ($hits_data as $value) {
                $per_hit[] = $value * 0.90 / $maxhit;
            }
            // процентное соотношение хостов
            $per_host = [];
            foreach ($host_data as $value) {
                $per_host[] = $value * 2.90 / $maxhit;
            }
            $img = @imagecreatefromgif(HOME . '/assets/img/images/counter24.gif');
            // линейный
            $color1 = imagecolorallocate($img, 44, 191, 228);
            $color2 = imagecolorallocate($img, 0, 0, 120);
            $color_red = imagecolorallocate($img, 200, 0, 0);

            $image = 47;
            $coll = 3;
            $x1 = 119;
            $x2 = $x1 - 3;
            $y1_hits = (int)($image - $image * $per_hit[0] + 7);
            $y1_host = (int)($image - $image * $per_host[0] + 7);

            $counth = count($hits_data);
            if ($counth > 24) {
                $counth = 24;
            }

            for($i = 1;$i < $counth;$i++) {
                // хиты
                $y2_hits = (int)($image - $image * $per_hit[$i] + 7);
                imageline($img, $x1 + 1, $y1_hits, $x2, $y2_hits, $color1);
                // хосты
                $y2_host = (int)($image - $image * $per_host[$i] + 7);
                imageline($img, $x1 + 1, $y1_host, $x2, $y2_host, $color2);

                if ($hits_data[$i] != 0 && $i == $max_index) {
                    imagettftext($img, 6, 0, 40, $y2_hits-3, $color_red, HOME . '/assets/fonts/font.ttf', 'max. ' . $maxhost.' / ' . $maxhit);
                    imageline($img, $x2-1, $y2_hits-2, $x2-1, $y2_hits + 42, $color_red);
                }
                $y1_hits = $y2_hits;
                $y1_host = $y2_host;
                $x1 -= $coll + 2;
                $x2 -= $coll + 2;
            }
            //Header("Content-type: image/gif");
            imagegif($img, HOME . $imageCache);
            imagedestroy($img);
        }

        echo '<img src="' . $imageCache . '?' . dateFixed(SITETIME, "dmYH") . '" alt="Сутки"><br><br>';
    }

    /**
     * Выводит счетчик за неделю
     *
     * @return string
     */
    public function getCounterWeek()
    {
        $imageCache = '/uploads/counters/counter7.gif';
        if (!file_exists($imageCache) || dateFixed(@filemtime($imageCache), "dmY") != dateFixed(SITETIME, "dmY")){

            $week_day = date("w") - 1;
            $arr_week = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'];
            $days = floor((gmmktime(0, 0, 0, date("m"), date("d"), date("Y")) - gmmktime(0, 0, 0, 1, 1, 1970)) / 86400);

            $counts = Counter31::query()
                ->orderBy('days', 'desc')
                ->limit(7)
                ->pluck('hosts', 'days')
                ->all();

            $host_data = [];
            for ($i = 0, $tekdays = $days; $i < 7; $tekdays--, $i++) {
                $host_data[] = $counts[$tekdays] ?? 0;
            }

            $host_data = array_reverse($host_data);
            // ---------------------------------------------//
            $max = max($host_data);
            if ($max == 0) $max = 1;

            $per_host = [];
            foreach ($host_data as $value) {
                $per_host[] = $value * 0.90 / $max;
            }

            $img = imagecreatefromgif(HOME . '/assets/img/images/counter7.gif');

            $imageW = 47;
            $collW  = 14;

            $x1 = 12;
            $y2 = 59;
            $x2 = $x1 + $collW;
            $colorBlack = imagecolorallocate($img, 0, 0, 120);

            foreach ($per_host as $index => $percent) {
                $week_day++;
                if ($week_day > 6) {
                    $week_day -= 7;
                }

                if ($index / 2 == (int)($index / 2)) {
                    $color = imagecolorallocate($img, 249, 243, 70);
                    $color2 = imagecolorallocate($img, 242, 226, 42);
                    $color3 = imagecolorallocate($img, 226, 210, 34);
                } else {
                    $color = imagecolorallocate($img, 11, 215, 252);
                    $color2 = imagecolorallocate($img, 7, 203, 239);
                    $color3 = imagecolorallocate($img, 7, 187, 219);
                }

                $y1 = round($imageW - $imageW * $percent + 12);
                imagefilledrectangle($img, $x1, $y1, $x2, $y2, $color);

                $points = [0 => $x1, // x1
                           1 => $y1, // y1
                           2 => $x1 + 3, // x2
                           3 => $y1-5, // y2
                           4 => $x1 + $collW + 3, // x3
                           5 => $y1-5, // y3
                           6 => $x2, // x4
                           7 => $y1, // y4
                ];

                imagefilledpolygon($img, $points, 4, $color2);

                $points = [0 => $x2, // x1
                           1 => $y1, // y1
                           2 => $x1 + $collW + 3, // x2
                           3 => $y1-5, // y2
                           4 => $x1 + $collW + 3, // x3
                           5 => $y2-5, // y3
                           6 => $x2, // x4
                           7 => $y2, // y4
                ];

                imagefilledpolygon($img, $points, 4, $color3);
                imagettftext($img, 6, 90, $x1+10, 50, $colorBlack, HOME . '/assets/fonts/font.ttf', $host_data[$index]);
                imagettftext($img, 6, 0, $x1 + 3, 66, $colorBlack, HOME . '/assets/fonts/font.ttf', $arr_week[$week_day]);

                $x1 += $collW;
                $x2 += $collW;
            }
            //Header("Content-type: image/gif");
            imagegif($img, HOME.$imageCache);
            imagedestroy($img);
        }

        echo '<img src="' . $imageCache . '?'.dateFixed(SITETIME, "dmY") . '" alt="Неделя"><br><br>';
    }

    /**
     * Выводит счетчик за месяц
     *
     * @return string
     */
    public function getCounterMonth()
    {
        $imageCache = '/uploads/counters/counter31.gif';
        if (!file_exists($imageCache) || dateFixed(@filemtime($imageCache), "dmY") != dateFixed(SITETIME, "dmY")){

            $days = floor((gmmktime(0, 0, 0, date("m"), date("d"), date("Y")) - gmmktime(0, 0, 0, 1, 1, 1970)) / 86400);

            $counts = Counter31::query()->orderBy('days', 'desc')->get();

            $arrhits   = [];
            $arrhosts  = [];
            $hits_data = [];
            $host_data = [];

            foreach ($counts as $val) {
                $arrhits[$val['days']]  = $val['hits'];
                $arrhosts[$val['days']] = $val['hosts'];
            }

            for ($i = 0, $tekdays = $days; $i < 31; $tekdays -= 1, $i++) {
                $hits_data[] = $arrhits[$tekdays] ?? 0;
                $host_data[] = $arrhosts[$tekdays] ?? 0;
            }
            // --------------------------------------------------//
            $maxhit = 0;
            $max_index = 0;
            foreach ($hits_data as $index => $value) {
                if ($value > $maxhit) {
                    $maxhit = $value;
                    $max_index = $index;
                }
            }

            $maxhost = max($host_data);
            if ($maxhit == 0) {
                $maxhit = 1;
            }
            // процентное соотношение хитов
            $per_hit = [];
            foreach ($hits_data as $value) {
                $per_hit[] = $value * 0.90 / $maxhit;
            }
            // процентное соотношение хостов
            $per_host = [];
            foreach ($host_data as $value) {
                $per_host[] = $value * 2.90 / $maxhit;
            }
            $img = imagecreatefromgif(HOME . '/assets/img/images/counter31.gif');
            // линейный
            $color1 = imagecolorallocate($img, 44, 191, 228);
            $color2 = imagecolorallocate($img, 0, 0, 120);
            $color_red = imagecolorallocate($img, 200, 0, 0);

            $image = 47;
            $coll = 3;
            $x1 = 154;
            $x2 = $x1 - 3;
            $y1_hits = (int)($image - $image * $per_hit[0] + 7);
            $y1_host = (int)($image - $image * $per_host[0] + 7);

            $counth = count($hits_data);
            if ($counth > 31) {
                $counth = 31;
            }

            imagettftext($img, 6, 0, 50, 7, $color_red, HOME . '/assets/fonts/font.ttf', 'max. ' . $maxhost . ' / ' . $maxhit);

            for($i = 1;$i < $counth;$i++) {
                // хиты
                $y2_hits = (int)($image - $image * $per_hit[$i] + 7);
                imageline($img, $x1 + 1, $y1_hits, $x2, $y2_hits, $color1);
                // хосты
                $y2_host = (int)($image - $image * $per_host[$i] + 7);
                imageline($img, $x1 + 1, $y1_host, $x2, $y2_host, $color2);

                if ($hits_data[$i] != 0 && $i == $max_index) {
                    imageline($img, $x2-1, $y2_hits-2, $x2-1, $y2_hits + 42, $color_red);
                }
                $y1_hits = $y2_hits;
                $y1_host = $y2_host;
                $x1 -= $coll + 2;
                $x2 -= $coll + 2;
            }
            //Header("Content-type: image/gif");
            imagegif($img, HOME . $imageCache);
            imagedestroy($img);
        }

        echo '<img src="' . $imageCache . '?' . dateFixed(SITETIME, "dmY") . '" alt="Месяц"><br><br>';
    }

    /**
     * Сохраняет статистику
     *
     * @return void
     */
    public function saveStatistic()
    {
        $days  = floor((gmmktime(0, 0, 0, date("m"), date("d"), date("Y")) - gmmktime(0, 0, 0, 1, 1, 1970)) / 86400);
        $hours = floor((gmmktime(date("H"), 0, 0, date("m"), date("d"), date("Y")) - gmmktime((date("Z") / 3600), 0, 0, 1, 1, 1970)) / 3600);

        Online::query()->where('updated_at', '<', SITETIME - setting('timeonline'))->delete();

        $newHost = false;

        if (getUser()) {
            $online = Online::query()
                ->where('ip', getIp())
                ->orWhere('user_id', getUser('id'))
                ->orderByRaw('user_id = ? desc', [getUser('id')])
                ->first();

            if ($online) {
                $online->update([
                    'ip'         => getIp(),
                    'brow'       => getBrowser(),
                    'updated_at' => SITETIME,
                    'user_id'    => getUser('id'),
                ]);
            } else {
                Online::query()->create([
                    'ip'         => getIp(),
                    'brow'       => getBrowser(),
                    'updated_at' => SITETIME,
                    'user_id'    => getUser('id'),
                ]);
                $newHost = true;
            }
        } else {
            $online = Online::query()
                ->where('ip', getIp())
                ->orderByRaw('user_id IS NULL desc')
                ->first();

            if ($online) {
                $online->update([
                    'brow'       => getBrowser(),
                    'updated_at' => SITETIME,
                    'user_id'    => null,
                ]);
            } else {
                Online::query()->create([
                    'ip'         => getIp(),
                    'brow'       => getBrowser(),
                    'updated_at' => SITETIME,
                ]);
                $newHost = true;
            }
        }
        // -----------------------------------------------------------//
        $counter = Counter::query()->first();

        if ($counter->hours != $hours) {
            DB::insert("insert ignore into `counters24` (`hour`, `hosts`, `hits`) values (?, ?, ?);", [$hours, $counter->hosts24, $counter->hits24]);
            DB::update("update `counters` set `hours`=?, `hosts24`=?, `hits24`=?;", [$hours, 0, 0]);
            DB::delete("delete from `counters24` where `hour` < (select min(`hour`) from (select `hour` from `counters24` order by `hour` desc limit 24) as del);");
        }

        if ($counter->days != $days) {
            DB::insert("insert ignore into `counters31` (`days`, `hosts`, `hits`) values (?, ?, ?);", [$days, $counter->dayhosts, $counter->dayhits]);
            DB::update("update `counters` set `days`=?, `dayhosts`=?, `dayhits`=?;", [$days, 0, 0]);
            DB::delete("delete from `counters31` where `days` < (select min(`days`) from (select `days` from `counters31` order by `days` desc limit 31) as del);");
            // ---------------------------------------------------//

            $week = Counter31::query()
                ->orderBy('days', 'desc')
                ->limit(6)
                ->pluck('hosts', 'days')
                ->all();

            $hostData = [];
            for ($i = 0, $tekdays = $days; $i < 6; $tekdays--, $i++) {
                array_unshift($hostData, $week[$tekdays] ?? 0);
            }

            file_put_contents(STORAGE . '/temp/counter7.dat', json_encode($hostData), LOCK_EX);
        }

        // -----------------------------------------------------------//
        if ($newHost) {
            $counter->update([
                'allhosts' => DB::raw('allhosts + 1'),
                'allhits'  => DB::raw('allhits + 1'),
                'dayhosts' => DB::raw('dayhosts + 1'),
                'dayhits'  => DB::raw('dayhits + 1'),
                'hosts24'  => DB::raw('hosts24 + 1'),
                'hits24'   => DB::raw('hits24 + 1'),
            ]);
        } else {
            $counter->update([
                'allhits' => DB::raw('allhits + 1'),
                'dayhits' => DB::raw('dayhits + 1'),
                'hits24'  => DB::raw('hits24 + 1'),
            ]);
        }
    }
}