Exemplo n.º 1
0
 /**
  *	Enforces singleton use
  *
  *
  ***/
 public static function instance()
 {
     if (empty(self::$instance)) {
         self::$instance = new vB_Akismet();
     }
     return self::$instance;
 }
Exemplo n.º 2
0
 /**
  * Sets or unsets the approved field
  * @param array $nodeids
  * @param boolean $approved - set or unset the approved field
  * @throws vB_Exception_Api
  * @return array - the nodeids that have the permission to be changed
  */
 public function setApproved($approveNodeIds, $approved = true)
 {
     if (empty($approveNodeIds)) {
         return false;
     }
     $loginfo = array();
     $nodeIds = array();
     foreach ($approveNodeIds as $idx => $id) {
         $nodeInfo = $this->getNode($id);
         if ($nodeInfo['deleteuserid']) {
             // Do not do approve/unapprove actions on deleted posts
             continue;
         }
         if (!empty($nodeInfo['errors'])) {
             continue;
         }
         if (!$nodeInfo['approved'] and !$approved) {
             continue;
         }
         if ($nodeInfo['approved'] and $approved) {
             continue;
         }
         $nodeIds[] = $nodeInfo['nodeid'];
         $loginfo[] = array('nodeid' => $nodeInfo['nodeid'], 'nodetitle' => $nodeInfo['title'], 'nodeusername' => $nodeInfo['authorname'], 'nodeuserid' => $nodeInfo['userid']);
     }
     if (empty($nodeIds)) {
         return false;
     }
     $errors = array();
     $assertor = vB::getDbAssertor();
     $result = $assertor->update('vBForum:node', array('approved' => $approved), array('nodeid' => $nodeIds));
     if (!empty($result['errors'])) {
         $errors[] = $result['errors'];
     }
     $method = empty($approved) ? 'unapproveNode' : 'approveNode';
     $result = $assertor->assertQuery('vBForum:' . $method, array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $nodeIds));
     // Report as ham if this node was spam..
     if ($method == 'approveNode') {
         $vboptions = vB::getDatastore()->getValue('options');
         if ($vboptions['vb_antispam_type'] and $vboptions['vb_antispam_key']) {
             $spamids = array();
             $spamcheck = $assertor->getRows('spamlog', array('nodeid' => $nodeIds));
             foreach ($spamcheck as $spam) {
                 $spamids[] = $spam['nodeid'];
             }
             if ($spamids) {
                 $nodes = $this->getContentforNodes($spamids);
                 $akismet = vB_Akismet::instance();
                 foreach ($nodes as $node) {
                     if ($node['content']['rawtext']) {
                         $text = vB_String::stripBbcode($node['content']['rawtext'], true);
                         $akismet->markAsHam(array('comment_type' => 'comment', 'comment_author' => $node['content']['authorname'], 'comment_content' => $text, 'user_ip' => $node['content']['ipaddress']));
                     }
                 }
                 $assertor->delete('spamlog', array('nodeid' => $spamids));
             }
         }
     }
     if (!empty($result['errors'])) {
         $errors[] = $result['errors'];
     }
     $nodeIds = array_unique($nodeIds);
     $searchAPI = vB_Api::instanceInternal('Search');
     foreach ($nodeIds as $nodeid) {
         $node = $this->getNode($nodeid);
         $parent = $this->getNodeBare($node['parentid']);
         if ($node['showpublished']) {
             $nodeUpdates = $this->publishChildren($node['nodeid']);
         } else {
             $nodeUpdates = $this->unpublishChildren($node['nodeid']);
         }
         //we must update the last nodes for the subtree before handling the parents, otherwise it won't work.
         $this->updateLastForSubtree($nodeid);
         $this->updateChangedNodeParentCounts($node, $nodeUpdates);
         //$assertor->assertQuery('vBForum:updateLastData', array('parentid' => $nodeid, 'timenow' => vB::getRequest()->getTimeNow()));
         // Update the user post count (approve / unapprove)
         vB_Cache::allCacheEvent('nodeChg_' . $nodeid);
         if ($approved) {
             vB_Library_Content::getContentLib($node['contenttypeid'])->incrementUserPostCount($node);
         } else {
             vB_Library_Content::getContentLib($node['contenttypeid'])->decrementUserPostCount($node, 'unapprove');
         }
         $searchAPI->attributeChanged($node['nodeid']);
     }
     $this->clearCacheEvents($nodeIds);
     $this->clearChildCache($nodeIds);
     if (!empty($errors)) {
         return array('errors' => $errors);
     }
     vB_Library_Admin::logModeratorAction($loginfo, $approved ? 'node_approved_by_x' : 'node_unapproved_by_x');
     return $nodeIds;
 }
