xgit simple git

nexus

nexus

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

forum/new-topic.php

1 <?php
2 require_once __DIR__ . '/../includes/bootstrap.php';
3 must_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 
10 if ($_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';
70 include __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>
137 document.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 });
141 function escH(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
142 document.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'; ?>