Пример #1
0
 /**
  * Add photo record
  *
  * @param	mixed	Array of field => value pairs which define the record.
  * @param	array		Array of options for the content being created
  * 						Understands skipTransaction, skipFloodCheck, floodchecktime.
  *
  * 	@return	mixed		array with nodeid (int), success (bool), cacheEvents (array of strings), nodeVals (array of field => value).
  */
 public function add($data, array $options = array())
 {
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     $options += array('skipDupCheck' => true);
     if (empty($data['filedataid'])) {
         throw new vB_Exception_Api('incomplete_data');
     }
     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'])) {
             $user = vB_Api::instanceInternal('user')->fetchUserName($userid);
             $data['authorname'] = $user;
         }
     }
     try {
         if (!$skipTransaction) {
             $this->assertor->beginTransaction();
         }
         $options['skipTransaction'] = true;
         /** Validate Filedata */
         $newNode = parent::add($data, $options);
         /** Update filedata refcount */
         $fileData = $this->assertor->getRow('vBForum:filedata', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'filedataid' => $data["filedataid"]));
         $refCount = $fileData["refcount"] + 1;
         $photodata = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, vB_dB_Query::CONDITIONS_KEY => array('filedataid' => $data['filedataid']), 'refcount' => $refCount);
         $this->assertor->assertQuery('vBForum:filedata', $photodata);
         if (!$skipTransaction) {
             $this->assertor->commitTransaction();
         }
     } catch (exception $e) {
         if (!$skipTransaction) {
             $this->assertor->rollbackTransaction();
         }
         throw $e;
     }
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($newNode['nodeid'], $data, $options, $newNode['cacheEvents'], $newNode['nodeVals']);
     }
     return $newNode;
 }
Пример #2
0
 public function add($data, array $options = array())
 {
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     //todo -- lock the caption to the description until we collapse the fields.  Remove when caption goes away
     if (isset($data['caption'])) {
         $data['description'] = $data['caption'];
     } else {
         if (isset($data['description'])) {
             $data['caption'] = $data['description'];
         }
     }
     try {
         if (!$skipTransaction) {
             $this->assertor->beginTransaction();
         }
         $options['skipTransaction'] = true;
         $result = parent::add($data, $options);
         if ($result) {
             $this->assertor->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'nodeid' => $data['parentid'], 'hasphoto' => 1));
             // Increment the refcount in filedata.
             // Note that content_attach API's validate() ensures that we have $data['filedataid'] set.
             $this->assertor->assertQuery('updateFiledataRefCount', array('countChange' => 1, 'filedataid' => $data['filedataid']));
         }
         if (!$skipTransaction) {
             $this->assertor->commitTransaction();
         }
     } catch (exception $e) {
         if (!$skipTransaction) {
             $this->assertor->rollbackTransaction();
         }
         throw $e;
     }
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($result['nodeid'], $data, $options, $result['cacheEvents'], $result['nodeVals']);
     }
     return $result;
 }
Пример #3
0
 public function add($data, array $options = array('nodeonly' => false))
 {
     $options += array('skipDupCheck' => true);
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     // VBV-833: we allow interfaces to not specify a parent. Main channel should be used in that case
     if (!isset($data['parentid']) or $data['parentid'] <= 0) {
         $data['parentid'] = vB::getDbAssertor()->getField('vBForum:channel', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array('guid' => vB_Channel::DEFAULT_CHANNEL_PARENT)));
     } else {
         // if we are not using the default channel parent, we need to check for pagetemplates
         if (!isset($data['templates'])) {
             $parent = vB::getDbAssertor()->getRow('vBForum:channel', array(vB_dB_Query::COLUMNS_KEY => array('nodeid', 'guid'), vB_dB_Query::CONDITIONS_KEY => array('nodeid' => $data['parentid'])));
             switch ($parent['guid']) {
                 case vB_Channel::DEFAULT_SOCIALGROUP_PARENT:
                     // This is done only when saving from activity stream configuration, once it is removed we can get rid of this
                     $data['templates']['vB5_Route_Channel'] = vB_Page::getSGCategoryPageTemplate();
                     $data['templates']['vB5_Route_Conversation'] = vB_Page::getSGCategoryConversPageTemplate();
                     $data['category'] = 1;
                     break;
                 case vB_Channel::DEFAULT_ARTICLE_PARENT:
                     // articles
                     $data['templates']['vB5_Route_Channel'] = vB_Page::getArticleChannelPageTemplate();
                     $data['templates']['vB5_Route_Conversation'] = vB_Page::getArticleConversPageTemplate();
                     break;
                 default:
                     // use inherited from parent channel
                     break;
             }
         }
     }
     if (!isset($data['guid'])) {
         // creating guid
         $data['guid'] = vB_Xml_Export_Channel::createGUID($data);
     }
     // parse options array
     if (isset($data['options'])) {
         if (is_array($data['options'])) {
             $value = $this->buildChannelOptions(0, $data['options']);
             if ($value !== FALSE) {
                 $data['options'] = $value;
             } else {
                 // do not update field
                 unset($data['options']);
             }
         } else {
             // should we accept raw ints as updates?
             unset($data['options']);
         }
     }
     if (empty($data['urlident']) and !empty($data['title'])) {
         $data['urlident'] = $this->getUniqueUrlIdent($data['title']);
     }
     if (!isset($options['nodeonly']) || !$options['nodeonly']) {
         // if we are going to create pages, verify that prefix/regex generated is valid BEFORE creating the node
         vB5_Route_Channel::validatePrefix($data);
     }
     try {
         if (!$skipTransaction) {
             $this->assertor->beginTransaction();
         }
         $options['skipTransaction'] = true;
         $result = parent::add($data, $options);
         if (!isset($options['nodeonly']) || !$options['nodeonly']) {
             $this->nodeLibrary->clearCacheEvents($result['nodeid']);
             $this->createChannelPages($result['nodeid'], $data);
         }
         if (!$skipTransaction) {
             $this->assertor->commitTransaction();
         }
     } catch (exception $e) {
         if (!$skipTransaction) {
             $this->assertor->rollbackTransaction();
         }
         throw $e;
     }
     //and announce that the cached channel structure has changed.
     $result['cacheEvents'][] = 'vB_ChannelStructure_chg';
     if (isset($data['filedataid']) and vB::getUserContext()->getChannelPermission('forumpermissions', 'canuploadchannelicon', $result['nodeid'])) {
         $this->qryAfterAdd[] = array('definition' => 'incrementFiledataRefcountAndMakePublic', 'data' => array('filedataid' => $data['filedataid']));
     }
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($result['nodeid'], $data, $options, $result['cacheEvents'], $result['nodeVals']);
     }
     if (!defined('VB_AREA') or !in_array(VB_AREA, array('Install', 'Upgrade'))) {
         vB::getUserContext()->rebuildGroupAccess();
         vB::getUserContext()->reloadUserPerms();
         vB_Channel::rebuildChannelTypes();
     }
     return $result;
 }
Пример #4
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;
 }