Exemplo n.º 3
0
 /**
  * Adds a new node.
  *
  * @param	mixed		Array of field => value pairs which define the record.
  *  -- htmlstate
  *  -- parentid
  *  -- disable_bbcode
  *  -- rawtext
  *  -- and others
  * @param	array		Array of options for the content being created
  * 						Understands skipTransaction, skipFloodCheck, floodchecktime, skipDupCheck, skipNotification, nl2br, autoparselinks.
  *							- nl2br: if TRUE, all \n will be converted to <br /> so that it's not removed by the html parser (e.g. comments).
  * @param	bool		Convert text to bbcode
  *
  * 	@return	mixed		array with nodeid (int), success (bool), cacheEvents (array of strings), nodeVals (array of field => value), attachments (array of attachment records).
  */
 public function add($data, array $options = array(), $convertWysiwygTextToBbcode = true)
 {
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     // html permission already checked in the api
     if (isset($data['htmlstate']) and $data['htmlstate'] == 'on' and isset($data['disable_bbcode']) and $data['disable_bbcode'] == 1) {
         // article 'static html' type
         $convertWysiwygTextToBbcode = false;
         if (isset($options['nl2br'])) {
             $options['nl2br'] = false;
         }
     }
     if (empty($data['parentid'])) {
         throw new Exception('need_parent_node');
     }
     // Get parents for cleaning cache and checking permissions
     $parents = vB_Library::instance('node')->getParents($data['parentid']);
     $parents = array_reverse($parents);
     // convert to bbcode for saving
     if (isset($data['rawtext']) and !empty($data['rawtext'])) {
         // Converts new lines when CKEditor is not in use (plain text area) VBV-11279
         // also used for the mobile app.
         if (isset($options['nl2br']) and $options['nl2br']) {
             $data['rawtext'] = nl2br($data['rawtext']);
         }
         if ($convertWysiwygTextToBbcode) {
             $channelType = vB_Types::instance()->getContentTypeId('vBForum_Channel');
             // check if we can autoparselinks
             $options['autoparselinks'] = true;
             foreach ($parents as $parent) {
                 // currently only groups and blogs seem to disallow this
                 if (($parent['contenttypeid'] == $channelType and vB_Api::instanceInternal('socialgroup')->isSGNode($parent['nodeid']) or vB_Api::instanceInternal('blog')->isBlogNode($parent['nodeid'])) and $channelOptions = vB_Library::instance('node')->getNodeOptions($parent['nodeid'])) {
                     $options['autoparselinks'] = $channelOptions['autoparselinks'];
                 }
             }
             $data['rawtext'] = vB_Api::instanceInternal('bbcode')->convertWysiwygTextToBbcode($data['rawtext'], $options);
             if (empty($data['description'])) {
                 $data['description'] = vB_String::getPreviewText($this->parseAndStrip($data['rawtext']));
             } else {
                 $data['description'] = vB_String::getPreviewText($this->parseAndStrip($data['description']));
             }
         }
     } else {
         if (empty($data['description'])) {
             $data['description'] = isset($data['title']) ? vB_String::getPreviewText($this->parseAndStrip($data['title'])) : '';
         } else {
             $data['description'] = vB_String::getPreviewText($this->parseAndStrip($data['description']));
         }
     }
     if (empty($data['userid'])) {
         $user = vB::getCurrentSession()->fetch_userinfo();
         $data['authorname'] = $user['username'];
         $userid = $data['userid'] = $user['userid'];
     } else {
         $userid = $data['userid'];
         if (empty($data['authorname'])) {
             $data['authorname'] = vB_Api::instanceInternal('user')->fetchUserName($userid);
         }
         $user = vB_Api::instance('user')->fetchUserinfo($userid);
     }
     $userContext = vB::getUserContext($userid);
     $isSpam = false;
     $skipSpam = ($userContext->getChannelPermission('forumpermissions2', 'exemptfromspamcheck', $data['parentid']) or $userContext->getChannelPermission('moderatorpermissions', 'canmoderateposts', $data['parentid']) or isset($options['skipSpamCheck']) and $options['skipSpamCheck'] and vB::getUserContext()->getChannelPermission('moderatorpermissions', 'canmoderateposts', $data['parentid']));
     //run the spam check.
     if (!$skipSpam and $this->spamType !== false) {
         if (empty($this->akismet)) {
             $this->akismet = vB_Akismet::instance();
         }
         $params = array('comment_type' => 'user_post', 'comment_content' => $data['rawtext']);
         $params['comment_author'] = $data['authorname'];
         $params['comment_author_email'] = $user['email'];
         $result = $this->akismet->verifyText($params);
         if ($result == 'spam') {
             $data['approved'] = 0;
             $data['showapproved'] = 0;
             $isSpam = true;
         }
     }
     if (!$skipSpam and !$isSpam and $blacklist = trim($this->options['vb_antispam_badwords'])) {
         $badwords = preg_split('#\\s+#', $blacklist, -1, PREG_SPLIT_NO_EMPTY);
         if (str_replace($badwords, '', strtolower($data['rawtext'])) != strtolower($data['rawtext'])) {
             $data['approved'] = 0;
             $data['showapproved'] = 0;
             $isSpam = true;
         }
     }
     if (!$skipSpam and !$isSpam) {
         preg_match_all('#\\[(url|email).*\\[/(\\1)\\]#siU', $data['rawtext'], $matches);
         if (isset($matches[0]) and count($matches[0]) > intval($this->options['vb_antispam_maxurl'])) {
             $data['approved'] = 0;
             $data['showapproved'] = 0;
             $isSpam = true;
         }
     }
     //We need a copy of the data, maybe
     $updates = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED);
     //Set the "hasvideo" value;
     if (!empty($data['rawtext'])) {
         $filter = '~\\[video.*\\[\\/video~i';
         $matches = array();
         $count = preg_match_all($filter, $data['rawtext'], $matches);
         if ($count > 0) {
             $data['hasvideo'] = 1;
         } else {
             $data['hasvideo'] = 0;
         }
     }
     //publishdate is set in the parent class and api. If not set in data, it'll be set to vB::getRequest()->getTimeNow() in parent::add()
     if (isset($data['publishdate'])) {
         $updates['lastcontent'] = $data['publishdate'];
     } else {
         $updates['lastcontent'] = vB::getRequest()->getTimeNow();
     }
     if (isset($data['userid'])) {
         $updates['lastauthorid'] = $data['userid'];
     } else {
         $updates['lastauthorid'] = $data['userid'] = vB::getCurrentSession()->get('userid');
     }
     if (isset($data['authorname'])) {
         $updates['lastcontentauthor'] = $data['authorname'];
     } else {
         $author = $this->assertor->getRow('user', array(vB_Db_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'userid' => $data['userid']));
         $data['authorname'] = $author['username'];
         $updates['lastcontentauthor'] = $author['username'];
     }
     $published = $this->isPublished($data);
     try {
         if (!$skipTransaction) {
             $this->assertor->beginTransaction();
         }
         $options['skipTransaction'] = true;
         $results = parent::add($data, $options);
         $newNode = $this->getFullContent($results['nodeid']);
         $newNode = array_pop($newNode);
         // Obtain and set generic conversation route
         $conversation = $this->getConversationParent($results['nodeid']);
         $routeid = vB_Api::instanceInternal('route')->getChannelConversationRoute($conversation['parentid']);
         $this->assertor->update('vBForum:node', array('routeid' => $routeid), array('nodeid' => $results['nodeid']));
         if (!$skipTransaction) {
             $this->assertor->commitTransaction();
         }
     } catch (exception $e) {
         if (!$skipTransaction) {
             $this->assertor->rollbackTransaction();
         }
         throw $e;
     }
     //set the last post and count data.
     /* 	We do something similar (vBForum:fixNodeLast) that ends up affect parent last data in the parent add(),
      *	downstream of updateParentCounts(). We should probably refactor to just do it in one place. I tried to
      *	comment this section out, but the node test told me that they're not *quite* the same and this is
      *	necessary.
      */
     $approved = (isset($data['showapproved']) ? $data['showapproved'] : true and isset($data['approved']) ? $data['approved'] : true);
     if ($published and $approved and (!isset($options['skipUpdateLastContent']) or !$options['skipUpdateLastContent'])) {
         $updates['nodeid'] = $results['nodeid'];
         $updates['lastcontentid'] = $results['nodeid'];
         $parentids = array();
         foreach ($parents as $node) {
             $parentids[] = $node['nodeid'];
         }
         $updates['parentlist'] = $parentids;
         $this->qryAfterAdd[] = array('definition' => 'vBForum:setLastDataParentList', 'data' => $updates);
     }
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($results['nodeid'], $data, $options, $results['cacheEvents'], $results['nodeVals']);
     }
     if ($isSpam) {
         $this->assertor->assertQuery('spamlog', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERTIGNORE, 'nodeid' => $results['nodeid']));
     }
     $cachedNodes = array($results['nodeid']);
     foreach ($parents as $node) {
         $cachedNodes[] = $node['nodeid'];
     }
     $this->nodeApi->clearCacheEvents($cachedNodes);
     $this->nodeApi->clearCacheEvents(array($results['nodeid'], $data['parentid']));
     return $results;
 }