TemplateRender.php 35 KB

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