<?php
/**
  * Ahead WebSoft Technologies Pvt Ltd.
  * @copyright  Copyright 2006-2026 Ahead WebSoft Technologies Pvt Ltd.
  * @license    https://www.socialengine.com/policies
*/
class Forum_TopicController extends Core_Controller_Action_Standard
{
  public function init()
  {
    if( 0 !== ($topic_id = (int) $this->_getParam('topic_id')) &&
        null !== ($topic = Engine_Api::_()->getItem('forum_topic', $topic_id)) &&
        $topic instanceof Forum_Model_Topic ) {
      Engine_Api::_()->core()->setSubject($topic);
    }
  }

  public function deleteAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();
    
    if(!Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.delete'))
      return $this->_forward('requireauth', 'error', 'core');
    
    $this->view->form = $form = new Forum_Form_Topic_Delete();

    if( !$this->getRequest()->isPost() ) {
      return;
    }

    if( !$form->isValid($this->getRequest()->getPost()) ) {
      return;
    }

    // Process
    $table = Engine_Api::_()->getItemTable('forum_topic');
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      $topic->delete();

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    return $this->_forward('success', 'utility', 'core', array(
      'messages' => array(Zend_Registry::get('Zend_Translate')->_('Topic deleted.')),
      'layout' => 'default-simple',
      'parentRedirect' => $forum->getHref(),
    ));
  }

  public function editAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();
    if( !$this->_helper->requireAuth()->setAuthParams($forum, null, 'topic.edit')->isValid() ) {
      return;
    }

    $this->view->form = $form = new Forum_Form_Topic_Edit();

    if( !$this->getRequest()->isPost() )
    {
      return;
    }

    if( !$form->isValid($this->getRequest()->getPost()) )
    {
      return;
    }

    // Process
    $table = Engine_Api::_()->getItemTable('forum_topic');
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      $values = $form->getValues();

      $topic->setFromArray($values);
      $topic->save();
      
