first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?php
namespace Common\Votes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
trait OrdersByWeightedScore
{
public function scopeOrderByWeightedScore(
Builder $query,
$direction = 'desc',
string $positiveCol = 'upvotes',
string $negativeCol = 'downvotes',
): Builder {
return $query
->select($query->getQuery()->columns ?? '*')
->addSelect([
DB::raw(
"(($positiveCol + 1.9208) / ($positiveCol + $negativeCol) -.96 * SQRT(($positiveCol * $negativeCol) / ($positiveCol + $negativeCol) + 0.9604) / ($positiveCol + $negativeCol)) / (1 + 3.8416 / ($positiveCol + $negativeCol)) AS weighted_score",
),
])
->orderBy('weighted_score', $direction);
}
}

66
common/Votes/StoreVote.php Executable file
View File

@@ -0,0 +1,66 @@
<?php
namespace Common\Votes;
use Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
class StoreVote
{
public function execute($model, string $newVoteType, ?string $userIp)
{
$userId = Auth::id();
// if we can't match current user, bail
if (!$userId && !$userIp) {
return null;
}
$currentVote = $model
->votes()
->where(
fn(Builder $query) => $query
->where('user_id', $userId)
->orWhere('user_ip', $userIp),
)
->first();
// remove old vote from this user
if ($currentVote) {
$this->deleteCurrentVote($model, $currentVote);
}
// create a new rating
if (!$currentVote || $currentVote->vote_type !== $newVoteType) {
$this->storeVote($model, $newVoteType, $userId, $userIp);
}
return $model;
}
private function deleteCurrentVote($model, Vote $vote): void
{
$column = Str::plural($vote->vote_type);
if ($model->$column > 0) {
$model->decrement($column);
}
$vote->delete();
}
private function storeVote(
$model,
string $voteType,
?int $userId,
?string $userIp,
): void
{
$model->votes()->create([
'vote_type' => $voteType,
'user_id' => $userId,
'user_ip' => $userIp,
]);
$model->increment(Str::plural($voteType), 1);
}
}

24
common/Votes/Vote.php Executable file
View File

@@ -0,0 +1,24 @@
<?php
namespace Common\Votes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Vote extends Model
{
protected $guarded = ['id'];
protected $casts = [
'id' => 'integer',
'user_id' => 'integer',
];
public $timestamps = false;
public function scopeWithCurrentUserVotes(Builder $query): Builder
{
return $query
->where('user_id', auth()->id())
->orWhere('user_ip', getIp());
}
}

37
common/Votes/VoteController.php Executable file
View File

@@ -0,0 +1,37 @@
<?php
namespace Common\Votes;
use Common\Core\BaseController;
class VoteController extends BaseController
{
public function store()
{
$data = $this->validate(request(), [
'vote_type' => 'required|in:upvote,downvote',
'model_type' => 'required|string',
'model_id' => 'required|integer',
]);
$namespace = modelTypeToNamespace($data['model_type']);
$model = app($namespace)::findOrFail($data['model_id']);
$this->authorize('vote', $model);
$model = app(StoreVote::class)->execute(
$model,
$data['vote_type'],
getIp(),
);
$model->unsetRelation('votes');
$model->load([
'votes' => fn($builder) => $builder->withCurrentUserVotes(),
]);
$model->current_vote = $model->votes->first()?->vote_type;
$model->unsetRelation('votes');
return $this->success(['model' => $model]);
}
}