WordPushCommand.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. class WordPushCommand extends CConsoleCommand
  3. {
  4. public $examType = array(1=>'周考', 2=>'单元考', 3=>'月考', 4=>'联考', 5=>'期中',6=>'期末', 7=>'高考模拟', 8=>'冲刺', 9=>'测试');
  5. public $topicTypeName = array(
  6. 3 => array(1=>'选择题',2=>'多选题',5=>'填空题',6=>'填空题',7=>'解答题',11=>'不定项'),
  7. 8 => array(1=>'单项填空',2=>'完形填空',3=>'阅读理解',4=>'任务型阅读',5=>'七选五',6=>'语法填空',7=>'短文改错',13=>'书面表达',15=>'听力',16=>'应用文写作',17=>'读后续写'),
  8. );
  9. public function init()
  10. {
  11. parent::init();
  12. @ini_set('memory_limit', '1024M');
  13. set_time_limit(0);
  14. }
  15. public function actionIndex($school_id = '', $YII_ENV = 'development')
  16. {
  17. // 连接业务库
  18. // $pdoParam = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8";');
  19. // $businessServer = Yii::app()->params["businessDb"];
  20. $databaseFields = 'database_host,database_name,database_user,database_password,school_id';
  21. // $busDsn = 'mysql:host=' . $businessServer['addr'] . ';dbname=' . Yii::app()->params["default_db"]['name'] . ';';
  22. // $busDbh = new PDO($busDsn, $businessServer['username'], $businessServer['password'], $pdoParam);
  23. $busDbh = Yii::app()->businessDb;
  24. // 获取所有可用的学校
  25. if ($school_id) {
  26. $dataSql = "SELECT {$databaseFields} FROM `database` WHERE `school_id` IN ({$school_id})";
  27. } else {
  28. $dataSql = "SELECT {$databaseFields} FROM `database` WHERE `school_id` IN (SELECT school_id FROM `school` WHERE `status`=0)";
  29. }
  30. // 找出学校的链接信息
  31. $dataObj = $busDbh->query($dataSql);
  32. $dataInfo = $dataObj->fetchAll(PDO::FETCH_ASSOC);
  33. if (empty($dataInfo)) {
  34. exit('未找到学校数据库链接信息!');
  35. }
  36. // 获取学校所属的省份
  37. $schoolIds = array();
  38. $schoolProvince = array();
  39. foreach($dataInfo as $tempSchool) {
  40. $schoolIds[] = $tempSchool['school_id'];
  41. }
  42. $schoolIdString = implode(',', $schoolIds);
  43. $schoolObj = $busDbh->query("SELECT s.school_id,r.region_name FROM `school` s LEFT JOIN `region` r ON r.region_id = s.province_id WHERE s.`school_id` IN ({$schoolIdString})");
  44. $schoolInfo = $schoolObj->fetchAll(PDO::FETCH_ASSOC);
  45. foreach ($schoolInfo as $key => $tempProvince) {
  46. $schoolProvince[$tempProvince['school_id']] = $tempProvince['region_name'];
  47. }
  48. // 获取所有学科
  49. $packSubject = array();
  50. $subjectObj = $busDbh->query('SELECT subject_id,subject_name,section FROM `subject`')->fetchAll(PDO::FETCH_ASSOC);
  51. foreach($subjectObj as $tempSubject) {
  52. $packSubject[$tempSubject['subject_id']]['name'] = $tempSubject['subject_name'];
  53. $packSubject[$tempSubject['subject_id']]['section'] = $tempSubject['section'];
  54. }
  55. $busDbh = null; // 关闭链接
  56. $callbackUrl = ''; // 回调地址
  57. $analysisUrl = ''; // 解析地址
  58. $myPath = dirname(dirname(dirname(__FILE__)));
  59. $scienceWordAnalysisUrl = Yii::app()->params['science_word_analysis_url']; // 物理解析地址
  60. $subjectCoachCallbackUrl = Yii::app()->params['subject_coach_callback_url']; // 全学科第三方试卷解析回调
  61. // 新解析工具
  62. $rapidAnalysisUrl = Yii::app()->params['rapid_analysis_url']; // 解析地址
  63. $rapidCallbackUrl = Yii::app()->params['rapid_callback_url']; // 解析回调
  64. // 发送Word处理
  65. foreach ($dataInfo as $data) {
  66. echo 'STARTING==>' . $data['school_id'] . "\n";
  67. $temp_dsn = 'mysql:host=' . $data['database_host'] . ';dbname=' . $data['database_name'] . ';';
  68. $temp_dbh = new PDO($temp_dsn, $data['database_user'], $data['database_password'], $pdoParam);
  69. $temp_obj = $temp_dbh->query('SELECT word_id,exam_group_id,word_path,uploader_id,type_id,subject_id,allsubject_file_path,source FROM `topic_word` WHERE `status`=0 AND `source` != 4');
  70. $temp_info = $temp_obj->fetchAll(PDO::FETCH_ASSOC);
  71. if (empty($temp_info)) {
  72. echo 'not found any word in school_' . $data['school_id'] . "\n";
  73. } else {
  74. foreach ($temp_info as $info) {
  75. // 老版解析工具
  76. if (empty($info['allsubject_file_path'])) {
  77. $analysisUrl = $scienceWordAnalysisUrl; // 高中物理解析地址
  78. if ($info['exam_group_id']) {
  79. $callbackUrl = $subjectCoachCallbackUrl;
  80. }
  81. if (empty($callbackUrl) || empty($analysisUrl)) continue;
  82. echo $analysisUrl.'----'.$callbackUrl. "\n";
  83. if (false !== strpos($info['word_path'], 'http://')) {
  84. $time = time();
  85. $arr = self::getFile($info['word_path'], '/tem', $info['uploader_id'] . $time . '.docx');
  86. if ($arr && file_exists($arr['save_path'])) {
  87. $retRes = self::curlWord($analysisUrl, $callbackUrl, $info['word_id'], $arr['save_path'], $data['school_id']);
  88. $json_array = json_decode($retRes, true);
  89. $temp_dbh = new PDO($temp_dsn, $data['database_user'], $data['database_password'], $pdoParam);
  90. if (!$json_array || $json_array['errcode'] > 0) {
  91. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '3',`wrong_reason` = '" . $json_array['errmsg'] . "',`content` ='" . $retRes . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  92. } else {
  93. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '1',`file_queue`='" . $json_array['docsbefore'] . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  94. }
  95. $temp_dbh = null;
  96. @unlink($arr['save_path']);
  97. echo 'Send the word id : ' . $info['word_id'] . "\n";
  98. }
  99. } else {
  100. if (file_exists($myPath . '/' . $info['word_path'])) {
  101. echo 'Send the word path : ' . $info['word_path'] . "\n";
  102. $retRes = self::curlWord($analysisUrl, $callbackUrl, $info['word_id'], $myPath . '/' . $info['word_path'], $data['school_id']);
  103. $json_array = json_decode($retRes, true);
  104. $temp_dbh = new PDO($temp_dsn, $data['database_user'], $data['database_password'], $pdoParam);
  105. if (!$json_array || $json_array['errcode'] > 0) {
  106. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '3',`wrong_reason` = '" . $json_array['errmsg'] . "',`content` ='" . $retRes . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  107. } else {
  108. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '1',`file_queue`='" . $json_array['docsbefore'] . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  109. }
  110. } else {
  111. echo 'lost the word path : ' . $myPath . '/' . $info['word_path'] . "\n";
  112. }
  113. }
  114. } else {
  115. $paperTopicType = array();
  116. $typeNames = $info['subject_id'] == 8 ? $this->topicTypeName[8] : $this->topicTypeName[3];
  117. // 考试信息
  118. $exam = $temp_dbh->query('SELECT `name`,`type`,`exam_id` FROM `exam` WHERE `exam_group_id`="' . $info['exam_group_id'].'"')->fetch(PDO::FETCH_ASSOC);
  119. if (empty($exam)) continue;
  120. // 在线答题卡PDF
  121. $card = $temp_dbh->query('SELECT `online_card_pdf` FROM `third_answer_sheet` WHERE `exam_group_id`="' . $info['exam_group_id'].'"')->fetch(PDO::FETCH_ASSOC);
  122. $onlineCardPdf = $card && !empty($card['online_card_pdf']) ? $card['online_card_pdf'] : '';
  123. // 获取考试试题信息
  124. $paperTopics = $temp_dbh->query('select ptr.topic_id,ptr.type from paper p left join paper_topic_relation ptr ON ptr.paper_id = p.paper_id where p.exam_id="'.$exam['exam_id'].'" order by ptr.order asc')->fetchAll(PDO::FETCH_ASSOC);
  125. if (empty($paperTopics)) continue;
  126. if ($info['subject_id'] == 8) { // 英语试卷获取大题逻辑题型
  127. $largeTopics = $temp_dbh->query('select ptl.logic_type from paper p left join paper_topic_large ptl ON ptl.paper_id = p.paper_id where p.exam_id="'.$exam['exam_id'].'" order by ptl.topic_no asc')->fetchAll(PDO::FETCH_ASSOC);
  128. if ($largeTopics) {
  129. foreach ($largeTopics as $largeTopic) {
  130. $paperTopicType[] = isset($typeNames[$largeTopic['logic_type']]) ? $typeNames[$largeTopic['logic_type']] : '';
  131. }
  132. }
  133. } else {
  134. foreach ($paperTopics as $paperTopic) {
  135. $paperTopicType[] = isset($typeNames[$paperTopic['type']]) ? $typeNames[$paperTopic['type']] : '解答题';
  136. }
  137. }
  138. $wordParams = array(
  139. 'source' => 'xue_guan',
  140. 'paper_name' => $exam['name'],
  141. 'subject' => isset($packSubject[$info['subject_id']]) ? $packSubject[$info['subject_id']]['name'] : '',
  142. 'period' => isset($packSubject[$info['subject_id']]) && $packSubject[$info['subject_id']]['section'] == 1 ? '高中' : '初中',
  143. 'province' => isset($schoolProvince[$data['school_id']]) ? $schoolProvince[$data['school_id']] : '中国',
  144. 'category' => isset($this->examType[$exam['type']]) ? array($this->examType[$exam['type']]) : array(),
  145. 'is_cloud' => 1,
  146. 'file_list' => json_decode($info['allsubject_file_path'],true),
  147. 'item_num_info' => array(
  148. 'total_nums' => count($paperTopics),
  149. 'paper_topic_type' => $paperTopicType,
  150. 'paper_card_pdf' => $onlineCardPdf
  151. ),
  152. 'callback_url' => $rapidCallbackUrl . '/sid/' . $data['school_id'] . '/wid/' . $info['word_id']
  153. );
  154. $retrunJson = self::curlFile($rapidAnalysisUrl, json_encode($wordParams));
  155. $returnResult = json_decode($retrunJson, true);
  156. if (isset($returnResult['id']) && $returnResult['id'] != 0) {
  157. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '1',`params_id`='" . $returnResult['id'] . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  158. } else {
  159. $temp_dbh->exec("UPDATE `topic_word` SET `status` = '3',`wrong_reason` = '发送解析异常',`content` ='" . $retrunJson . "' WHERE `word_id` ='" . $info['word_id'] . "'");
  160. }
  161. echo 'Send the word id : ' . $info['word_id'] . "\n";
  162. }
  163. }
  164. }
  165. $temp_dbh = null;
  166. echo 'ENDING==>' . $data['school_id'] . "\n\n";
  167. }
  168. }
  169. // POST word
  170. public function curlWord($analysisUrl, $word_api_url, $word_id, $postFilePath, $school_id)
  171. {
  172. if (substr(PHP_VERSION, 0, 3) >= '5.5') {
  173. $pathName = pathinfo($postFilePath);
  174. $cfile = curl_file_create($postFilePath, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', $pathName['basename']);
  175. $imgdata = array(
  176. 'callback_url' => $word_api_url . '/sid/' . $school_id . '/wid/' . $word_id . '/is_cloud/1',
  177. 'sid' => $school_id,
  178. 'is_cloud' => 1,
  179. 'mydata' => $cfile
  180. );
  181. } else {
  182. $imgdata = array(
  183. 'callback_url' => $word_api_url . '/sid/' . $school_id . '/wid/' . $word_id . '/is_cloud/1',
  184. 'sid' => $school_id,
  185. 'is_cloud' => 1,
  186. 'mydata' => '@' . $postFilePath
  187. );
  188. }
  189. $curl = curl_init();
  190. curl_setopt($curl, CURLOPT_URL, $analysisUrl);
  191. curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
  192. curl_setopt($curl, CURLOPT_HTTPHEADER, array('User-Agent: Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15', 'Referer: http://someaddress.tld', 'Content-Type: multipart/form-data'));
  193. //curl_setopt($ch, CURLOPT_HEADER, false);
  194. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  195. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  196. curl_setopt($curl, CURLOPT_POST, true);
  197. curl_setopt($curl, CURLOPT_POSTFIELDS, $imgdata);
  198. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  199. $r = curl_exec($curl);
  200. curl_close($curl);
  201. return $r;
  202. }
  203. protected function getFile($url, $save_dir = '', $filename = '', $type = 1)
  204. {
  205. $file_type = strtolower(substr($url, strrpos($url, '.') + 1));
  206. //获取远程文件所采用的方法
  207. if ($type) {
  208. $ch = curl_init();
  209. $timeout = 5;
  210. curl_setopt($ch, CURLOPT_URL, $url);
  211. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  212. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  213. $content = curl_exec($ch);
  214. curl_close($ch);
  215. } else {
  216. ob_start();
  217. readfile($url);
  218. $content = ob_get_contents();
  219. ob_end_clean();
  220. }
  221. $size = strlen($content);
  222. $test_dir = tempnam($save_dir, $filename);
  223. //文件大小
  224. $fp2 = @fopen($test_dir, 'w');
  225. fwrite($fp2, $content);
  226. fclose($fp2);
  227. unset($content, $url);
  228. $path = explode('.', $test_dir);
  229. @rename($test_dir, $path[0] . '.' . $file_type);
  230. return array(
  231. 'file_name' => $filename,
  232. 'save_path' => $path[0] . '.' . $file_type,
  233. 'file_size' => $size
  234. );
  235. }
  236. // POST WORD
  237. public function curlFile($analysisUrl, $wordParams)
  238. {
  239. $ch = curl_init();
  240. curl_setopt($ch, CURLOPT_HEADER, 0); // 不输出头部
  241. curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 返回数据等待
  242. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); // 连接等待时间
  243. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取到的内容不直接输出, 而是返回
  244. curl_setopt($ch, CURLOPT_URL, $analysisUrl);
  245. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
  246. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
  247. curl_setopt($ch, CURLOPT_POST, 1);
  248. curl_setopt($ch, CURLOPT_POSTFIELDS, $wordParams);
  249. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length: ' . strlen($wordParams)));
  250. $output = curl_exec($ch);
  251. $errnoNumber = curl_errno($ch);
  252. curl_close($ch);
  253. return $errnoNumber ? 'curl_errno:' . $errnoNumber : $output;
  254. }
  255. }