      //Save editor images
      Engine_Api::_()->core()->saveTinyMceImages($values['body'], $topic);
      
      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }
  }

  public function viewAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }

    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $viewer_id = $viewer->getIdentity();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum =  $forum = $topic->getParent();

    if( !Engine_Api::_()->core()->isViewPermission($forum->getIdentity()) ) {
      return $this->_forward('notfound', 'error', 'core');
    }
    
    if( !$topic || !$topic->getIdentity() || ((!$topic->approved) && !$topic->isOwner($viewer)) ) {
      if(!empty($viewer->getIdentity()) && $viewer->isAdmin()) {
      } else
        return $this->_helper->requireSubject->forward();
    }

    // Settings
    $settings = Engine_Api::_()->getApi('settings', 'core');
    $this->view->post_id = $post_id = (int) $this->_getParam('post_id');
    $this->view->decode_bbcode = $settings->getSetting('forum_bbcode');
    
    // Views
    if( !$viewer || !$viewer->getIdentity() || $viewer->getIdentity() != $topic->user_id ) {
      $topic->view_count = new Zend_Db_Expr('view_count + 1');
      $topic->save();
    }

    // Check watching
    $isWatching = null;
    if( $viewer->getIdentity() ) {
      $topicWatchesTable = Engine_Api::_()->getDbtable('topicWatches', 'forum');
      $isWatching = $topicWatchesTable
        ->select()
        ->from($topicWatchesTable->info('name'), 'watch')
        ->where('resource_id = ?', $forum->getIdentity())
        ->where('topic_id = ?', $topic->getIdentity())
        ->where('user_id = ?', $viewer->getIdentity())
        ->limit(1)
        ->query()
        ->fetchColumn(0)
        ;
      if( false === $isWatching ) {
        $isWatching = null;
      } else {
        $isWatching = (bool) $isWatching;
      }
    }
    $this->view->isWatching = $isWatching;
    
    // Auth for topic
    $canPost = false;
    $canEdit = false;
    $canDelete = false;
    if( !$topic->closed && Engine_Api::_()->authorization()->isAllowed($forum, null, 'post.create') ) {
      $canPost = true;
    }
    if($viewer->getIdentity() && $topic->user_id == $viewer->getIdentity()) {
      $canEdit = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit');
      $canDelete = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.delete');
    } else if($viewer->getIdentity() && $topic->user_id != $viewer->getIdentity() && $viewer->isSuperAdmin()) {
      $canEdit = true;
      $canDelete = true;
    } else if($viewer->getIdentity() && $topic->user_id != $viewer->getIdentity() && $viewer->isAdmin()) {
      $canEdit = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit');
      $canDelete = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.delete');
    }
    $this->view->canPost = $canPost;
    $this->view->canEdit = $canEdit;
    $this->view->canDelete = $canDelete;


    // Auth for posts
    $canEdit_Post = false;
    $canDelete_Post = false;
    if($viewer->getIdentity()){
      $canEdit_Post = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'post.edit');
      $canDelete_Post = Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'post.delete');
    }
    $this->view->canEdit_Post = $canEdit_Post;
    $this->view->canDelete_Post = $canDelete_Post;



    // Make form
    if( $canPost ) {
      $this->view->form = $form = new Forum_Form_Post_Quick();
      $form->setAction($topic->getHref(array('action' => 'post-create')));
      $form->populate(array(
        'topic_id' => $topic->getIdentity(),
        'ref' => $topic->getHref(),
        'watch' => ( false === $isWatching ? '0' : '1' ),
      ));
    }

    // Keep track of topic user views to show them which ones have new posts
    if( $viewer->getIdentity() ) {
      $topic->registerView($viewer);
    }
    
    $table = Engine_Api::_()->getItemTable('forum_post');
    $tableName = $table->info('name');
    $select = $topic->getChildrenSelect('forum_post', array('order'=>'post_id ASC'));
    
    if(!$viewer->isAdmin())
      $select->where("CASE WHEN " .$tableName .".user_id = '".$viewer_id."' THEN true ELSE ".$tableName.".approved = 1 END ");
      
    $this->view->paginator = $paginator = Zend_Paginator::factory($select);
    $paginator->setItemCountPerPage($settings->getSetting('forum_topic_pagelength'));

    // set up variables for pages
    $page_param = (int) $this->_getParam('page');
    $post = Engine_Api::_()->getItem('forum_post', $post_id);
            
    // if there is a post_id
    if( $post_id && $post && !$page_param )
    {
      $icpp = $paginator->getItemCountPerPage();
      $post_page = ceil(($post->getPostIndex() + 1) / $icpp);

      $paginator->setCurrentPageNumber($post_page);
    }
    // Use specified page
    else if( $page_param )
    {      
      $paginator->setCurrentPageNumber($page_param);
    }
 }


  public function stickyAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();
    
    if(!Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit'))
      return $this->_forward('requireauth', 'error', 'core');

    $table = $topic->getTable();
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      $topic = Engine_Api::_()->core()->getSubject();
      $topic->sticky = ( null === $this->_getParam('sticky') ? !$topic->sticky : (bool) $this->_getParam('sticky') );
      $topic->save();

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    $this->_redirectCustom($topic);
  }

  public function closeAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();

    if(!Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit'))
      return $this->_forward('requireauth', 'error', 'core');
    
    $table = $topic->getTable();
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      $topic = Engine_Api::_()->core()->getSubject();
      $topic->closed = ( null === $this->_getParam('closed') ? !$topic->closed : (bool) $this->_getParam('closed') );
      $topic->save();

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    $this->_redirectCustom($topic);
  }

  public function renameAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();

    if(!Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit'))
      return $this->_forward('requireauth', 'error', 'core');
    
    $this->view->form = $form = new Forum_Form_Topic_Rename();

    if( !$this->getRequest()->isPost() )
    {
      $form->title->setValue(htmlspecialchars_decode(($topic->title)));
      return;
    }

    if( !$form->isValid($this->getRequest()->getPost()) )
    {
      return;
    }

    $table = $topic->getTable();
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      $title = $form->getValue('title');
      $topic = Engine_Api::_()->core()->getSubject();
      $topic->title = $title;
      $topic->save();

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    return $this->_forward('success', 'utility', 'core', array(
      'messages' => array(Zend_Registry::get('Zend_Translate')->_('Topic renamed.')),
      'layout' => 'default-simple',
      'parentRefresh' => true,
    ));
  }

  public function moveAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();

    if(!Engine_Api::_()->authorization()->isAllowed('forum', $viewer->level_id, 'topic.edit'))
      return $this->_forward('requireauth', 'error', 'core');

    $this->view->form = $form = new Forum_Form_Topic_Move();

    // Populate with options
    $multiOptions = array();
    $forums = Engine_Api::_()->getDbTable('forums', 'forum')->getForumsAssoc();
    foreach( $forums as $forum ) {
      $multiOptions[$forum->getIdentity()] = $this->view->translate($forum->getTitle());
    }
    $form->getElement('forum_id')->setMultiOptions($multiOptions);

    if( !$this->getRequest()->isPost() ) {
      return;
    }

    if( !$form->isValid($this->getRequest()->getPost()) ) {
      return;
    }

    $values = $form->getValues();

    $table = $topic->getTable();
    $db = $table->getAdapter();
    $db->beginTransaction();

    try
    {
      // Update topic
      $topic->forum_id = $values['forum_id'];
      $topic->save();

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    return $this->_forward('success', 'utility', 'core', array(
      'messages' => array(Zend_Registry::get('Zend_Translate')->_('Topic moved.')),
      'layout' => 'default-simple',
      //'parentRefresh' => true,
      'parentRedirect' => $topic->getHref(),
    ));
  }
  
  public function postCreateAction()
  {
    if( !$this->_helper->requireUser()->isValid() ) {
      return;
    }
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();
    if( !$this->_helper->requireAuth()->setAuthParams($forum, null, 'post.create')->isValid() ) {
      return;
    }
    if( $topic->closed ) {
      return;
    }
    
    $this->view->form = $form = new Forum_Form_Post_Create();

    // Remove the file element if there is no file being posted
    if( $this->getRequest()->isPost() && empty($_FILES['photo']) ) {
      $form->removeElement('photo');
    }

    $allowHtml = (bool) Engine_Api::_()->getApi('settings', 'core')->getSetting('forum_html', 0);
    $allowBbcode = (bool) Engine_Api::_()->getApi('settings', 'core')->getSetting('forum_bbcode', 0);

    $quote_id = $this->getRequest()->getParam('quote_id');
    if( !empty($quote_id) ) {
      $quote = Engine_Api::_()->getItem('forum_post', $quote_id);
      if($quote->user_id == 0) {
          $owner_name = Zend_Registry::get('Zend_Translate')->_('Deleted Member');
      } else {
          $owner_name = $quote->getOwner()->__toString();
      }
      if ( !$allowHtml && !$allowBbcode ) {
        $form->body->setValue( strip_tags($this->view->translate('%1$s said:', $owner_name)) . " ''" . strip_tags($quote->body) . "''\n-------------\n" );
      } elseif( $allowHtml ) {
        $form->body->setValue("<blockquote><strong>" . $this->view->translate('%1$s said:', $owner_name) . "</strong><br />" . $quote->body . "</blockquote><br />");
      } else {
        $form->body->setValue("[quote][b]" . strip_tags($this->view->translate('%1$s said:', $owner_name)) . "[/b]\r\n" . htmlspecialchars_decode($quote->body, ENT_COMPAT) . "[/quote]\r\n");
      }
    }

    if( !$this->getRequest()->isPost() ) {
      return;
    }

    if( !$form->isValid($this->getRequest()->getPost()) ) {
      return;
    }
    $itemFlood = Engine_Api::_()->getDbtable('permissions', 'authorization')->getAllowed('forum', $this->view->viewer()->level_id, 'post.flood');
    if(!empty($itemFlood[0])){
      //get last activity
      $tableFlood = Engine_Api::_()->getDbTable("posts",'forum');
      $select = $tableFlood->select()->where("user_id = ?",$this->view->viewer()->getIdentity())->order("creation_date DESC");
      if($itemFlood[1] == "minute"){
          $select->where("creation_date >= DATE_SUB(NOW(),INTERVAL 1 MINUTE)");
      }else if($itemFlood[1] == "day"){
          $select->where("creation_date >= DATE_SUB(NOW(),INTERVAL 1 DAY)");
      }else{
          $select->where("creation_date >= DATE_SUB(NOW(),INTERVAL 1 HOUR)");
      }
      $floodItem = $tableFlood->fetchAll($select);
      if(engine_count($floodItem) && $itemFlood[0] <= engine_count($floodItem)){
          $message = Engine_Api::_()->core()->floodCheckMessage($itemFlood,$this->view);
          $form->addError($message);
          return;
      }
    }
    // Process
    $values = $form->getValues();
    $values['body'] = Engine_Text_BBCode::prepare($values['body']);
    $values['user_id'] = $viewer->getIdentity();
    $values['topic_id'] = $topic->getIdentity();
    $values['forum_id'] = $forum->getIdentity();

    $topicTable = Engine_Api::_()->getDbtable('topics', 'forum');
    $topicWatchesTable = Engine_Api::_()->getDbtable('topicWatches', 'forum');
    $postTable = Engine_Api::_()->getDbtable('posts', 'forum');
    $userTable = Engine_Api::_()->getItemTable('user');
    $notifyApi = Engine_Api::_()->getDbtable('notifications', 'activity');
    $activityApi = Engine_Api::_()->getDbtable('actions', 'activity');

    $viewer = Engine_Api::_()->user()->getViewer();
    $topicOwner = $topic->getOwner();
    $isOwnTopic = $viewer->isSelf($topicOwner);

    $watch = (bool) $values['watch'];
    $isWatching = $topicWatchesTable
      ->select()
      ->from($topicWatchesTable->info('name'), 'watch')
      ->where('resource_id = ?', $forum->getIdentity())
      ->where('topic_id = ?', $topic->getIdentity())
      ->where('user_id = ?', $viewer->getIdentity())
      ->limit(1)
      ->query()
      ->fetchColumn(0);
    
    $db = $postTable->getAdapter();
    $db->beginTransaction();

    try {
      //approve setting work
      $values['approved'] = Engine_Api::_()->authorization()->getAdapter('levels')->getAllowed('forum', $viewer, 'post.approve');
      if(!empty($values['approved']))
        $values['resubmit'] = 1;
      
      $post = $postTable->createRow();
      $post->setFromArray($values);
      $post->save();
      
      //Save editor images
      Engine_Api::_()->core()->saveTinyMceImages($values['body'], $post);
      
      if( !empty($values['photo']) ) {
        try {
          $post->setPhoto($form->photo);
        } catch( Engine_Image_Adapter_Exception $e ) {}
      }

      // Watch
      if( false === $isWatching ) {
        $topicWatchesTable->insert(array(
          'resource_id' => $forum->getIdentity(),
          'topic_id' => $topic->getIdentity(),
          'user_id' => $viewer->getIdentity(),
          'watch' => (bool) $watch,
        ));
      } else if( $watch != $isWatching ) {
        $topicWatchesTable->update(array(
          'watch' => (bool) $watch,
        ), array(
          'resource_id = ?' => $forum->getIdentity(),
          'topic_id = ?' => $topic->getIdentity(),
          'user_id = ?' => $viewer->getIdentity(),
        ));
      }

      // Activity
      $action = $activityApi->addActivity($viewer, $topic, 'forum_topic_reply');
      if( $action ) {
        $action->attach($post, Activity_Model_Action::ATTACH_DESCRIPTION);
      }
      
      //Start Send Approval Request to Admin
      Engine_Api::_()->core()->contentApprove($post, 'forum post');
      
      if ($post->approved) {
        // Notifications
        $notifyUserIds = $topicWatchesTable->select()
          ->from($topicWatchesTable->info('name'), 'user_id')
          ->where('resource_id = ?', $forum->getIdentity())
          ->where('topic_id = ?', $topic->getIdentity())
          ->where('watch = ?', 1)
          ->query()
          ->fetchAll(Zend_Db::FETCH_COLUMN);

        foreach( $userTable->find($notifyUserIds) as $notifyUser ) {
          // Don't notify self
          if( $notifyUser->isSelf($viewer) ) {
            continue;
          }
          if( $notifyUser->isSelf($topicOwner) ) {
            $type = 'forum_topic_response';
          } else {
            if($topic->getUserPosts($notifyUser) > 0){
              $type = 'forum_topic_reply';
            } else {
              $type = 'forum_topic_subscribed';
            }
          }
          $notifyApi->addNotification($notifyUser, $viewer, $topic, $type, array(
            'message' => $this->view->BBCode($post->body),
            'postGuid' => $post->getGuid(),
          ));
        }
      }

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }
    
    return $this->_redirectCustom($post);
  }

  public function watchAction()
  {
    if( !$this->_helper->requireSubject('forum_topic')->isValid() ) {
      return;
    }
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->topic = $topic = Engine_Api::_()->core()->getSubject('forum_topic');
    $this->view->forum = $forum = $topic->getParent();
    if( !$this->_helper->requireAuth()->setAuthParams($forum, $viewer, 'view')->isValid() ) {
      return;
    }

    $watch = $this->_getParam('watch', true);

    $topicWatchesTable = Engine_Api::_()->getDbtable('topicWatches', 'forum');
    $db = $topicWatchesTable->getAdapter();
    $db->beginTransaction();

    try
    {
      $isWatching = $topicWatchesTable
        ->select()
        ->from($topicWatchesTable->info('name'), 'watch')
        ->where('resource_id = ?', $forum->getIdentity())
        ->where('topic_id = ?', $topic->getIdentity())
        ->where('user_id = ?', $viewer->getIdentity())
        ->limit(1)
        ->query()
        ->fetchColumn(0)
        ;

      if( false === $isWatching ) {
        $topicWatchesTable->insert(array(
          'resource_id' => $forum->getIdentity(),
          'topic_id' => $topic->getIdentity(),
          'user_id' => $viewer->getIdentity(),
          'watch' => (bool) $watch,
        ));
      } else if( $watch != $isWatching ) {
        $topicWatchesTable->update(array(
          'watch' => (bool) $watch,
        ), array(
          'resource_id = ?' => $forum->getIdentity(),
          'topic_id = ?' => $topic->getIdentity(),
          'user_id = ?' => $viewer->getIdentity(),
        ));
      }

      $db->commit();
    }

    catch( Exception $e )
    {
      $db->rollBack();
      throw $e;
    }

    $this->_redirectCustom($topic);
  }
}
