xgit simple git

nexus

nexus

clone git clone https://kb.hax.al/nexus

forum/new-topic.php


1<?php
2require_once __DIR__ . '/../includes/bootstrap.php';
3must_login();
4 
5$allCats = DB::rows('SELECT * FROM categories ORDER BY position, id');
6$cats    = array_filter($allCats, fn($c) => can_post_topic($c));
7$selCat  = (int)get('cat');
8$errs    = [];
9 
10if ($_SERVER['REQUEST_METHOD'] === 'POST') {
11    if (!csrf_ok()) { $errs[] = 'Invalid request.'; }
12    else {
13        $title   = sanitise(post('title'));
14        $content = sanitise(post('content'));
15        $catId   = (int)post('cat_id');
16        $tagStr  = sanitise(post('tags'));
17 
18        if (!$title)   $errs[] = 'Title is required.';
19        if (!$content) $errs[] = 'Post content is required.';
20        if (!$catId)   $errs[] = 'Please select a category.';
21        if (strlen($title) > 200) $errs[] = 'Title too long (max 200 chars).';
22        if (strlen($content) > 50000) $errs[] = 'Content too long.';
23 
24        if (!$errs && !DB::row('SELECT id FROM categories WHERE id=?', [$catId])) $errs[] = 'Invalid category.';
25        if (!$errs) {
26            $postCat = DB::row('SELECT * FROM categories WHERE id=?', [$catId]);
27            if (!$postCat || !can_post_topic($postCat)) $errs[] = 'You do not have permission to post in this category.';
28        }
29 
30        if (!$errs && cfg('topic_captcha_enabled', '0') === '1') {
31            if (!post_captcha_verify(post('topic_captcha'))) $errs[] = 'Incorrect security answer.';
32        }
33 
34        if (!$errs) {
35            $rl = rate_check((int)$USER['id'], 'topic');
36            if (!$rl['ok']) {
37                $wait  = (int)$rl['wait'];
38                $errs[] = "Slow down! Please wait {$wait} second" . ($wait !== 1 ? 's' : '') . '.';
39            }
40        }
41 
42        if (!$errs) {
43            $slug = unique_slug($title, 'topics');
44            $tid  = DB::insert('INSERT INTO topics (title,slug,category_id,user_id) VALUES (?,?,?,?)',
45                [$title, $slug, $catId, $USER['id']]);
46            $pid  = DB::insert('INSERT INTO posts (topic_id,user_id,content,post_num) VALUES (?,?,?,1)',
47                [$tid, $USER['id'], $content]);
48 
49            if ($tagStr) {
50                $names = array_slice(array_filter(array_map('trim', explode(',', mb_strtolower($tagStr)))), 0, 5);
51                foreach ($names as $n) {
52                    if (!$n) continue;
53                    $tg   = DB::row('SELECT id FROM tags WHERE name=?', [$n]);
54                    $tgId = $tg ? $tg['id'] : DB::insert('INSERT INTO tags (name) VALUES (?)', [$n]);
55                    DB::insertIgnore('topic_tags', ['topic_id', 'tag_id'], [$tid, $tgId]);
56                    DB::run('UPDATE tags SET topic_count=topic_count+1 WHERE id=?', [$tgId]);
57                }
58            }
59            DB::run('UPDATE users SET topic_count=topic_count+1,post_count=post_count+1 WHERE id=?', [$USER['id']]);
60            DB::run('UPDATE categories SET topic_count=topic_count+1,post_count=post_count+1 WHERE id=?', [$catId]);
61            process_mentions($content, $pid, $slug, (int)$USER['id'], $USER['username']);
62            rate_record((int)$USER['id'], 'topic');
63            addon_hook('after_topic_created', ['topic_id'=>$tid,'title'=>$title,'slug'=>$slug,'category_id'=>$catId,'user_id'=>(int)$USER['id']]);
64            go('forum/topic.php?slug=' . urlencode($slug));
65        }
66    }
67}
68 
69$PAGE_TITLE = 'New Topic';
70include __DIR__ . '/../views/partials/layout.php';
71?>
72<nav class="bc"><a href="<?=u('/')?>">Home</a> β€Ί <span>New Topic</span></nav>
73<div class="form-card">
74  <h1>Create a New Topic</h1>
75  <?php if($errs):?><div class="alert err"><?=implode('<br>',array_map('e',$errs))?></div><?php endif;?>
76  <form method="POST" id="ntForm">
77    <?=csrf_input()?>
78    <div class="fg">
79      <label>Category <span class="req">*</span></label>
80      <select name="cat_id" class="fi" required>
81        <option value="">β€” Select a category β€”</option>
82        <?php foreach($cats as $c):?>
83          <option value="<?=$c['id']?>" <?=($selCat==$c['id']||((int)($_POST['cat_id']??0))==$c['id'])?'selected':''?>>
84            <?=e($c['icon'])?> <?=e($c['name'])?>
85          </option>
86        <?php endforeach;?>
87      </select>
88    </div>
89    <div class="fg">
90      <label>Title <span class="req">*</span></label>
91      <input type="text" name="title" class="fi" required maxlength="200"
92             value="<?=e($_POST['title']??'')?>" placeholder="What is this about?">
93    </div>
94    <div class="fg">
95      <label>Tags <small>(optional, comma-separated)</small></label>
96      <input type="text" name="tags" id="tagsIn" class="fi" value="<?=e($_POST['tags']??'')?>" placeholder="help, tutorial">
97      <div id="tagPreview" class="tag-preview"></div>
98    </div>
99    <div class="fg">
100      <label>Content <span class="req">*</span></label>
101      <div class="ed-toolbar">
102        <button type="button" onclick="fmt('bold','replyTa')"><b>B</b></button>
103        <button type="button" onclick="fmt('italic','replyTa')"><i>I</i></button>
104        <button type="button" onclick="fmt('link','replyTa')">πŸ”—</button>
105        <button type="button" onclick="fmt('quote','replyTa')" title="Quote"><svg viewBox="0 0 24 24" fill="currentColor" width="13" height="13" style="vertical-align:middle"><path d="M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z"/></svg></button>
106        <button type="button" onclick="fmt('codeblock','replyTa')">πŸ“„</button>
107        <button type="button" onclick="fmt('heading','replyTa')">H</button>
108        <button type="button" onclick="fmt('ul','replyTa')">≑</button>
109        <div class="ed-sep"></div>
110        <button type="button" onclick="pickImg('ntImg','replyTa')">πŸ–Ό</button>
111        <input type="file" id="ntImg" accept="image/*" style="display:none" onchange="uploadImg(this,'replyTa')">
112        <div class="ed-sep"></div>
113        <button type="button" id="prevBtn" onclick="togglePreview()">πŸ‘ Preview</button>
114      </div>
115      <div class="ed-panes">
116        <textarea id="replyTa" name="content" class="reply-ta" rows="14" required
117                  placeholder="Write your post… Markdown supported.&#10;Tip: use @username to mention someone!"><?=e($_POST['content']??'')?></textarea>
118        <div id="replyPreview" class="reply-preview hidden"></div>
119      </div>
120    </div>
121    <?php if (cfg('topic_captcha_enabled','0') === '1'): ?>
122      <?php $tc = post_captcha_generate(); ?>
123      <div class="fg captcha-box">
124        <label class="captcha-label">πŸ”’ Security β€” What is <strong class="captcha-q"><?= e($tc['q']) ?></strong></label>
125        <input type="number" name="topic_captcha" class="fi captcha-input" required placeholder="Answer" autocomplete="off" min="-99" max="99">
126        <span class="hint">Solve this math problem to post</span>
127      </div>
128    <?php endif; ?>
129 
130    <div class="form-actions">
131      <a href="<?=u('/')?>" class="btn-ghost">Cancel</a>
132      <button type="submit" class="btn-primary btn-lg">Post Topic</button>
133    </div>
134  </form>
135</div>
136<script>
137document.getElementById('tagsIn').addEventListener('input',function(){
138  var tags=this.value.split(',').map(function(t){return t.trim();}).filter(Boolean);
139  document.getElementById('tagPreview').innerHTML=tags.map(function(t){return '<span class="tag">'+escH(t)+'</span>';}).join('');
140});
141function escH(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
142document.getElementById('replyTa').addEventListener('paste',function(e){
143  var items=(e.clipboardData||e.originalEvent.clipboardData).items;
144  for(var i=0;i<items.length;i++){if(items[i].type.indexOf('image')!==-1){e.preventDefault();uploadFileToEditor(items[i].getAsFile(),'replyTa');}}
145});
146</script>
147<?php include __DIR__ . '/../views/partials/layout_end.php'; ?>