public function before() { parent::before(); $this->post = ORM::factory('Forum_Post', $this->request->param('id')); if (!$this->post->loaded()) { throw HTTP_Exception::factory('404', 'Forum post not found'); } $this->topic = $this->post->topic; $this->category = $this->topic->category; }
/** * Save topic and handle stats updated. * * @return boolean */ public function save_post() { if ($this->unsaved_post) { $this->unsaved_post->is_valid(); $area = $this->area(); if (!$this->id) { // New topic $this->save(); $this->unsaved_post->forum_topic_id = $this->id; $this->unsaved_post->save(); $this->created = $this->unsaved_post->created; $this->first_post_id = $this->unsaved_post->id; $area->topic_count++; } else { // Old topic $this->unsaved_post->save(); } // Topic stats $this->last_post_id = $this->unsaved_post->id; $this->last_poster = $this->unsaved_post->author_name; $this->last_posted = $this->unsaved_post->created; $this->post_count++; $this->save(); // Area stats $area->last_topic_id = $this->id; $area->post_count++; $area->save(); return true; } return false; }
/** * Handle forum quotations * * @param BBCode $bbcode * @param string $action * @param string $name * @param string $default * @param array $params * @param string $content * @return string */ public function bbcode_quote($bbcode, $action, $name, $default, $params, $content) { // Pass all to 2nd phase if ($action == BBCODE_CHECK) { return true; } // Parse parameters foreach ($params['_params'] as $param) { switch ($param['key']) { // Parent post id case 'post': $post = Model_Forum_Post::factory((int) $param['value']); break; // Parent post author // Parent post author case 'author': $author_name = $param['value']; $author = Model_User::find_user_light($author_name); break; } } // Add parent post if (isset($post) && $post->loaded()) { $quote = '<blockquote cite="' . URL::site(Route::model($post->topic())) . '?post=' . $post->id . '#post-' . $post->id . '">'; // Override author $author = Model_User::find_user_light($post->author_id); } else { $quote = '<blockquote>'; } $quote .= '<p>' . trim($content) . '</p>'; // Post author if (isset($author) && $author) { $quote .= '<cite>' . __('-- :author', array(':author' => HTML::user($author))) . '</cite>'; } else { if (isset($author_name)) { $quote .= '<cite>' . __('-- :author', array(':author' => HTML::chars($author_name))) . '</cite>'; } } $quote .= '</blockquote>'; return $quote; }
/** * Edit forum topic * * @param integer $area_id * @param integer $topic_id * * @throws Model_Exception invalid area, invalid topic * @throws InvalidArgumentException missing area and topic */ protected function _edit_topic($area_id = null, $topic_id = null) { $this->history = false; $this->view = new View_Page(); if ($area_id && !$topic_id) { // Start new topic $mode = View_Forum_PostEdit::NEW_TOPIC; /** @var Model_Forum_Private_Area|Model_Forum_Area $area */ $area = $this->private ? Model_Forum_Private_Area::factory($area_id) : Model_Forum_Area::factory($area_id); if (!$area->loaded()) { throw new Model_Exception($area, $area_id); } Permission::required($area, Model_Forum_Area::PERMISSION_POST, self::$user); $this->view->title = HTML::chars($area->name); if ($this->private) { $topic = new Model_Forum_Private_Topic(); $post = new Model_Forum_Private_Post(); $cancel = Route::url('forum_area', array('id' => 'private', 'action' => '')); $recipients = array(); } else { $topic = new Model_Forum_Topic(); $post = new Model_Forum_Post(); $cancel = Route::model($area); } } else { if ($topic_id) { // Edit old topic $mode = View_Forum_PostEdit::EDIT_TOPIC; /** @var Model_Forum_Private_Topic|Model_Forum_Topic $topic */ $topic = $this->private ? Model_Forum_Private_Topic::factory($topic_id) : Model_Forum_Topic::factory($topic_id); if (!$topic->loaded()) { throw new Model_Exception($topic, $topic_id); } Permission::required($topic, Model_Forum_Topic::PERMISSION_UPDATE, self::$user); // Build recipients list if ($this->private) { $recipients = $topic->find_recipient_names(); } $this->view->title_html = Forum::topic($topic); $cancel = Route::model($topic); // Set actions if (Permission::has($topic, Model_Forum_Topic::PERMISSION_DELETE, self::$user)) { $this->view->actions[] = array('link' => Route::model($topic, 'delete') . '?' . Security::csrf_query(), 'text' => '<i class="icon-trash icon-white"></i> ' . __('Delete topic'), 'class' => 'btn btn-danger topic-delete'); } } else { throw new InvalidArgumentException('Topic and area missing'); } } $errors = array(); if ($_POST && Security::csrf_valid()) { // Get recipients if ($this->private) { $post_recipients = array(); foreach (explode(',', Arr::get_once($_POST, 'recipients')) as $recipient) { if ($user = Model_User::find_user_light(trim($recipient))) { $post_recipients[$user['id']] = $user['username']; } } // Make sure author is included $post_recipients[self::$user->id] = self::$user->username; } if (isset($post)) { // New topic $post->post = $_POST['post']; $post->forum_area_id = $area->id; $post->author_id = self::$user->id; $post->author_name = self::$user->username; $post->author_ip = Request::$client_ip; $post->author_host = Request::host_name(); $post->created = time(); try { $post->is_valid(); } catch (Validation_Exception $e) { $errors += $e->array->errors('validate'); } $topic->author_id = self::$user->id; $topic->author_name = self::$user->username; $topic->name = $_POST['name']; $topic->forum_area_id = $area->id; $topic->created = time(); try { $topic->is_valid(); } catch (Validation_Exception $e) { $errors += $e->array->errors('validate'); } // If no errors found, save models if (empty($errors)) { $topic->save(); // Recipients if ($this->private) { $topic->set_recipients($post_recipients); } // Post $post->forum_topic_id = $topic->id; $post->save(); // Topic $topic->first_post_id = $topic->last_post_id = $post->id; $topic->last_poster = self::$user->username; $topic->last_posted = time(); $topic->post_count = 1; $topic->save(); // Area, only public forums if (!$this->private) { $area->last_topic_id = $topic->id; $area->post_count++; $area->topic_count++; $area->save(); } // User self::$user->post_count++; self::$user->save(); // News feed if (!$this->private) { NewsfeedItem_Forum::topic(self::$user, $topic); } $this->request->redirect(Route::model($topic)); } isset($post_recipients) and $recipients = $post_recipients; } else { // Old topic $topic->set_fields(Arr::intersect($_POST, array('name', 'status', 'sticky'))); try { $topic->save(); // Recipients if ($this->private) { $topic->set_recipients($post_recipients); } $this->request->redirect(Route::model($topic)); } catch (Validation_Exception $e) { $errors = $e->array->errors('validate'); } } } $form['errors'] = $errors; $section = $this->section_post_edit($mode, isset($post) ? $post : null); $section->forum_topic = $topic; $section->errors = $errors; $section->cancel = $cancel; $section->recipients = isset($recipients) ? implode(', ', $recipients) : null; $this->view->add(View_Page::COLUMN_MAIN, $section); }
/** * Refresh area data. * Potentially heavy function, use with caution! * * @param boolean $save */ public function refresh($save = true) { if (!$this->loaded()) { return false; } // Get table names if ($this instanceof Anqh_Model_Forum_Area) { $topic_table = Model_Forum_Topic::factory()->get_table_name(); $post_table = Model_Forum_Post::factory()->get_table_name(); } else { $topic_table = Model_Forum_Private_Topic::factory()->get_table_name(); $post_table = Model_Forum_Private_Post::factory()->get_table_name(); } // Stats $this->topic_count = (int) DB::select(array(DB::expr('COUNT(id)'), 'topics'))->from($topic_table)->where('forum_area_id', '=', $this->id)->execute($this->_db)->get('topics'); $this->post_count = (int) DB::select(array(DB::expr('COUNT(id)'), 'posts'))->from($post_table)->where('forum_area_id', '=', $this->id)->execute($this->_db)->get('posts'); // Last topic $this->last_topic_id = (int) DB::select(array(DB::expr('MAX(id)'), 'topic_id'))->from($topic_table)->where('forum_area_id', '=', $this->id)->execute($this->_db)->get('topic_id'); if ($save) { $this->save(); } return true; }
/** * Find topic posts by page. * * @param integer $offset * @param integer $limit * @return Model_Forum_Post[] */ public function posts($offset, $limit) { $post = Model_Forum_Post::factory(); $query = DB::select_array($post->fields())->where('forum_topic_id', '=', $this->id)->order_by('created', 'ASC'); if ($offset || $limit) { return $post->load($query->offset($offset), $limit); } else { return $post->load($query, null); } }
/** * Update the post count for users with posts in the topic. * * @return ORM */ public function delete() { $this->category->topics_count--; $this->category->save(); /* @var $users Model_User[] */ $users = array(); // Find all users. foreach ($this->posts->find_all() as $post) { $users[$post->user->id] = $post->user; } // Delete the topic, posts gets deleted by sql constraints. $post = parent::delete(); // Update the forum.posts property. foreach ($users as $user) { $user->set_property('forum.posts', Model_Forum_Post::get_user_post_count($user->id)); $user->save(); } return $post; }
/** * Render view. * * @return string */ public function content() { ob_start(); ?> <div class="pull-left"> <?php if ($this->author) { ?> <?php echo HTML::avatar($this->author->avatar, $this->author->username); ?> <p> <small><?php echo __('Posts: :posts', array(':posts' => '<var>' . Num::format($this->author->post_count, 0) . '</var>')); ?> </small> </p> <?php } else { ?> <?php echo HTML::avatar(false); ?> <?php } ?> </div> <div class="arrow"></div> <div class="media-body"> <header<?php echo $this->forum_post->id == $this->forum_topic->last_post_id ? ' id="last"' : ''; ?> > <small class="ago"> <?php echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic))) . '#post-' . $this->forum_post->id, '#' . $this->nth, array('title' => __('Permalink'))); ?> • <?php if (Permission::has($this->forum_post, Model_Forum_Post::PERMISSION_UPDATE, self::$_user)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'edit')), __('Edit'), array('class' => 'post-edit')) . ' • '; } ?> <?php if (Permission::has($this->forum_post, Model_Forum_Post::PERMISSION_DELETE, self::$_user)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'delete')) . '?token=' . Security::csrf(), __('Delete'), array('class' => 'post-delete')) . ' • '; } ?> <?php if (Permission::has($this->forum_topic, Model_Forum_Topic::PERMISSION_POST, self::$_user)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'quote')), __('Reply'), array('class' => 'post-quote')) . ' • '; } ?> <?php echo HTML::time(Date::short_span($this->forum_post->created, true, true), $this->forum_post->created); ?> </small> <?php if ($this->author) { echo HTML::user($this->author->light_array()); if ($this->author->title) { echo ' <small>“' . HTML::chars($this->author->title) . '”</small>'; } } else { echo $this->forum_post->author_name; echo ' <small>“' . __('Guest') . '”</small>'; } ?> </header> <?php if ($this->forum_post->parent_id) { echo __('Replying to :parent', array(':parent' => HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('topic_id' => Route::model_id($this->forum_topic), 'id' => $this->forum_post->parent_id)) . '#post-' . $this->forum_post->parent_id, HTML::chars($this->forum_post->parent()->topic()->name)))); } ?> <?php echo BB::factory($this->forum_post->post)->render(); ?> <footer> <?php echo $this->author && $this->author->signature ? BB::factory("\n--\n" . $this->author->signature)->render() : ''; ?> <?php if ($this->forum_post->modify_count > 0) { echo '<br /><br />' . __('Edited :ago', array(':ago' => HTML::time(Date::fuzzy_span($this->forum_post->modified), $this->forum_post->modified))); } ?> </footer> </div> <?php return ob_get_clean(); }
/** * Render view. * * @return string */ public function content() { $bbcode = BB::factory(); ob_start(); if ($this->my) { $panel_class = 'panel-success'; } elseif ($this->owner) { $panel_class = 'panel-info'; } else { $panel_class = 'panel-default'; } ?> <div class="pull-left"> <?php if ($this->author) { ?> <?php echo HTML::avatar($this->author->avatar_url, $this->author->username); ?> <p> <small><?php echo __('Posts: :posts', array(':posts' => '<var>' . Num::format($this->author->post_count, 0) . '</var>')); ?> </small> </p> <?php } else { ?> <?php echo HTML::avatar(false); ?> <?php } ?> </div> <div class="media-body panel <?php echo $panel_class; ?> "> <header class="panel-heading"<?php echo $this->forum_post->id == $this->forum_topic->last_post_id ? ' id="last"' : ''; ?> > <small class="pull-right"> <?php echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic))) . '#post-' . $this->forum_post->id, '#' . $this->nth, array('title' => __('Permalink'))); ?> • <?php if (Permission::has($this->forum_post, Model_Forum_Post::PERMISSION_UPDATE)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'edit')), __('Edit'), array('class' => 'post-edit')); } ?> <?php if (Permission::has($this->forum_post, Model_Forum_Post::PERMISSION_DELETE)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'delete')) . '?token=' . Security::csrf(), __('Delete'), array('class' => 'post-delete')); } ?> <?php if (Permission::has($this->forum_topic, Model_Forum_Topic::PERMISSION_POST)) { echo HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('id' => Route::model_id($this->forum_post), 'topic_id' => Route::model_id($this->forum_topic), 'action' => 'quote')), __('Reply'), array('class' => 'post-quote')); } ?> • <?php echo HTML::time(Date::short_span($this->forum_post->created, true, true), $this->forum_post->created); ?> <?php if ($this->forum_post->modify_count > 0) { ?> • <span title="<?php echo __($this->forum_post->modify_count == 1 ? ':edits edit, :ago' : ':edits edits, last :ago', array(':edits' => $this->forum_post->modify_count, ':ago' => Date::fuzzy_span($this->forum_post->modified))); ?> "><?php echo __('Edited'); ?> </span> <?php } ?> </small> <?php if ($this->author) { echo HTML::user($this->author->light_array()); if ($this->author->title) { echo ' <small>' . HTML::chars($this->author->title) . '</small>'; } } else { echo $this->forum_post->author_name; echo ' <small>' . __('Guest') . '</small>'; } ?> </header> <div class="panel-body"> <?php if ($this->forum_post->parent_id) { echo '<p class="text-muted">' . __('Replying to :parent', array(':parent' => HTML::anchor(Route::url($this->private ? 'forum_private_post' : 'forum_post', array('topic_id' => Route::model_id($this->forum_topic), 'id' => $this->forum_post->parent_id)) . '#post-' . $this->forum_post->parent_id, HTML::chars($this->forum_post->parent()->topic()->name)))) . ':</p>'; } ?> <?php echo $bbcode->render($this->forum_post->post); ?> <?php if ($this->forum_post->attachment) { $attachment = 'images/liitteet/' . $this->forum_post->attachment; if (file_exists($attachment)) { echo HTML::image($attachment); } } ?> </div> <?php if ($this->author && $this->author->signature) { ?> <footer class="panel-body"> <?php echo $this->author && $this->author->signature ? $bbcode->render("\n--\n" . $this->author->signature, true) : ''; ?> </footer> <?php } ?> </div> <?php return ob_get_clean(); }
/** * Edit forum post * * @param integer $topic_id When replying to a topic * @param integer $post_id When editing a post * @param integer $quote_id When quoting a post * * @throws Model_Exception missing topic, missing post */ protected function _edit_post($topic_id, $post_id = null, $quote_id = null) { $this->history = false; // Topic is always loaded, avoid haxing attempts to edit posts from wrong topics $topic = $this->private ? Model_Forum_Private_Topic::factory($topic_id) : Model_Forum_Topic::factory($topic_id); if (!$topic->loaded()) { throw new Model_Exception($topic, $topic_id); } Permission::required($topic, Model_Forum_Topic::PERMISSION_POST); if ($post_id) { // Editing a post $post = $this->private ? Model_Forum_Private_Post::factory($post_id) : Model_Forum_Post::factory($post_id); if (!$post->loaded() || $post->forum_topic_id != $topic->id) { throw new Model_Exception($post, $post_id); } Permission::required($post, Model_Forum_Post::PERMISSION_UPDATE); } else { // New reply $post = $this->private ? Model_Forum_Private_Post::factory() : Model_Forum_Post::factory(); } // Quoting a post if ($quote_id) { $quote = $this->private ? Model_Forum_Private_Post::factory() : Model_Forum_Post::factory($quote_id); if (!$quote->loaded() || $quote->forum_topic_id != $topic->id) { throw new Model_Exception($quote, $quote_id); } Permission::required($quote, Model_Forum_Post::PERMISSION_READ); if (!$post->loaded()) { $post->post = '[quote author="' . $quote->author_name . '" post="' . $quote->id . '"]' . $quote->post . "[/quote]\n\n"; } $post->parent_id = $quote_id; } // Handle post $errors = array(); if ($_POST && Security::csrf_valid()) { $post->post = Arr::get($_POST, 'post'); $post->author_ip = Request::$client_ip; $post->author_host = Request::host_name(); if (!$post->loaded()) { // New post $post->forum_topic_id = $topic->id; $post->forum_area_id = $topic->forum_area_id; $post->author_id = Visitor::$user->id; $post->author_name = Visitor::$user->username; $post->created = time(); $increase = true; } else { // Old post $post->modify_count++; $post->modified = time(); $increase = false; } // Preview if (isset($_POST['preview'])) { if ($this->ajax) { $this->response->body($this->section_post($topic, $post)); } return; } // Save try { $post->save(); if ($increase) { // Quote, only for public topics if (!$this->private && $quote_id && $quote->author_id) { $quoted = $quote->author_id; $quote = new Model_Forum_Quote(); $quote->user_id = $quoted; $quote->author_id = Visitor::$user->id; $quote->forum_topic_id = $topic->id; $quote->forum_post_id = $post->id; $quote->created = time(); $quote->save(); } // Notify recipients if ($this->private) { $topic->notify_recipients(Visitor::$user); } // Topic $topic->post_count++; $topic->last_post_id = $post->id; $topic->last_poster = $post->author_name; // If current topic is set to sink, don't update last posted date if ($topic->status != Model_Forum_Topic::STATUS_SINK) { $topic->last_posted = $post->created; } $topic->save(); // Area, only for public topics if (!$this->private) { $area = $topic->area(); $area->post_count++; $area->last_topic_id = $topic->id; $area->save(); } // User Visitor::$user->post_count++; Visitor::$user->save(); // News feed if (!$this->private) { NewsfeedItem_Forum::reply(Visitor::$user, $post); } } if ($this->ajax) { $post_route = Route::url($this->private ? 'forum_private_post' : 'forum_post', array('topic_id' => Route::model_id($topic), 'id' => $post->id)); $post_response = Request::factory($post_route)->execute(); $this->response->body($post_response->body()); return; } $this->request->redirect(Route::model($topic, '?page=last#last')); } catch (Validation_Exception $e) { $errors = $e->array->errors('validate'); } } // Common attributes if ($quote_id) { $mode = View_Forum_PostEdit::QUOTE; } else { if ($post_id) { $mode = View_Forum_PostEdit::EDIT_POST; } else { $mode = View_Forum_PostEdit::REPLY; } } $section = $this->section_post_edit($mode, $post); $section->forum_topic = $topic; $section->errors = $errors; $section->cancel = $this->ajax ? Route::url($this->private ? 'forum_private_post' : 'forum_post', array('topic_id' => Route::model_id($topic), 'id' => $quote_id ? $quote_id : $post->id)) : Request::back(Route::model($topic), true); if ($this->ajax) { $this->response->body($mode == View_Forum_PostEdit::EDIT_POST ? $section->content() : $section); return; } // Build page $this->view = new View_Page(); $this->view->title = $topic->name; $this->view->title_html = Forum::topic($topic); $this->view->add(View_Page::COLUMN_CENTER, $section); }