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