WebOrbiton
v2.0.0.0

Publisium

119 lines · 5.1 KB
  1. <?php
  2. ​
  3. declare(strict_types=1);
  4. ​
  5. require_once __DIR__ . '/includes/config.php';
  6. require_once __DIR__ . '/includes/database.php';
  7. require_once __DIR__ . '/includes/user-auth.php';
  8. require_once __DIR__ . '/includes/language.php';
  9. require_once __DIR__ . '/includes/site-front.php';
  10. require_once __DIR__ . '/includes/pagination.php';
  11. require_once __DIR__ . '/includes/article-card.php';
  12. require_once __DIR__ . '/includes/author-profile.php';
  13. require_once __DIR__ . '/includes/avatar.php';
  14. ​
  15. UserAuth::boot();
  16. ​
  17. $db = Database::site();
  18. $settings = SiteFront::settings();
  19. ​
  20. $slug = trim((string) ($_GET['slug'] ?? ''));
  21. $profile = AuthorProfile::isEnabled() ? AuthorProfile::findPublicBySlug($slug) : null;
  22. ​
  23. if ($profile === null) {
  24. http_response_code(404);
  25. $pageTitle = Language::get('not_found_title', 'Not found') . ' - ' . $settings['site_name'];
  26. $showBanner = false;
  27. require __DIR__ . '/includes/front-header.php';
  28. echo '<p>' . htmlspecialchars(Language::get('artist_not_found', 'Author not found.')) . '</p>';
  29. require __DIR__ . '/includes/front-footer.php';
  30. exit;
  31. }
  32. ​
  33. if (!defined('PUBLISIUM_SHORT_LINK') && CleanUrls::slugFor('author', (string) $profile['slug']) !== null) {
  34. CleanUrls::redirect(SiteFront::authorUrl((string) $profile['slug']));
  35. }
  36. ​
  37. $authorId = (int) $profile['account_id'];
  38. ​
  39. $totalStatement = $db->prepare("SELECT COUNT(*) FROM articles a WHERE a.status = 'published' AND a.author_id = :author" . Languages::articleFilterSql('a'));
  40. $totalStatement->execute(['author' => $authorId]);
  41. $totalArticles = (int) $totalStatement->fetchColumn();
  42. ​
  43. $isStaticArticleLoading = ($settings['article_loading_mode'] ?? 'scroll') === 'static';
  44. $perPage = $isStaticArticleLoading
  45. ? max(1, $totalArticles)
  46. : max(1, (int) $settings['articles_per_page_category']);
  47. $currentPage = $isStaticArticleLoading ? 1 : Pagination::currentPage();
  48. $totalPages = Pagination::totalPages($totalArticles, $perPage);
  49. $currentPage = min($currentPage, $totalPages);
  50. $offset = Pagination::offset($currentPage, $perPage);
  51. ​
  52. $articlesStatement = $db->prepare(
  53. "SELECT a.*, c.name AS category_name, c.slug AS category_slug
  54. FROM articles a
  55. LEFT JOIN categories c ON c.id = a.category_id
  56. WHERE a.status = 'published' AND a.author_id = :author" . Languages::articleFilterSql('a') . "
  57. ORDER BY a.published_at DESC
  58. LIMIT :limit OFFSET :offset"
  59. );
  60. $articlesStatement->bindValue('author', $authorId, PDO::PARAM_INT);
  61. $articlesStatement->bindValue('limit', $perPage, PDO::PARAM_INT);
  62. $articlesStatement->bindValue('offset', $offset, PDO::PARAM_INT);
  63. $articlesStatement->execute();
  64. $articles = Languages::articles($articlesStatement->fetchAll());
  65. ​
  66. $authorName = (string) $profile['display_name'];
  67. $websiteUrl = AuthorProfile::safeUrl((string) $profile['website_url']);
  68. $bioText = trim((string) $profile['bio']);
  69. ​
  70. $pageTitle = $authorName . ' - ' . $settings['site_name'];
  71. $pageDescription = $profile['headline'] !== '' ? (string) $profile['headline'] : mb_substr((string) preg_replace('/\s+/u', ' ', $bioText), 0, 160);
  72. $showBanner = false;
  73. $pageType = 'author';
  74. $ogType = 'profile';
  75. $ogImagePath = Avatar::isValidPath((string) $profile['avatar_path']) ? (string) $profile['avatar_path'] : null;
  76. ​
  77. require __DIR__ . '/includes/front-header.php';
  78. ​
  79. ?>
  80. <section class="artist-header">
  81. <?= Avatar::html($profile, 'artist-avatar') ?>
  82. <div class="artist-header-info">
  83. <h1 class="artist-name"><?= htmlspecialchars($authorName) ?></h1>
  84. <?php if ($profile['headline'] !== ''): ?>
  85. <p class="artist-headline"><?= htmlspecialchars((string) $profile['headline']) ?></p>
  86. <?php endif; ?>
  87. <p class="artist-meta">
  88. <?= htmlspecialchars(str_replace('{count}', (string) $totalArticles, Language::get('author_articles_count', 'Articles: {count}'))) ?>
  89. <?php if ($websiteUrl !== null && $websiteUrl !== ''): ?>
  90. &middot; <a href="<?= htmlspecialchars($websiteUrl, ENT_QUOTES) ?>" target="_blank" rel="nofollow ugc noopener noreferrer"><?= htmlspecialchars(Language::get('artist_website', 'Website')) ?></a>
  91. <?php endif; ?>
  92. </p>
  93. </div>
  94. </section>
  95. ​
  96. <?php if ($bioText !== ''): ?>
  97. <div class="artist-bio"><?= nl2br(htmlspecialchars($bioText)) ?></div>
  98. <?php endif; ?>
  99. ​
  100. <div class="section-heading-row">
  101. <h2 class="section-heading"><?= htmlspecialchars(str_replace('{name}', $authorName, Language::get('artist_articles_title', 'Articles by {name}'))) ?></h2>
  102. </div>
  103. ​
  104. <div class="article-grid" id="article-list">
  105. <?php foreach ($articles as $article): ?>
  106. <?= renderArticleCard($article) ?>
  107. <?php endforeach; ?>
  108. <?php if (empty($articles)): ?>
  109. <p><?= htmlspecialchars(Language::get('artist_no_articles', 'No published articles yet.')) ?></p>
  110. <?php endif; ?>
  111. </div>
  112. ​
  113. <div id="pagination-container">
  114. <?php $authorShortUrl = CleanUrls::slugFor('author', $slug) !== null ? SiteFront::authorUrl($slug) : null; ?>
  115. <?= $isStaticArticleLoading ? '' : Pagination::render('numbered', $authorShortUrl ?? 'artist.php', $currentPage, $totalPages, $authorShortUrl !== null ? [] : ['slug' => $slug], 'article-list') ?>
  116. </div>
  117. ​
  118. <?php require __DIR__ . '/includes/front-footer.php'; ?>
  119. ​