Code
Publisium
A modern, fast CMS for building article and blog websites.
Version history
Version 1.0.0.6 2026-10-01
Browse filesFiles changed9
Lines added+58
Lines removed-3
article.php
⋮ 125 unchanged lines ⋮ exit('You do not have permission to preview this article.'); } } else { - $updateViews = $db->prepare('UPDATE articles SET views_count = views_count + 1 WHERE id = :id'); + $updateViews = $db->prepare('UPDATE articles SET views_count = views_count + 1, updated_at = updated_at WHERE id = :id'); $updateViews->execute(['id' => $article['id']]); } ⋮ 30 unchanged lines ⋮ $ogImagePath = !empty($article['cover_image_path']) ? $article['cover_image_path'] : null; $pageType = 'article'; $authorPage = AuthorProfile::isEnabled() ? AuthorProfile::publicSummary((int) $article['author_id']) : null; + $authorPageUrl = $authorPage !== null ? SiteFront::authorUrl((string) $authorPage['slug']) : null; + $ogArticleMeta = [ + 'published' => $article['published_at'] ?? null, + 'modified' => $article['updated_at'] ?? null, + 'author' => $authorPageUrl !== null ? SiteFront::absoluteUrl($authorPageUrl) : (string) $article['author_name'], + 'section' => (string) ($article['category_name'] ?? ''), + ]; + $pageSchema = !$isPreview && $settings['seo_article_schema_enabled'] === '1' + ? SiteFront::renderArticleSchema($article, AuthorProfile::schemaType((int) $article['author_id']), $authorPageUrl) + : ''; $pageTitle = $isPreview ? 'Preview - ' . $pageTitle : $pageTitle; require __DIR__ . '/includes/front-header.php'; ⋮ 217 unchanged lines ⋮
dashboard-actions/save-settings.php
⋮ 222 unchanged lines ⋮ 'seo_robots_index' => isset($_POST['seo_robots_index']) ? '1' : '0', 'seo_robots_follow' => isset($_POST['seo_robots_follow']) ? '1' : '0', 'seo_og_article_image_enabled' => isset($_POST['seo_og_article_image_enabled']) ? '1' : '0', + 'seo_social_tags_enabled' => isset($_POST['seo_social_tags_enabled']) ? '1' : '0', + 'seo_twitter_handle' => preg_match('/^@?([A-Za-z0-9_]{1,15})$/', trim((string) ($_POST['seo_twitter_handle'] ?? '')), $twitterHandle) === 1 ? '@' . $twitterHandle[1] : '', + 'seo_article_schema_enabled' => isset($_POST['seo_article_schema_enabled']) ? '1' : '0', 'clean_article_urls' => isset($_POST['clean_article_urls']) ? '1' : '0', 'clean_page_urls' => isset($_POST['clean_page_urls']) ? '1' : '0', 'clean_author_urls' => isset($_POST['clean_author_urls']) ? '1' : '0', ⋮ 9 unchanged lines ⋮
dashboard-views/profile.php
⋮ 25 unchanged lines ⋮ : AuthorProfile::formValues($profile); $publishDirectly = Auth::canPublishDirectly(); $status = $profile['status'] ?? 'draft'; + $showSchemaType = SiteFront::settings()['seo_article_schema_enabled'] === '1'; + $schemaType = $wasPosted ? (string) ($_POST['schema_type'] ?? '') : (string) ($profile['schema_type'] ?? ''); + $schemaType = in_array($schemaType, AuthorProfile::SCHEMA_TYPES, true) ? $schemaType : 'Person'; ?> <div class="dash-header-row"> ⋮ 31 unchanged lines ⋮ <label>Website (optional)</label> <input type="url" name="website_url" maxlength="<?= AuthorProfile::URL_MAX ?>" value="<?= htmlspecialchars($form['website_url']) ?>" placeholder="https://"> + + <?php if ($showSchemaType): ?> + <label>For search engines, this author is</label> + <select name="schema_type"> + <option value="Person" <?= $schemaType === 'Person' ? 'selected' : '' ?>>A person (Person)</option> + <option value="Organization" <?= $schemaType === 'Organization' ? 'selected' : '' ?>>An organization, e.g. an editorial team or agency (Organization)</option> + </select> + <p style="font-size:12px;color:var(--muted);margin-top:6px;">Used in the article data Google reads. It changes right away, without review.</p> + <?php endif; ?> <p style="font-size:12px;color:var(--muted);margin-top:10px;">Your profile photo is set by an administrator in Team.</p> ⋮ 7 unchanged lines ⋮
includes/author-profile.php
⋮ 10 unchanged lines ⋮ public const BIO_MAX = 2000; public const URL_MAX = 255; public const REASON_MAX = 500; + public const SCHEMA_TYPES = ['Person', 'Organization']; private static ?bool $enabled = null; ⋮ 57 unchanged lines ⋮ } } + public static function schemaType(int $accountId): string + { + if ($accountId <= 0) { + return 'Person'; + } + + try { + $statement = Database::site()->prepare('SELECT schema_type FROM author_profiles WHERE account_id = :account LIMIT 1'); + $statement->execute(['account' => $accountId]); + $type = (string) $statement->fetchColumn(); + } catch (PDOException $e) { + return 'Person'; + } + + return in_array($type, self::SCHEMA_TYPES, true) ? $type : 'Person'; + } + public static function pendingCount(): int { try { ⋮ 95 unchanged lines ⋮ } $db = Database::site(); + + if (in_array($input['schema_type'] ?? null, self::SCHEMA_TYPES, true)) { + $db->prepare('UPDATE author_profiles SET schema_type = :type WHERE account_id = :account') + ->execute(['type' => $input['schema_type'], 'account' => $accountId]); + } if ($intent === 'submit' && $publishDirectly) { $db->prepare( ⋮ 147 unchanged lines ⋮
includes/database.php
⋮ 112 unchanged lines ⋮ 'article_comments' => [ 'author_email' => "ALTER TABLE article_comments ADD COLUMN author_email VARCHAR(190) NULL AFTER author_name", ], + 'author_profiles' => [ + 'schema_type' => "ALTER TABLE author_profiles ADD COLUMN schema_type VARCHAR(12) NOT NULL DEFAULT 'Person' AFTER website_url", + ], 'nav_items' => [ 'icon_key' => "ALTER TABLE nav_items ADD COLUMN icon_key VARCHAR(30) NULL AFTER target", 'icon_svg' => "ALTER TABLE nav_items ADD COLUMN icon_svg MEDIUMTEXT NULL AFTER icon_key", ⋮ 59 unchanged lines ⋮ headline VARCHAR(160) NOT NULL DEFAULT '', bio TEXT NULL, website_url VARCHAR(255) NOT NULL DEFAULT '', + schema_type VARCHAR(12) NOT NULL DEFAULT 'Person', draft_headline VARCHAR(160) NULL, draft_bio TEXT NULL, draft_website_url VARCHAR(255) NULL, ⋮ 181 unchanged lines ⋮
includes/front-header.php
⋮ 29 unchanged lines ⋮ <?php endif; ?> <?= SiteFront::renderSeoMeta() ?> <?= Languages::renderAlternates() ?> - <?= SiteFront::renderOpenGraph($resolvedPageTitle, $resolvedPageDescription, $ogType ?? 'website', $ogImagePath ?? null) ?> + <?= SiteFront::renderOpenGraph($resolvedPageTitle, $resolvedPageDescription, $ogType ?? 'website', $ogImagePath ?? null, $ogArticleMeta ?? null) ?> <?php if ($isHomepage): ?> <?= SiteFront::renderOrganizationSchema() ?> + <?php endif; ?> + <?php if (!empty($pageSchema)): ?> + <?= $pageSchema ?> <?php endif; ?> <?= Asset::favicon() ?> <?php if (($settings['pwa_enabled'] ?? '0') === '1'): ?> ⋮ 130 unchanged lines ⋮
includes/site-front.php
Not shown (binary file or too large to diff).
settings.php
Not shown (binary file or too large to diff).
version.txt
- 1.0.0.5 + 1.0.0.6