Esempio n. 1
0
 /**
  * Performs the actual merging, using edited input from UI.
  * @param type $data - Contains pairs (value, name) from edit form in addition to the following fields:
  *						* mergePosts - posts to be merged
  *						* destnodeid - target post
  *						* destauthorid - author to be used
  *						* contenttype - target contenttype
  */
 public function mergePosts($input)
 {
     $this->inlinemodAuthCheck();
     $cleaner = vB::getCleaner();
     $data = array();
     foreach ($input as $i) {
         $name = $cleaner->clean($i['name'], vB_Cleaner::TYPE_NOHTML);
         //mostly the data is either integer or string, although the possibility exists of a
         //'url_image'
         switch ($name) {
             case 'nodeid':
             case 'url_nopreview':
             case 'nodeuserid':
             case 'filedataid':
             case 'destauthorid':
             case 'destnodeid':
                 $value = $cleaner->clean($i['value'], vB_Cleaner::TYPE_UINT);
                 break;
             case 'title':
             case 'text':
             case 'reason':
                 $value = $cleaner->clean($i['value'], vB_Cleaner::TYPE_STR);
                 break;
             case 'url_title':
             case 'authorname':
             case 'url':
             case 'url_image':
             case 'url_meta':
                 $value = $cleaner->clean($i['value'], vB_Cleaner::TYPE_NOHTML);
                 break;
             case 'mergePosts':
                 if (!is_array($i['value'])) {
                     $i['value'] = explode(',', $i['value']);
                 }
                 $value = $cleaner->clean($i['value'], vB_Cleaner::TYPE_ARRAY_UINT);
                 break;
             case 'filedataid[]':
                 //The filedata records are passed as
                 //input[xx][name]	filedataid[]
                 //input[xx][value]	<integer>
                 $value = $cleaner->clean($i['value'], vB_Cleaner::TYPE_UINT);
                 if (!isset($data['filedataid'])) {
                     $data['filedataid'] = array();
                 }
                 if (!isset($data['filedataid'][$value])) {
                     $data['filedataid'][$value] = '';
                 }
                 continue;
             default:
                 //The title records are passed as
                 //input[xx][name]	title_<filedataid>
                 //input[xx][value]	<title>
                 if (empty($name)) {
                     continue;
                 }
                 if (substr($name, 0, 6) == 'title_') {
                     $filedataid = substr($name, 6);
                     $filedataid = $cleaner->clean($filedataid, vB_Cleaner::TYPE_UINT);
                     if ($filedataid) {
                         if (!isset($data['filedataid'])) {
                             $data['filedataid'] = array();
                         }
                         $data['filedataid'][$filedataid] = $cleaner->clean($i['value'], vB_Cleaner::TYPE_NOHTML);
                     }
                     continue;
                 } else {
                     if (preg_match('#^videoitems\\[([\\d]+)#', $name, $matches)) {
                         if (!isset($data['videoitems'])) {
                             $data['videoitems'] = array();
                         }
                         $videoitems[] = array('videoitemid' => intval($matches[1]), 'url' => $i['value']);
                     } else {
                         if (preg_match('^videoitems\\[new^', $name, $matches)) {
                             if (!isset($data['videoitems'])) {
                                 $data['videoitems'] = array();
                             }
                             foreach ($matches as $video) {
                                 $data['videoitems'][] = array('url' => $video['url']);
                             }
                         }
                     }
                 }
                 continue;
         }
         if (isset($data[$name])) {
             if (!is_array($data[$name])) {
                 $data[$name] = array($data[$name]);
             }
             $data[$name][] = $value;
         } else {
             $data[$name] = $value;
         }
     }
     if (empty($data['mergePosts'])) {
         throw new vB_Exception_Api('please_select_at_least_one_post');
     }
     // check that the user has permission
     $nodesToCheck = $data['mergePosts'];
     $nodesToCheck[] = $data['destnodeid'];
     foreach ($nodesToCheck as $key => $nodeid) {
         // this is here just in case for some reason, a nodeid is 0. Shouldn't happen, but
         // I don't want getChannelPermission to go bonkers from it.
         if (empty($nodeid)) {
             unset($nodesToCheck[$key]);
             continue;
         }
         if (!vB::getUserContext()->getChannelPermission('moderatorpermissions', 'canmanagethreads', $nodeid)) {
             // perhaps we could generate a list of unmergeable nodes and return a warning instead, but
             // I don't think there's a real use case where a moderator can manage only *some* of the
             // nodes they're trying to merge. I think that would require multiple channels being involved, and
             // we don't have a UI for that so I can't test it. As such I'm just going to throw an exception if
             // *any* of the nodes fail the check.
             throw new vB_Exception_Api('no_permission');
         }
     }
     // validate that selected nodes can be merged
     $mergeInfo = $this->validateMergePosts($data['mergePosts']);
     if (isset($mergeInfo['error'])) {
         throw new vB_Exception_Api($mergeInfo['error']);
     }
     // validate form fields
     if (empty($data['destnodeid']) || !array_key_exists($data['destnodeid'], $mergeInfo['destnodes'])) {
         throw new vB_Exception_Api('invalid_data');
     }
     if (empty($data['destauthorid']) || !array_key_exists($data['destauthorid'], $mergeInfo['destauthors'])) {
         throw new vB_Exception_Api('invalid_data');
     }
     $destnode = $this->library->getNodeFullContent($data['destnodeid']);
     $destnode = array_pop($destnode);
     if ($destnode['starter'] != $destnode['nodeid'] and $destnode['starter'] != $destnode['parentid']) {
         if (isset($data['tags'])) {
             unset($data['tags']);
         }
     }
     $type = vB_Types::instance()->getContentTypeClass($destnode['contenttypeid']);
     $response = vB_Library::instance("content_{$type}")->mergeContent($data);
     if ($response) {
         $sources = array_diff($data['mergePosts'], array($data['destnodeid']));
         $origDestnode = $destnode;
         if (!empty($destnode['rawtext'])) {
             $origRawText = $destnode['rawtext'];
         } else {
             if (!empty($destnode['content']['rawtext'])) {
                 $origRawText = $destnode['content']['rawtext'];
             } else {
                 $origRawText = '';
             }
         }
         $destnode = $this->getNode($data['destnodeid']);
         if (!empty($destnode['rawtext'])) {
             $rawText = $destnode['rawtext'];
         } else {
             if (!empty($destnode['content']['rawtext'])) {
                 $rawText = $destnode['content']['rawtext'];
             } else {
                 $rawText = '';
             }
         }
         $destnode = $this->getNode($data['destnodeid']);
         $loginfo = array('nodeid' => $destnode['nodeid'], 'nodetitle' => $destnode['title'], 'nodeusername' => $destnode['authorname'], 'nodeuserid' => $destnode['userid']);
         // move children to target node
         $children = vB::getDbAssertor()->assertQuery('vBForum:closure', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'parent' => $sources, 'depth' => 1));
         $childrenIds = array();
         foreach ($children as $child) {
             $childrenIds[] = $child['child'];
         }
         if (!empty($childrenIds)) {
             $this->moveNodes($childrenIds, $data['destnodeid'], false, false, false);
         }
         // remove merged nodes
         $this->deleteNodes($sources, true, null, false);
         //  Dont log the deletes
         $loginfo['action'] = array('merged_nodes' => implode(',', $sources));
         $vboptions = vB::getDatastore()->getValue('options');
         if (vB_Api::instanceInternal('user')->hasPermissions('genericoptions', 'showeditedby') and $destnode['publishdate'] > 0 and $destnode['publishdate'] < vB::getRequest()->getTimeNow() - $vboptions['noeditedbytime'] * 60 or !empty($data['reason'])) {
             $userinfo = vB::getCurrentSession()->fetch_userinfo();
             if ($vboptions['postedithistory']) {
                 $record = vB::getDbAssertor()->getRow('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'original' => 1, 'nodeid' => $destnode['nodeid']));
                 // insert original post on first edit
                 if (empty($record)) {
                     vB::getDbAssertor()->assertQuery('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'nodeid' => $origDestnode['nodeid'], 'userid' => $origDestnode['userid'], 'username' => $origDestnode['authorname'], 'dateline' => $origDestnode['publishdate'], 'pagetext' => $origRawText, 'original' => 1));
                 }
                 // insert the new version
                 vB::getDbAssertor()->assertQuery('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'nodeid' => $destnode['nodeid'], 'userid' => $userinfo['userid'], 'username' => $userinfo['username'], 'dateline' => vB::getRequest()->getTimeNow(), 'reason' => isset($data['reason']) ? vB5_String::htmlSpecialCharsUni($data['reason']) : '', 'pagetext' => $rawText));
             }
             vB::getDbAssertor()->assertQuery('editlog_replacerecord', array('nodeid' => $destnode['nodeid'], 'userid' => $userinfo['userid'], 'username' => $userinfo['username'], 'timenow' => vB::getRequest()->getTimeNow(), 'reason' => isset($data['reason']) ? vB5_String::htmlSpecialCharsUni($data['reason']) : '', 'hashistory' => intval($vboptions['postedithistory'])));
         }
         vB_Library_Admin::logModeratorAction($loginfo, 'node_merged_by_x');
         return true;
     }
 }