HEX
Server: Apache
System: Linux info 3.0 #1337 SMP Tue Jan 01 00:00:00 CEST 2000 all GNU/Linux
User: u115237990 (7145895)
PHP: 8.3.32
Disabled: NONE
Upload Files
File: /homepages/35/d993672390/htdocs/dermiteseborrheique/includes/social.php
<?php
/**
 * social.php — Fonctions utilitaires du module social
 */
declare(strict_types=1);
if (!defined('DS_APP')) die('Accès direct interdit.');

class Social
{
    // ── Slug SEO ──────────────────────────────────────────────────────────────
    public static function makeSlug(string $title, int $id): string
    {
        $slug = mb_strtolower($title);
        $slug = str_replace(
            ['é','è','ê','ë','à','â','ä','î','ï','ô','ö','ù','û','ü','ç','œ','æ'],
            ['e','e','e','e','a','a','a','i','i','o','o','u','u','u','c','oe','ae'],
            $slug
        );
        $slug = preg_replace('/[^a-z0-9\s-]/', '', $slug);
        $slug = preg_replace('/[\s-]+/', '-', trim($slug));
        $slug = mb_substr($slug, 0, 80);
        $slug = rtrim($slug, '-');
        return $id . '-' . $slug;
    }

    // ── URL d'un post ─────────────────────────────────────────────────────────
    public static function postUrl(array $post): string
    {
        return url('social/post/' . $post['slug'] . '/');
    }

    // ── URL d'un profil ───────────────────────────────────────────────────────
    public static function profileUrl(string $username): string
    {
        return url('social/u/' . rawurlencode($username) . '/');
    }

    // ── Sanitize body (markdown simplifié) ────────────────────────────────────
    public static function renderBody(string $body): string
    {
        $body = e($body);
        // Gras **text**
        $body = preg_replace('/\*\*(.+?)\*\*/s', '<strong>$1</strong>', $body);
        // Italique *text*
        $body = preg_replace('/\*(.+?)\*/s', '<em>$1</em>', $body);
        // Lien [texte](url)
        $body = preg_replace(
            '/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/',
            '<a href="$2" rel="nofollow noopener" target="_blank">$1</a>',
            $body
        );
        // Retours à la ligne
        $body = nl2br($body);
        return $body;
    }

    // ── Pseudo forum (auto si non défini) ────────────────────────────────────
    public static function getForumUsername(array $user): string
    {
        return $user['forum_username'] ?? 'utilisateur_' . $user['id'];
    }

    // ── Vote ──────────────────────────────────────────────────────────────────
    public static function vote(int $userId, string $type, int $targetId, int $value): array
    {
        // Récupérer vote existant
        $existing = db_fetch(
            "SELECT id, value FROM social_votes
             WHERE user_id=? AND target_type=? AND target_id=?",
            [$userId, $type, $targetId]
        );

        $table  = $type === 'post' ? 'social_posts' : 'social_replies';
        $delta  = 0;

        if ($existing) {
            if ($existing['value'] === $value) {
                // Annuler le vote
                db_execute("DELETE FROM social_votes WHERE id=?", [$existing['id']]);
                $delta = -$value;
            } else {
                // Changer le vote
                db_execute("UPDATE social_votes SET value=? WHERE id=?", [$value, $existing['id']]);
                $delta = $value * 2;
            }
        } else {
            db_insert(
                "INSERT INTO social_votes (user_id, target_type, target_id, value) VALUES (?,?,?,?)",
                [$userId, $type, $targetId, $value]
            );
            $delta = $value;
        }

        if ($delta !== 0) {
            db_execute("UPDATE {$table} SET score = score + ? WHERE id=?", [$delta, $targetId]);
            // Karma de l'auteur
            $authorId = db_fetch("SELECT user_id FROM {$table} WHERE id=?", [$targetId])['user_id'] ?? null;
            if ($authorId && $authorId !== $userId) {
                db_execute("UPDATE users SET forum_karma = forum_karma + ? WHERE id=?", [$delta, $authorId]);
            }
        }

        $newScore = db_fetch("SELECT score FROM {$table} WHERE id=?", [$targetId])['score'] ?? 0;
        return ['success' => true, 'score' => $newScore, 'delta' => $delta];
    }

    // ── Tags : parse & update ─────────────────────────────────────────────────
    public static function parseTags(string $raw): array
    {
        $tags = array_map('trim', explode(',', $raw));
        $tags = array_filter($tags, fn($t) => mb_strlen($t) >= 2 && mb_strlen($t) <= 30);
        $tags = array_map(fn($t) => mb_strtolower(preg_replace('/[^a-z0-9\-éèêàâîôùûç ]/i', '', $t)), $tags);
        return array_values(array_unique(array_slice($tags, 0, 5)));
    }

    public static function updateTagCounts(array $tags): void
    {
        foreach ($tags as $tag) {
            $slug = self::makeTagSlug($tag);
            db_execute(
                "INSERT INTO social_tags (slug, label, post_count) VALUES (?,?,1)
                 ON DUPLICATE KEY UPDATE label=VALUES(label), post_count = post_count + 1",
                [$slug, $tag]
            );
        }
    }

    public static function makeTagSlug(string $tag): string
    {
        $tag = mb_strtolower($tag);
        $tag = str_replace(
            ['é','è','ê','ë','à','â','ä','î','ï','ô','ö','ù','û','ü','ç'],
            ['e','e','e','e','a','a','a','i','i','o','o','u','u','u','c'],
            $tag
        );
        return preg_replace('/[^a-z0-9-]/', '-', trim($tag));
    }

    // ── Excerpt ───────────────────────────────────────────────────────────────
    public static function excerpt(string $body, int $len = 160): string
    {
        // Stripper le markdown avant l'extrait
        $plain = $body;
        $plain = preg_replace('/\*\*(.+?)\*\*/s', '$1', $plain);  // **gras**
        $plain = preg_replace('/\*(.+?)\*/s', '$1', $plain);       // *italique*
        $plain = preg_replace('/\[([^\]]+)\]\([^\)]+\)/', '$1', $plain); // [lien](url)
        $plain = preg_replace('/#{1,6}\s/', '', $plain);            // # titres
        $plain = strip_tags($plain);
        $plain = preg_replace('/\s+/', ' ', trim($plain));
        return mb_strlen($plain) > $len
            ? mb_substr($plain, 0, $len) . '…'
            : $plain;
    }

    // ── Temps relatif ─────────────────────────────────────────────────────────
    public static function timeAgo(string $datetime): string
    {
        $diff = time() - strtotime($datetime);
        return match(true) {
            $diff < 60     => 'à l\'instant',
            $diff < 3600   => round($diff/60) . ' min',
            $diff < 86400  => round($diff/3600) . 'h',
            $diff < 604800 => round($diff/86400) . 'j',
            default        => date('d/m/Y', strtotime($datetime)),
        };
    }

    // ── Vérification username disponible ──────────────────────────────────────
    public static function isUsernameAvailable(string $username, int $excludeUserId = 0): bool
    {
        if (!preg_match('/^[a-zA-Z0-9_-]{3,30}$/', $username)) return false;
        $count = db_count(
            "SELECT COUNT(*) FROM users WHERE forum_username = ? AND id != ?",
            [$username, $excludeUserId]
        );
        return $count === 0;
    }
}