WordPushCommand.php 13 KB

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