Move stats to their own models

This commit is contained in:
DariusIII
2024-09-10 22:22:01 +02:00
parent e1ebe235fe
commit ce4d47e0f0
15 changed files with 365 additions and 129 deletions
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace App\Console\Commands;
use App\Models\DownloadStat;
use App\Models\GrabStat;
use App\Models\ReleaseStat;
use App\Models\RoleStat;
use App\Models\SignupStat;
use Illuminate\Console\Command;
class CollectStats extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'nntmux:collect-stats';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Collects and stores various statistics about the site.';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Collecting site stats...');
GrabStat::insertTopGrabbers();
$this->info('Top grabbers collected.');
DownloadStat::insertTopDownloads();
$this->info('Top downloads collected.');
ReleaseStat::insertRecentlyAdded();
$this->info('Recently added releases collected.');
SignupStat::insertUsersByMonth();
$this->info('New users by month collected.');
RoleStat::insertUsersByRole();
$this->info('Users by role collected.');
$this->info('Site stats collected.');
}
}
@@ -4,7 +4,12 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\BasePageController;
use App\Models\Category;
use App\Models\DownloadStat;
use App\Models\GrabStat;
use App\Models\ReleaseStat;
use App\Models\RoleStat;
use App\Models\Settings;
use App\Models\SignupStat;
use App\Models\SiteStat;
use Blacklight\utility\Utility;
use Illuminate\Http\Request;
@@ -182,19 +187,19 @@ class AdminSiteController extends BasePageController
$meta_title = $title = 'Site Stats';
$topGrabs = SiteStat::getTopGrabbers();
$topGrabs = GrabStat::getTopGrabbers();
$this->smarty->assign('topgrabs', $topGrabs);
$topDownloads = SiteStat::getTopDownloads();
$topDownloads = DownloadStat::getTopDownloads();
$this->smarty->assign('topdownloads', $topDownloads);
$recent = SiteStat::getRecentlyAdded();
$recent = ReleaseStat::getRecentlyAdded();
$this->smarty->assign('recent', $recent);
$usersByMonth = SiteStat::getUsersByMonth();
$usersByMonth = SignupStat::getUsersByMonth();
$this->smarty->assign('usersbymonth', $usersByMonth);
$usersByRole = SiteStat::usersByRole();
$usersByRole = RoleStat::getUsersByRole();
$this->smarty->assign('usersbyrole', $usersByRole);
$this->smarty->assign('totusers', 0);
$this->smarty->assign('totrusers', 0);
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class DownloadStat extends Model
{
use HasFactory;
protected $guarded = [];
public static function insertTopDownloads(): void
{
$releases = Release::query()
->where('grabs', '>', 0)
->select(['id', 'searchname', 'guid', 'adddate'])
->selectRaw('SUM(grabs) as grabs')
->groupBy('id', 'searchname', 'adddate')
->havingRaw('SUM(grabs) > 0')
->orderByDesc('grabs')
->limit(10)
->get();
foreach ($releases as $release) {
self::updateOrCreate([
'searchname' => $release->searchname,
'guid' => $release->guid,
'adddate' => $release->adddate,
'grabs' => $release->grabs,
]);
}
}
public static function getTopDownloads(): array
{
return self::query()->select(['searchname', 'guid', 'adddate', 'grabs'])->get()->toArray();
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class GrabStat extends Model
{
use HasFactory;
protected $guarded = [];
public static function insertTopGrabbers(): void
{
$users = User::query()->selectRaw('id, username, SUM(grabs) as grabs')->groupBy('id', 'username')->having('grabs', '>', 0)->orderByDesc('grabs')->limit(10)->get();
// Insert data into the grab_stats table
foreach ($users as $user) {
self::updateOrCreate(['username' => $user->username], ['grabs' => $user->grabs]);
}
}
public static function getTopGrabbers(): array
{
return self::query()->select(['username', 'grabs'])->get()->toArray();
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class ReleaseStat extends Model
{
use HasFactory;
protected $guarded = [];
public static function insertRecentlyAdded(): void
{
$categories = Category::query()->with('parent')->where('r.adddate', '>', now()->subWeek())->select([
'root_categories_id', DB::raw('COUNT(r.id) as count'), 'title',
])->join('releases as r', 'r.categories_id', '=',
'categories.id')->groupBy('title')->orderByDesc('count')->get();
foreach($categories as $category) {
self::updateOrCreate([
'category' => $category->title,
'count' => $category->count,
]);
}
}
public static function getRecentlyAdded(): array
{
return self::query()->select(['category', 'count'])->get()->toArray();
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Models\Role;
class RoleStat extends Model
{
use HasFactory;
protected $guarded = [];
public static function insertUsersByRole(): void
{
$roles = Role::query()->select(['name'])->withCount('users')->groupBy('name')->having('users_count', '>', 0)->orderByDesc('users_count')->get();
foreach ($roles as $role) {
self::updateOrCreate(['role' => $role->name, 'users' => $role->users_count]);
}
}
public static function getUsersByRole(): array
{
return self::query()->select(['role', 'users'])->get()->toArray();
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class SignupStat extends Model
{
use HasFactory;
protected $guarded = [];
public static function insertUsersByMonth(): void
{
$users = User::query()->whereNotNull('created_at')->where('created_at', '<>', '0000-00-00 00:00:00')->selectRaw("DATE_FORMAT(created_at, '%M %Y') as mth, COUNT(id) as num")->groupBy(['mth'])->orderByDesc('created_at')->get();
foreach ($users as $user) {
self::updateOrCreate(['month' => $user->mth], ['signups' => $user->num]);
}
}
public static function getUsersByMonth(): array
{
return self::query()->select(['month', 'signups'])->get()->toArray();
}
}
-95
View File
@@ -2,7 +2,6 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
@@ -14,98 +13,4 @@ class SiteStat extends Model
use HasFactory;
protected $guarded = [];
/**
* @return Collection|\Illuminate\Support\Collection|static[]
*/
public static function getTopGrabbers()
{
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
$result = Cache::get(md5('topGrabbers'));
if ($result !== null) {
return $result;
}
$result = User::query()->selectRaw('id, username, SUM(grabs) as grabs')->groupBy('id', 'username')->having('grabs', '>', 0)->orderByDesc('grabs')->limit(10)->get();
Cache::put(md5('topGrabbers'), $result, $expiresAt);
return $result;
}
/**
* @return Collection|\Illuminate\Support\Collection|static[]
*/
public static function getUsersByMonth()
{
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
$result = Cache::get(md5('usersByMonth'));
if ($result !== null) {
return $result;
}
$result = User::query()->whereNotNull('created_at')->where('created_at', '<>', '0000-00-00 00:00:00')->selectRaw("DATE_FORMAT(created_at, '%M %Y') as mth, COUNT(id) as num")->groupBy(['mth'])->orderByDesc('created_at')->get();
Cache::put(md5('usersByMonth'), $result, $expiresAt);
return $result;
}
/**
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
*/
public static function getTopDownloads()
{
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
$result = Cache::get(md5('topDownloads'));
if ($result !== null) {
return $result;
}
$result = Release::query()
->where('grabs', '>', 0)
->select(['id', 'searchname', 'guid', 'adddate'])
->selectRaw('SUM(grabs) as grabs')
->groupBy('id', 'searchname', 'adddate')
->havingRaw('SUM(grabs) > 0')
->orderByDesc('grabs')
->limit(10)
->get();
Cache::put(md5('topDownloads'), $result, $expiresAt);
return $result;
}
/**
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
*/
public static function getRecentlyAdded()
{
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
$result = Cache::get(md5('RecentlyAdded'));
if ($result !== null) {
return $result;
}
$result = Category::query()->with('parent')->where('r.adddate', '>', now()->subWeek())->select([
'root_categories_id', DB::raw('COUNT(r.id) as count'), 'title',
])->join('releases as r', 'r.categories_id', '=',
'categories.id')->groupBy('title')->orderByDesc('count')->get();
Cache::put(md5('RecentlyAdded'), $result, $expiresAt);
return $result;
}
public static function usersByRole()
{
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
$result = Cache::get(md5('usersByRole'));
if ($result !== null) {
return $result;
}
$result = Role::query()->select(['name'])->withCount('users')->groupBy('name')->having('users_count', '>', 0)->orderByDesc('users_count')->get();
Cache::put(md5('usersByRole'), $result, $expiresAt);
return $result;
}
}
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('grab_stats', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('username')->nullable();
$table->integer('grabs')->default(0);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('grab_stats');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('signup_stats', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('month')->nullable();
$table->integer('signups')->default(0);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('signup_stats');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('role_stats', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('role')->nullable();
$table->integer('users')->default(0);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('role_stats');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('download_stats', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('searchname')->nullable();
$table->integer('grabs')->default(0);
$table->string('guid')->nullable();
$table->dateTime('adddate')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('download_stats');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('release_stats', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('category', 255)->index();
$table->integer('count')->default(0);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('release_stats');
}
};
+7 -29
View File
@@ -33,10 +33,10 @@
</tr>
{foreach from=$usersbymonth item=result}
{assign var="totusers" value=$totusers+$result.num}
{assign var="totusers" value=$totusers+$result.signups}
<tr class="{cycle values=",alt"}">
<td width="75%">{$result.mth}</td>
<td>{$result.num}</td>
<td width="75%">{$result.month}</td>
<td>{$result.signups}</td>
</tr>
{/foreach}
<tr>
@@ -57,10 +57,10 @@
</tr>
{foreach from=$usersbyrole item=result}
{assign var="totrusers" value=$totrusers+$result.users_count}
{assign var="totrusers" value=$totrusers+$result.users}
<tr class="{cycle values=",alt"}">
<td width="75%">{$result.name}</td>
<td>{$result.users_count}</td>
<td width="75%">{$result.role}</td>
<td>{$result.users}</td>
</tr>
{/foreach}
<tr>
@@ -106,7 +106,7 @@
{foreach from=$recent item=result}
<tr class="{cycle values=",alt"}">
<td>{$result->parent->title} > {$result->title}</td>
<td>{$result.category} > {$result.category}</td>
<td>{$result.count}</td>
</tr>
{/foreach}
@@ -114,26 +114,4 @@
</table>
<br/><br/>
{if $topcomments|count > 0}
<h2>Top Comments</h2>
<table style="width:100%;margin-top:10px;" class="data table table-striped responsive-utilities jambo-table">
<tr>
<th>Release</th>
<th>Comments</th>
<th>Days Ago</th>
</tr>
{foreach from=$topcomments item=result}
<tr class="{cycle values=",alt"}">
<td width="75%"><a
href="{{url("/details/{$result.guid}/#comments")}}">{$result.searchname|escape:"htmlall"|replace:".":" "}</a>
</td>
<td>{$result.comments}</td>
<td>{$result.adddate|timeago}</td>
</tr>
{/foreach}
</table>
{/if}
</div>
+1
View File
@@ -28,6 +28,7 @@ Schedule::command('telescope:prune')->daily();
Schedule::command('horizon:snapshot')->everyFiveMinutes()->withoutOverlapping();
Schedule::command('cloudflare:reload')->daily();
Schedule::command('cache:prune-stale-tags')->hourly();
Schedule::command('nntmux:collect-stats')->hourly();
if (config('nntmux.purge_inactive_users') === true) {
Schedule::job(new RemoveInactiveAccounts)->daily();
}