TemplateRender.php 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. <?php
  2. namespace App\Http\Api;
  3. use Illuminate\Support\Facades\Cache;
  4. use Illuminate\Support\Facades\Log;
  5. use Illuminate\Support\Str;
  6. use Illuminate\Support\Facades\Http;
  7. use App\Models\DhammaTerm;
  8. use App\Models\PaliText;
  9. use App\Models\Channel;
  10. use App\Models\PageNumber;
  11. use App\Models\Discussion;
  12. use App\Http\Controllers\CorpusController;
  13. use App\Tools\RedisClusters;
  14. use App\Http\Api\ChannelApi;
  15. use App\Http\Api\MdRender;
  16. use App\Http\Api\PaliTextApi;
  17. class TemplateRender{
  18. protected $param = [];
  19. protected $mode = "read";
  20. protected $channel_id = [];
  21. protected $debug = [];
  22. protected $format = 'react';
  23. protected $studioId = null;
  24. protected $lang = 'en';
  25. protected $langFamily = 'en';
  26. /**
  27. * Create a new command instance.
  28. * string $mode 'read' | 'edit'
  29. * string $format 'react' | 'text' | 'tex' | 'unity'
  30. * @return void
  31. */
  32. public function __construct($param, $channelInfo, $mode,$format='react',$studioId,$debug=[])
  33. {
  34. $this->param = $param;
  35. foreach ($channelInfo as $value) {
  36. $this->channel_id[] = $value->uid;
  37. }
  38. $this->channelInfo = $channelInfo;
  39. $this->mode = $mode;
  40. $this->format = $format;
  41. $this->studioId = $studioId;
  42. $this->debug = $debug;
  43. if(count($this->channel_id)>0){
  44. $channelId = $this->channel_id[0];
  45. if(Str::isUuid($channelId)){
  46. $lang = Channel::where('uid',$channelId)->value('lang');
  47. if(!empty($lang)){
  48. $this->lang = $lang;
  49. $this->langFamily = explode('-',$lang)[0];
  50. }
  51. }
  52. }
  53. }
  54. private function info($message,$debug){
  55. if(in_array($debug,$this->debug)){
  56. Log::info($message);
  57. }
  58. }
  59. private function error($message,$debug){
  60. if(in_array($debug,$this->debug)){
  61. Log::error($message);
  62. }
  63. }
  64. public function render($tpl_name){
  65. switch ($tpl_name) {
  66. case 'term':
  67. # 术语
  68. $result = $this->render_term();
  69. break;
  70. case 'note':
  71. $result = $this->render_note();
  72. break;
  73. case 'sent':
  74. $result = $this->render_sent();
  75. break;
  76. case 'quote':
  77. $result = $this->render_quote();
  78. break;
  79. case 'ql':
  80. $result = $this->render_quote_link();
  81. break;
  82. case 'exercise':
  83. $result = $this->render_exercise();
  84. break;
  85. case 'article':
  86. $result = $this->render_article();
  87. break;
  88. case 'nissaya':
  89. $result = $this->render_nissaya();
  90. break;
  91. case 'mermaid':
  92. $result = $this->render_mermaid();
  93. break;
  94. case 'qa':
  95. $result = $this->render_qa();
  96. break;
  97. case 'v':
  98. $result = $this->render_video();
  99. break;
  100. case 'g':
  101. $result = $this->render_grammar_lookup();
  102. break;
  103. default:
  104. # code...
  105. $result = [
  106. 'props'=>base64_encode(\json_encode([])),
  107. 'html'=>'',
  108. 'tag'=>'span',
  109. 'tpl'=>'unknown',
  110. ];
  111. break;
  112. }
  113. return $result;
  114. }
  115. public function getTermProps($word,$tag=null,$channel=null){
  116. if($channel && !empty($channel)){
  117. $channelId = $channel;
  118. }else{
  119. if(count($this->channel_id)>0){
  120. $channelId = $this->channel_id[0];
  121. }else{
  122. $channelId = null;
  123. }
  124. }
  125. if(count($this->channelInfo)===0){
  126. Log::error('channel is null');
  127. $output = [
  128. "word" => $word,
  129. 'innerHtml' => '',
  130. ];
  131. return $output;
  132. }
  133. $channelInfo = $this->channelInfo[0];
  134. if(Str::isUuid($channelId)){
  135. $lang = Channel::where('uid',$channelId)->value('lang');
  136. if(!empty($lang)){
  137. $langFamily = explode('-',$lang)[0];
  138. }else{
  139. $langFamily = 'zh';
  140. }
  141. $this->info("term:{$word} 先查属于这个channel 的",'term');
  142. $this->info('channel id'.$channelId,'term');
  143. $table = DhammaTerm::where("word",$word)
  144. ->where('channal',$channelId);
  145. if($tag && !empty($tag)){
  146. $table = $table->where('tag',$tag);
  147. }
  148. $tplParam = $table->orderBy('updated_at','desc')
  149. ->first();
  150. $studioId = $channelInfo->owner_uid;
  151. }else{
  152. $tplParam = false;
  153. $lang = '';
  154. $langFamily = '';
  155. $studioId = $this->studioId;
  156. }
  157. if(!$tplParam){
  158. if(Str::isUuid($studioId)){
  159. /**
  160. * 没有,再查这个studio的
  161. * 按照语言过滤
  162. * 完全匹配的优先
  163. * 语族匹配也行
  164. */
  165. $this->info("没有-再查这个studio的",'term');
  166. $table = DhammaTerm::where("word",$word);
  167. if(!empty($tag)){
  168. $table = $table->where('tag',$tag);
  169. }
  170. $termsInStudio = $table->where('owner',$channelInfo->owner_uid)
  171. ->orderBy('updated_at','desc')
  172. ->get();
  173. if(count($termsInStudio)>0){
  174. $list = array();
  175. foreach ($termsInStudio as $key=>$term) {
  176. if(empty($term->channal)){
  177. if($term->language===$lang){
  178. $list[$term->guid]=2;
  179. }else if(strpos($term->language,$langFamily) !== false){
  180. $list[$term->guid]=1;
  181. }
  182. }
  183. }
  184. if(count($list)>0){
  185. arsort($list);
  186. foreach ($list as $key => $one) {
  187. foreach ($termsInStudio as $term) {
  188. if($term->guid===$key){
  189. $tplParam = $term;
  190. break;
  191. }
  192. }
  193. break;
  194. }
  195. }
  196. }
  197. }
  198. }
  199. if(!$tplParam){
  200. $this->info("没有,再查社区",'term');
  201. $community_channel = ChannelApi::getSysChannel("_community_term_zh-hans_");
  202. $table = DhammaTerm::where("word",$word);
  203. if(!empty($tag)){
  204. $table = $table->where('tag',$tag);
  205. }
  206. $tplParam = $table->where('channal',$community_channel)
  207. ->first();
  208. if($tplParam){
  209. $isCommunity = true;
  210. }else{
  211. $this->info("查社区没有",'term');
  212. }
  213. }
  214. $output = [
  215. "word" => $word,
  216. "parentChannelId" => $channelId,
  217. "parentStudioId" => $channelInfo->owner_uid,
  218. ];
  219. $innerString = $output["word"];
  220. if($tplParam){
  221. $output["id"] = $tplParam->guid;
  222. $output["meaning"] = $tplParam->meaning;
  223. $output["channel"] = $tplParam->channal;
  224. if(isset($isCommunity)){
  225. $output["isCommunity"] = true;
  226. }
  227. $innerString = "{$output["meaning"]}({$output["word"]})";
  228. if(!empty($tplParam->other_meaning)){
  229. $output["meaning2"] = $tplParam->other_meaning;
  230. }
  231. }
  232. $output['innerHtml'] = $innerString;
  233. return $output;
  234. }
  235. private function render_term(){
  236. $word = $this->get_param($this->param,"word",1);
  237. $props = $this->getTermProps($word,'');
  238. //$key = "/term/{$channelId}/{$word}";
  239. $output = $props['word'];
  240. switch ($this->format) {
  241. case 'react':
  242. $output=[
  243. 'props'=>base64_encode(\json_encode($props)),
  244. 'html'=>$props['innerHtml'],
  245. 'tag'=>'span',
  246. 'tpl'=>'term',
  247. ];
  248. break;
  249. case 'unity':
  250. $output=[
  251. 'props'=>base64_encode(\json_encode($props)),
  252. 'tpl'=>'term',
  253. ];
  254. break;
  255. case 'html':
  256. if(isset($props["meaning"])){
  257. $key = 'term-'.$props["word"];
  258. $termHead = "<a href='#'>".$props['meaning']."</a>";
  259. if(isset($GLOBALS[$key])){
  260. $output = $termHead;
  261. }else{
  262. $GLOBALS[$key] = 1;
  263. $output = $termHead.'(<em>'.$props["word"].'</em>)';
  264. }
  265. }else{
  266. $output = $props["word"];
  267. }
  268. break;
  269. case 'text':
  270. if(isset($props["meaning"])){
  271. $key = 'term-'.$props["word"];
  272. if(isset($GLOBALS[$key])){
  273. $output = $props["meaning"];
  274. }else{
  275. $GLOBALS[$key] = 1;
  276. $output = $props["meaning"].'('.$props["word"].')';
  277. }
  278. }else{
  279. $output = $props["word"];
  280. }
  281. break;
  282. case 'tex':
  283. if(isset($props["meaning"])){
  284. $key = 'term-'.$props["word"];
  285. if(isset($GLOBALS[$key])){
  286. $output = $props["meaning"];
  287. }else{
  288. $GLOBALS[$key] = 1;
  289. $output = $props["meaning"].'('.$props["word"].')';
  290. }
  291. }else{
  292. $output = $props["word"];
  293. }
  294. break;
  295. case 'simple':
  296. if(isset($props["meaning"])){
  297. $output = $props["meaning"];
  298. }else{
  299. $output = $props["word"];
  300. }
  301. break;
  302. default:
  303. if(isset($props["meaning"])){
  304. $output = $props["meaning"];
  305. }else{
  306. $output = $props["word"];
  307. }
  308. break;
  309. }
  310. return $output;
  311. }
  312. private function render_note(){
  313. $note = $this->get_param($this->param,"text",1);
  314. $trigger = $this->get_param($this->param,"trigger",2);
  315. $props = ["note" => $note ];
  316. $innerString = "";
  317. if(!empty($trigger)){
  318. $props["trigger"] = $trigger;
  319. $innerString = $props["trigger"];
  320. }
  321. if($this->format==='unity'){
  322. $props["note"] = MdRender::render($props["note"],
  323. $this->channel_id,
  324. null,
  325. 'read',
  326. 'translation',
  327. 'markdown',
  328. 'unity'
  329. );
  330. }
  331. $output = $note;
  332. switch ($this->format) {
  333. case 'react':
  334. $output=[
  335. 'props'=>base64_encode(\json_encode($props)),
  336. 'html'=>$innerString,
  337. 'tag'=>'span',
  338. 'tpl'=>'note',
  339. ];
  340. break;
  341. case 'unity':
  342. $output=[
  343. 'props'=>base64_encode(\json_encode($props)),
  344. 'tpl'=>'note',
  345. ];
  346. break;
  347. case 'html':
  348. if(isset($GLOBALS['note_sn'])){
  349. $GLOBALS['note_sn']++;
  350. }else{
  351. $GLOBALS['note_sn'] = 1;
  352. $GLOBALS['note'] = array();
  353. }
  354. $GLOBALS['note'][] = [
  355. 'sn' => 1,
  356. 'trigger' => $trigger,
  357. 'content' => MdRender::render($props["note"],
  358. $this->channel_id,
  359. null,
  360. 'read',
  361. 'translation',
  362. 'markdown',
  363. 'html'
  364. ),
  365. ];
  366. $link="<a href='#footnote-".$GLOBALS['note_sn']."' name='note-".$GLOBALS['note_sn']."'>";
  367. if(empty($trigger)){
  368. $output = $link. "<sup>[" . $GLOBALS['note_sn'] . "]</sup></a>";
  369. }else{
  370. $output = $link . $trigger . "</a>";
  371. }
  372. break;
  373. case 'text':
  374. $output = $trigger;
  375. break;
  376. case 'tex':
  377. $output = $trigger;
  378. break;
  379. case 'simple':
  380. $output = '';
  381. break;
  382. default:
  383. $output = '';
  384. break;
  385. }
  386. return $output;
  387. }
  388. private function render_nissaya(){
  389. $pali = $this->get_param($this->param,"pali",1);
  390. $meaning = $this->get_param($this->param,"meaning",2);
  391. $innerString = "";
  392. $props = [
  393. "pali" => $pali,
  394. "meaning" => $meaning,
  395. ];
  396. switch ($this->format) {
  397. case 'react':
  398. $output = [
  399. 'props'=>base64_encode(\json_encode($props)),
  400. 'html'=>$innerString,
  401. 'tag'=>'span',
  402. 'tpl'=>'nissaya',
  403. ];
  404. break;
  405. case 'unity':
  406. $output = [
  407. 'props'=>base64_encode(\json_encode($props)),
  408. 'tpl'=>'nissaya',
  409. ];
  410. break;
  411. case 'text':
  412. $output = $pali.'၊'.$meaning;
  413. break;
  414. case 'tex':
  415. $output = $pali.'၊'.$meaning;
  416. break;
  417. case 'simple':
  418. $output = $pali.'၊'.$meaning;
  419. break;
  420. default:
  421. $output = $pali.'၊'.$meaning;
  422. break;
  423. }
  424. return $output;
  425. }
  426. private function render_exercise(){
  427. $id = $this->get_param($this->param,"id",1);
  428. $title = $this->get_param($this->param,"title",1);
  429. $props = [
  430. "id" => $id,
  431. "title" => $title,
  432. "channel" => $this->channel_id[0],
  433. ];
  434. switch ($this->format) {
  435. case 'react':
  436. $output = [
  437. 'props'=>base64_encode(\json_encode($props)),
  438. 'html'=>"",
  439. 'tag'=>'span',
  440. 'tpl'=>'exercise',
  441. ];
  442. break;
  443. case 'unity':
  444. $output = [
  445. 'props'=>base64_encode(\json_encode($props)),
  446. 'tpl'=>'exercise',
  447. ];
  448. break;
  449. case 'text':
  450. $output = $title;
  451. break;
  452. case 'tex':
  453. $output = $title;
  454. break;
  455. case 'simple':
  456. $output = $title;
  457. break;
  458. default:
  459. $output = '';
  460. break;
  461. }
  462. return $output;
  463. }
  464. private function render_article(){
  465. $type = $this->get_param($this->param,"type",1);
  466. $id = $this->get_param($this->param,"id",2);
  467. $title = $this->get_param($this->param,"title",3);
  468. $channel = $this->get_param($this->param,"channel",4,$this->channel_id[0]);
  469. $style = $this->get_param($this->param,"style",5);
  470. $book = $this->get_param($this->param,"book",6);
  471. $paragraphs = $this->get_param($this->param,"paragraphs",7);
  472. $props = [
  473. "type" => $type,
  474. "id" => $id,
  475. "channel" => $channel,
  476. 'style' => $style,
  477. ];
  478. if(!empty($title)){
  479. $props['title'] = $title;
  480. }
  481. if(!empty($book)){
  482. $props['book'] = $book;
  483. }
  484. if(!empty($paragraphs)){
  485. $props['paragraphs'] = $paragraphs;
  486. }
  487. switch ($this->format) {
  488. case 'react':
  489. $output = [
  490. 'props'=>base64_encode(\json_encode($props)),
  491. 'html'=>"",
  492. 'text'=>$title,
  493. 'tag'=>'span',
  494. 'tpl'=>'article',
  495. ];
  496. break;
  497. case 'unity':
  498. $output = [
  499. 'props'=>base64_encode(\json_encode($props)),
  500. 'tpl'=>'article',
  501. ];
  502. break;
  503. case 'text':
  504. $output = $title;
  505. break;
  506. case 'tex':
  507. $output = $title;
  508. break;
  509. case 'simple':
  510. $output = $title;
  511. break;
  512. default:
  513. $output = '';
  514. break;
  515. }
  516. return $output;
  517. }
  518. private function render_quote(){
  519. $paraId = $this->get_param($this->param,"para",1);
  520. $channelId = $this->channel_id[0];
  521. $props = RedisClusters::remember("/quote/{$channelId}/{$paraId}",
  522. config('mint.cache.expire'),
  523. function() use($paraId,$channelId){
  524. $para = \explode('-',$paraId);
  525. $output = [
  526. "paraId" => $paraId,
  527. "channel" => $channelId,
  528. "innerString" => $paraId,
  529. ];
  530. if(count($para)<2){
  531. return $output;
  532. }
  533. $PaliText = PaliText::where("book",$para[0])
  534. ->where("paragraph",$para[1])
  535. ->select(['toc','path'])
  536. ->first();
  537. if($PaliText){
  538. $output["pali"] = $PaliText->toc;
  539. $output["paliPath"] = \json_decode($PaliText->path);
  540. $output["innerString"]= $PaliText->toc;
  541. }
  542. return $output;
  543. });
  544. switch ($this->format) {
  545. case 'react':
  546. $output = [
  547. 'props'=>base64_encode(\json_encode($props)),
  548. 'html'=>$props["innerString"],
  549. 'tag'=>'span',
  550. 'tpl'=>'quote',
  551. ];
  552. break;
  553. case 'unity':
  554. $output = [
  555. 'props'=>base64_encode(\json_encode($props)),
  556. 'tpl'=>'quote',
  557. ];
  558. break;
  559. case 'text':
  560. $output = $props["innerString"];
  561. break;
  562. case 'tex':
  563. $output = $props["innerString"];
  564. break;
  565. case 'simple':
  566. $output = $props["innerString"];
  567. break;
  568. default:
  569. $output = $props["innerString"];
  570. break;
  571. }
  572. return $output;
  573. }
  574. private function render_quote_link(){
  575. $type = $this->get_param($this->param,"type",1);
  576. $title = $this->get_param($this->param,"title",6,'');
  577. $bookName = $this->get_param($this->param,"bookname",2,'');
  578. $volume = $this->get_param($this->param,"volume",3);
  579. $page = $this->get_param($this->param,"page",4,'');
  580. $style = $this->get_param($this->param,"style",5,'modal');
  581. $book = $this->get_param($this->param,"book",7,false);
  582. $para = $this->get_param($this->param,"para",8,false);
  583. $props = [
  584. 'type' => $type,
  585. 'style' => $style,
  586. 'found' => true,
  587. ];
  588. if(!empty($bookName) && $volume !== '' && !empty($page)){
  589. $props['bookName'] = $bookName;
  590. $props['volume'] = (int)$volume;
  591. $props['page'] = $page;
  592. $props['found'] = true;
  593. }else if($book && $para){
  594. /**
  595. * 没有指定书名,根据book para 查询
  596. */
  597. if($type==='c'){
  598. //按照章节名称显示
  599. $path = PaliTextApi::getChapterPath($book,$para);
  600. if($path){
  601. $path = json_decode($path,true);
  602. }
  603. if($path && is_array($path) && count($path)>2){
  604. $props['bookName'] = strtolower($path[0]['title']) ;
  605. $props['chapter'] = strtolower(end($path)['title']);
  606. $props['found'] = true;
  607. }else{
  608. $props['found'] = false;
  609. }
  610. }else{
  611. $pageInfo = $this->pageInfoByPara($type,$book,$para);
  612. if($pageInfo['found']){
  613. $props['bookName'] = $pageInfo['bookName'];
  614. $props['volume'] = $pageInfo['volume'];
  615. $props['page'] = $pageInfo['page'];
  616. $props['found'] = true;
  617. }else{
  618. $props['found'] = false;
  619. }
  620. }
  621. }else if($title){
  622. //没有书号用title查询
  623. $tmpTitle = explode('။',$title);
  624. if(count($tmpTitle)>1){
  625. $tmpBookTitle = $tmpTitle[0];
  626. $tmpBookPage = $tmpTitle[1];
  627. $tmpBookPage = (int)str_replace(
  628. ['၁','၂','၃','၄','၅','၆','၇','၈','၉','၀'],
  629. ['1','2','3','4','5','6','7','8','9','0'],
  630. $tmpBookPage);
  631. $found_key = array_search($tmpBookTitle, array_column(BookTitle::my(), 'title2'));
  632. if($found_key !== false){
  633. $props['bookName'] = BookTitle::my()[$found_key]['bookname'];
  634. $props['volume'] = BookTitle::my()[$found_key]['volume'];
  635. $props['page'] = $tmpBookPage;
  636. if(!empty($props['bookName'])){
  637. $found_title = array_search($props['bookName'], array_column(BookTitle::my(), 'bookname'));
  638. if($found_title === false){
  639. $props['found'] = false;
  640. }
  641. }
  642. }else{
  643. //没找到,返回术语和页码
  644. $props['found'] = false;
  645. $props['bookName'] = $tmpBookTitle;
  646. $props['page'] = $tmpBookPage;
  647. $props['volume'] = 0;
  648. }
  649. }
  650. }else{
  651. $props['found'] = false;
  652. }
  653. if($book && $para){
  654. $props['book'] = $book;
  655. $props['para'] = $para;
  656. }
  657. if($title){
  658. $props['title'] = $title;
  659. }
  660. $text = '';
  661. if(isset($props['bookName'])){
  662. $searchField = '';
  663. switch ($type) {
  664. case 'm':
  665. $searchField = 'm_title';
  666. break;
  667. case 'p':
  668. $searchField = 'p_title';
  669. break;
  670. }
  671. $found_title = array_search($props['bookName'], array_column(BookTitle::get(), $searchField));
  672. if($found_title === false){
  673. $props['found'] = false;
  674. }
  675. $term = $this->getTermProps($props['bookName'],':quote:');
  676. $props['term'] = $term;
  677. if(isset($term['id'])){
  678. $props['bookNameLocal'] = $term['meaning'];
  679. $text .= $term['meaning'];
  680. }else{
  681. $text .= $bookName;
  682. }
  683. }
  684. if(isset($props['volume']) && isset($props['page'])){
  685. $text .= " {$volume}.{$page}";
  686. }
  687. switch ($this->format) {
  688. case 'react':
  689. $output = [
  690. 'props'=>base64_encode(\json_encode($props)),
  691. 'html'=>'',
  692. 'tag'=>'span',
  693. 'tpl'=>'quote-link',
  694. ];
  695. break;
  696. case 'unity':
  697. $output = [
  698. 'props'=>base64_encode(\json_encode($props)),
  699. 'tpl'=>'quote-link',
  700. ];
  701. break;
  702. default:
  703. $output = $text;
  704. break;
  705. }
  706. return $output;
  707. }
  708. private function pageInfoByPara($type,$book,$para){
  709. $output = array();
  710. $pageInfo = PageNumber::where('type',strtoupper($type))
  711. ->where('book',$book)
  712. ->where('paragraph','<=',$para)
  713. ->orderBy('paragraph','desc')
  714. ->first();
  715. if($pageInfo){
  716. foreach (BookTitle::get() as $value) {
  717. if($value['id']===$pageInfo->pcd_book_id){
  718. switch (strtoupper($type)) {
  719. case 'M':
  720. $key = 'm_title';
  721. break;
  722. case 'P':
  723. $key = 'p_title';
  724. break;
  725. case 'V':
  726. $key = 'v_title';
  727. break;
  728. default:
  729. $key = 'term';
  730. break;
  731. }
  732. $output['bookName'] = $value[$key];
  733. break;
  734. }
  735. }
  736. $output['volume'] = $pageInfo->volume;
  737. $output['page'] = $pageInfo->page;
  738. $output['found'] = true;
  739. }else{
  740. $output['found'] = false;
  741. }
  742. return $output;
  743. }
  744. private function render_sent(){
  745. $sid = $this->get_param($this->param,"sid",1);
  746. $channel = $this->get_param($this->param,"channel",2);
  747. if(!empty($channel)){
  748. $channels = explode(',',$channel);
  749. }else{
  750. $channels = $this->channel_id;
  751. }
  752. $sentInfo = explode('@',trim($sid));
  753. $sentId = $sentInfo[0];
  754. if(isset($sentInfo[1])){
  755. $channels = [$sentInfo[1]];
  756. }
  757. $Sent = new CorpusController();
  758. $props = $Sent->getSentTpl($sentId,$channels,
  759. $this->mode,true,
  760. $this->format);
  761. if($props === false){
  762. $props['error']="句子模版渲染错误。句子参数个数不符。应该是四个。";
  763. }
  764. if($this->mode==='read'){
  765. $tpl = "sentread";
  766. }else{
  767. $tpl = "sentedit";
  768. }
  769. switch ($this->format) {
  770. case 'react':
  771. $output = [
  772. 'props'=>base64_encode(\json_encode($props)),
  773. 'html'=>"",
  774. 'tag'=>'span',
  775. 'tpl'=>$tpl,
  776. ];
  777. break;
  778. case 'unity':
  779. $output = [
  780. 'props'=>base64_encode(\json_encode($props)),
  781. 'tpl'=>$tpl,
  782. ];
  783. break;
  784. case 'text':
  785. $output = '';
  786. if(isset($props['translation']) && is_array($props['translation'])){
  787. foreach ($props['translation'] as $key => $value) {
  788. $output .= $value['html'];
  789. }
  790. }
  791. break;
  792. case 'html':
  793. $output = '';
  794. if(isset($props['translation']) && is_array($props['translation'])){
  795. foreach ($props['translation'] as $key => $value) {
  796. $output .= '<span class="sentence">'.$value['html'].'</span>';
  797. }
  798. }
  799. break;
  800. case 'tex':
  801. $output = '';
  802. if(isset($props['translation']) && is_array($props['translation'])){
  803. foreach ($props['translation'] as $key => $value) {
  804. $output .= $value['html'];
  805. }
  806. }
  807. break;
  808. case 'simple':
  809. $output = '';
  810. if(isset($props['translation']) &&
  811. is_array($props['translation']) &&
  812. count($props['translation']) > 0
  813. ){
  814. $sentences = $props['translation'];
  815. foreach ($sentences as $key => $value) {
  816. $output .= $value['html'];
  817. }
  818. }
  819. if(empty($output)){
  820. if(isset($props['origin']) &&
  821. is_array($props['origin']) &&
  822. count($props['origin']) > 0
  823. ){
  824. $sentences = $props['origin'];
  825. foreach ($sentences as $key => $value) {
  826. $output .= $value['html'];
  827. }
  828. }
  829. }
  830. break;
  831. default:
  832. $output = '';
  833. break;
  834. }
  835. return $output;
  836. }
  837. private function render_mermaid(){
  838. $text = json_decode(base64_decode($this->get_param($this->param,"text",1)));
  839. $props = ["text" => implode("\n",$text)];
  840. switch ($this->format) {
  841. case 'react':
  842. $output = [
  843. 'props'=>base64_encode(\json_encode($props)),
  844. 'html'=>"mermaid",
  845. 'tag'=>'div',
  846. 'tpl'=>'mermaid',
  847. ];
  848. break;
  849. case 'unity':
  850. $output = [
  851. 'props'=>base64_encode(\json_encode($props)),
  852. 'tpl'=>'mermaid',
  853. ];
  854. break;
  855. case 'text':
  856. $output = 'mermaid';
  857. break;
  858. case 'tex':
  859. $output = 'mermaid';
  860. break;
  861. case 'simple':
  862. $output = 'mermaid';
  863. break;
  864. default:
  865. $output = 'mermaid';
  866. break;
  867. }
  868. return $output;
  869. }
  870. private function render_qa(){
  871. $id = $this->get_param($this->param,"id",1);
  872. $style = $this->get_param($this->param,"style",2);
  873. $props = [
  874. "type" => 'qa',
  875. "id" => $id,
  876. 'title' => '',
  877. 'style' => $style,
  878. ];
  879. $qa = Discussion::where('id',$id)->first();
  880. if($qa){
  881. $props['title'] = $qa->title;
  882. $props['resId'] = $qa->res_id;
  883. $props['resType'] = $qa->res_type;
  884. }
  885. switch ($this->format) {
  886. case 'react':
  887. $output = [
  888. 'props'=>base64_encode(\json_encode($props)),
  889. 'html'=>"",
  890. 'text'=>$props['title'],
  891. 'tag'=>'div',
  892. 'tpl'=>'qa',
  893. ];
  894. break;
  895. case 'unity':
  896. $output = [
  897. 'props'=>base64_encode(\json_encode($props)),
  898. 'tpl'=>'qa',
  899. ];
  900. break;
  901. default:
  902. $output = $props['title'];
  903. break;
  904. }
  905. return $output;
  906. }
  907. private function render_grammar_lookup(){
  908. $word = $this->get_param($this->param,"word",1);
  909. $props = ['word' => $word];
  910. $localTermChannel = ChannelApi::getSysChannel(
  911. "_System_Grammar_Term_".strtolower($this->lang)."_",
  912. "_System_Grammar_Term_en_"
  913. );
  914. $term = $this->getTermProps($word,null,$localTermChannel);
  915. $props['term'] = $term;
  916. switch ($this->format) {
  917. case 'react':
  918. $output = [
  919. 'props'=>base64_encode(\json_encode($props)),
  920. 'html'=>"",
  921. 'text'=>$props['word'],
  922. 'tag'=>'span',
  923. 'tpl'=>'grammar',
  924. ];
  925. break;
  926. case 'unity':
  927. $output = [
  928. 'props'=>base64_encode(\json_encode($props)),
  929. 'tpl'=>'grammar',
  930. ];
  931. break;
  932. default:
  933. $output = $props['word'];
  934. break;
  935. }
  936. return $output;
  937. }
  938. private function render_video(){
  939. $url = $this->get_param($this->param,"url",1);
  940. $style = $this->get_param($this->param,"style",2,'modal');
  941. $title = $this->get_param($this->param,"title",3);
  942. $props = [
  943. "url" => $url,
  944. 'title' => $title,
  945. 'style' => $style,
  946. ];
  947. switch ($this->format) {
  948. case 'react':
  949. $output = [
  950. 'props'=>base64_encode(\json_encode($props)),
  951. 'html'=>"",
  952. 'text'=>$props['title'],
  953. 'tag'=>'span',
  954. 'tpl'=>'video',
  955. ];
  956. break;
  957. case 'unity':
  958. $output = [
  959. 'props'=>base64_encode(\json_encode($props)),
  960. 'tpl'=>'video',
  961. ];
  962. break;
  963. default:
  964. $output = $props['title'];
  965. break;
  966. }
  967. return $output;
  968. }
  969. private function get_param(array $param,string $name,int $id,string $default=''){
  970. if(isset($param[$name])){
  971. return trim($param[$name]);
  972. }else if(isset($param["{$id}"])){
  973. return trim($param["{$id}"]);
  974. }else{
  975. return $default;
  976. }
  977. }
  978. }