1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17declare(strict_types=1); 18 19namespace Fisharebest\Webtrees\Module; 20 21use Fisharebest\Webtrees\Auth; 22use Fisharebest\Webtrees\Carbon; 23use Fisharebest\Webtrees\I18N; 24use Fisharebest\Webtrees\Services\HtmlService; 25use Fisharebest\Webtrees\Tree; 26use Illuminate\Database\Capsule\Manager as DB; 27use Illuminate\Support\Str; 28use InvalidArgumentException; 29use Psr\Http\Message\ResponseInterface; 30use Psr\Http\Message\ServerRequestInterface; 31use stdClass; 32use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; 33use function assert; 34 35/** 36 * Class UserJournalModule 37 */ 38class UserJournalModule extends AbstractModule implements ModuleBlockInterface 39{ 40 use ModuleBlockTrait; 41 42 /** @var HtmlService */ 43 private $html_service; 44 45 /** 46 * HtmlBlockModule bootstrap. 47 * 48 * @param HtmlService $html_service 49 */ 50 public function boot(HtmlService $html_service) 51 { 52 $this->html_service = $html_service; 53 } 54 55 /** 56 * A sentence describing what this module does. 57 * 58 * @return string 59 */ 60 public function description(): string 61 { 62 /* I18N: Description of the “Journal” module */ 63 return I18N::translate('A private area to record notes or keep a journal.'); 64 } 65 66 /** 67 * Generate the HTML content of this block. 68 * 69 * @param Tree $tree 70 * @param int $block_id 71 * @param string $context 72 * @param string[] $config 73 * 74 * @return string 75 */ 76 public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string 77 { 78 $articles = DB::table('news') 79 ->where('user_id', '=', Auth::id()) 80 ->orderByDesc('updated') 81 ->get() 82 ->map(static function (stdClass $row): stdClass { 83 $row->updated = Carbon::make($row->updated); 84 85 return $row; 86 }); 87 88 $content = view('modules/user_blog/list', [ 89 'articles' => $articles, 90 'block_id' => $block_id, 91 'limit' => 5, 92 ]); 93 94 if ($context !== self::CONTEXT_EMBED) { 95 return view('modules/block-template', [ 96 'block' => Str::kebab($this->name()), 97 'id' => $block_id, 98 'config_url' => '', 99 'title' => $this->title(), 100 'content' => $content, 101 ]); 102 } 103 104 return $content; 105 } 106 107 /** 108 * How should this module be identified in the control panel, etc.? 109 * 110 * @return string 111 */ 112 public function title(): string 113 { 114 /* I18N: Name of a module */ 115 return I18N::translate('Journal'); 116 } 117 118 /** 119 * Should this block load asynchronously using AJAX? 120 * 121 * Simple blocks are faster in-line, more complex ones can be loaded later. 122 * 123 * @return bool 124 */ 125 public function loadAjax(): bool 126 { 127 return false; 128 } 129 130 /** 131 * Can this block be shown on the user’s home page? 132 * 133 * @return bool 134 */ 135 public function isUserBlock(): bool 136 { 137 return true; 138 } 139 140 /** 141 * Can this block be shown on the tree’s home page? 142 * 143 * @return bool 144 */ 145 public function isTreeBlock(): bool 146 { 147 return false; 148 } 149 150 /** 151 * @param ServerRequestInterface $request 152 * 153 * @return ResponseInterface 154 */ 155 public function getEditJournalAction(ServerRequestInterface $request): ResponseInterface 156 { 157 if (!Auth::check()) { 158 throw new AccessDeniedHttpException(); 159 } 160 161 $news_id = $request->getQueryParams()['news_id'] ?? ''; 162 163 if ($news_id !== '') { 164 $row = DB::table('news') 165 ->where('news_id', '=', $news_id) 166 ->where('user_id', '=', Auth::id()) 167 ->first(); 168 } else { 169 $row = (object) [ 170 'body' => '', 171 'subject' => '', 172 ]; 173 } 174 175 $title = I18N::translate('Add/edit a journal/news entry'); 176 177 return $this->viewResponse('modules/user_blog/edit', [ 178 'body' => $row->body, 179 'news_id' => $news_id, 180 'subject' => $row->subject, 181 'title' => $title, 182 ]); 183 } 184 185 /** 186 * @param ServerRequestInterface $request 187 * 188 * @return ResponseInterface 189 */ 190 public function postEditJournalAction(ServerRequestInterface $request): ResponseInterface 191 { 192 $tree = $request->getAttribute('tree'); 193 assert($tree instanceof Tree, new InvalidArgumentException()); 194 195 if (!Auth::check()) { 196 throw new AccessDeniedHttpException(); 197 } 198 199 $news_id = $request->getQueryParams()['news_id'] ?? ''; 200 $subject = $request->getParsedBody()['subject']; 201 $body = $request->getParsedBody()['body']; 202 203 $subject = $this->html_service->sanitize($subject); 204 $body = $this->html_service->sanitize($body); 205 206 if ($news_id !== '') { 207 DB::table('news') 208 ->where('news_id', '=', $news_id) 209 ->where('user_id', '=', Auth::id()) 210 ->update([ 211 'body' => $body, 212 'subject' => $subject, 213 ]); 214 } else { 215 DB::table('news')->insert([ 216 'body' => $body, 217 'subject' => $subject, 218 'user_id' => Auth::id(), 219 ]); 220 } 221 222 $url = route('user-page', ['tree' => $tree->name()]); 223 224 return redirect($url); 225 } 226 227 /** 228 * @param ServerRequestInterface $request 229 * 230 * @return ResponseInterface 231 */ 232 public function postDeleteJournalAction(ServerRequestInterface $request): ResponseInterface 233 { 234 $tree = $request->getAttribute('tree'); 235 $news_id = $request->getQueryParams()['news_id']; 236 237 DB::table('news') 238 ->where('news_id', '=', $news_id) 239 ->where('user_id', '=', Auth::id()) 240 ->delete(); 241 242 $url = route('user-page', ['tree' => $tree->name()]); 243 244 return redirect($url); 245 } 246} 247