TemplateRender.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  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\Http\Controllers\CorpusController;
  12. use App\Tools\RedisClusters;
  13. use App\Http\Api\ChannelApi;
  14. use App\Http\Api\MdRender;
  15. class TemplateRender{
  16. protected $param = [];
  17. protected $mode = "read";
  18. protected $channel_id = [];
  19. protected $debug = [];
  20. protected $format = 'react';
  21. protected $studioId = null;
  22. /**
  23. * Create a new command instance.
  24. * string $mode 'read' | 'edit'
  25. * string $format 'react' | 'text' | 'tex' | 'unity'
  26. * @return void
  27. */
  28. public function __construct($param, $channelInfo, $mode,$format='react',$studioId,$debug=[])
  29. {
  30. $this->param = $param;
  31. foreach ($channelInfo as $value) {
  32. $this->channel_id[] = $value->uid;
  33. }
  34. $this->channelInfo = $channelInfo;
  35. $this->mode = $mode;
  36. $this->format = $format;
  37. $this->studioId = $studioId;
  38. $this->debug = $debug;
  39. }
  40. private function info($message,$debug){
  41. if(in_array($debug,$this->debug)){
  42. Log::info($message);
  43. }
  44. }
  45. private function error($message,$debug){
  46. if(in_array($debug,$this->debug)){
  47. Log::error($message);
  48. }
  49. }
  50. public function render($tpl_name){
  51. switch ($tpl_name) {
  52. case 'term':
  53. # 术语
  54. $result = $this->render_term();
  55. break;
  56. case 'note':
  57. $result = $this->render_note();
  58. break;
  59. case 'sent':
  60. $result = $this->render_sent();
  61. break;
  62. case 'quote':
  63. $result = $this->render_quote();
  64. break;
  65. case 'ql':
  66. $result = $this->render_quote_link();
  67. break;
  68. case 'exercise':
  69. $result = $this->render_exercise();
  70. break;
  71. case 'article':
  72. $result = $this->render_article();
  73. break;
  74. case 'nissaya':
  75. $result = $this->render_nissaya();
  76. break;
  77. case 'mermaid':
  78. $result = $this->render_mermaid();
  79. break;
  80. default:
  81. # code...
  82. $result = [
  83. 'props'=>base64_encode(\json_encode([])),
  84. 'html'=>'',
  85. 'tag'=>'span',
  86. 'tpl'=>'unknown',
  87. ];
  88. break;
  89. }
  90. return $result;
  91. }
  92. public function getTermProps($word,$channelId,$channelInfo){
  93. if(Str::isUuid($channelId)){
  94. $lang = Channel::where('uid',$channelId)->value('lang');
  95. if(!empty($lang)){
  96. $langFamily = explode('-',$lang)[0];
  97. }else{
  98. $langFamily = 'zh';
  99. }
  100. $this->info("term:{$word} 先查属于这个channel 的",'term');
  101. $this->info('channel id'.$channelId,'term');
  102. $tplParam = DhammaTerm::where("word",$word)
  103. ->where('channal',$channelId)
  104. ->orderBy('updated_at','desc')
  105. ->first();
  106. $studioId = $channelInfo->owner_uid;
  107. }else{
  108. $tplParam = false;
  109. $lang = '';
  110. $langFamily = '';
  111. $studioId = $this->studioId;
  112. }
  113. if(!$tplParam){
  114. if(Str::isUuid($studioId)){
  115. /**
  116. * 没有,再查这个studio的
  117. * 按照语言过滤
  118. * 完全匹配的优先
  119. * 语族匹配也行
  120. */
  121. $this->info("没有-再查这个studio的",'term');
  122. $termsInStudio = DhammaTerm::where("word",$word)
  123. ->where('owner',$channelInfo->owner_uid)
  124. ->orderBy('updated_at','desc')
  125. ->get();
  126. if(count($termsInStudio)>0){
  127. $list = array();
  128. foreach ($termsInStudio as $key=>$term) {
  129. if(empty($term->channal)){
  130. if($term->language===$lang){
  131. $list[$term->guid]=2;
  132. }else if(strpos($term->language,$langFamily) !== false){
  133. $list[$term->guid]=1;
  134. }
  135. }
  136. }
  137. if(count($list)>0){
  138. arsort($list);
  139. foreach ($list as $key => $one) {
  140. foreach ($termsInStudio as $term) {
  141. if($term->guid===$key){
  142. $tplParam = $term;
  143. break;
  144. }
  145. }
  146. break;
  147. }
  148. }
  149. }
  150. }
  151. }
  152. if(!$tplParam){
  153. $this->info("没有,再查社区",'term');
  154. $community_channel = ChannelApi::getSysChannel("_community_term_zh-hans_");
  155. $tplParam = DhammaTerm::where("word",$word)
  156. ->where('channal',$community_channel)
  157. ->first();
  158. if($tplParam){
  159. $isCommunity = true;
  160. }else{
  161. $this->info("查社区没有",'term');
  162. }
  163. }
  164. $output = [
  165. "word" => $word,
  166. "parentChannelId" => $channelId,
  167. "parentStudioId" => $channelInfo->owner_uid,
  168. ];
  169. $innerString = $output["word"];
  170. if($tplParam){
  171. $output["id"] = $tplParam->guid;
  172. $output["meaning"] = $tplParam->meaning;
  173. $output["channel"] = $tplParam->channal;
  174. if(isset($isCommunity)){
  175. $output["isCommunity"] = true;
  176. }
  177. $innerString = "{$output["meaning"]}({$output["word"]})";
  178. if(!empty($tplParam->other_meaning)){
  179. $output["meaning2"] = $tplParam->other_meaning;
  180. }
  181. }
  182. $output['innerHtml'] = $innerString;
  183. return $output;
  184. }
  185. private function render_term(){
  186. $word = $this->get_param($this->param,"word",1);
  187. if(count($this->channel_id)>0){
  188. $channelId = $this->channel_id[0];
  189. }else{
  190. $channelId = null;
  191. }
  192. $channelInfo = $this->channelInfo[0];
  193. $key = "/term/{$channelId}/{$word}";
  194. $props = $this->getTermProps($word,$channelId,$channelInfo);
  195. $output = $props['word'];
  196. switch ($this->format) {
  197. case 'react':
  198. $output=[
  199. 'props'=>base64_encode(\json_encode($props)),
  200. 'html'=>$props['innerHtml'],
  201. 'tag'=>'span',
  202. 'tpl'=>'term',
  203. ];
  204. break;
  205. case 'unity':
  206. $output=[
  207. 'props'=>base64_encode(\json_encode($props)),
  208. 'tpl'=>'term',
  209. ];
  210. break;
  211. case 'html':
  212. if(isset($props["meaning"])){
  213. $key = 'term-'.$props["word"];
  214. $termHead = "<a href='#'>".$props['meaning']."</a>";
  215. if(isset($GLOBALS[$key])){
  216. $output = $termHead;
  217. }else{
  218. $GLOBALS[$key] = 1;
  219. $output = $termHead.'(<em>'.$props["word"].'</em>)';
  220. }
  221. }else{
  222. $output = $props["word"];
  223. }
  224. break;
  225. case 'text':
  226. if(isset($props["meaning"])){
  227. $key = 'term-'.$props["word"];
  228. if(isset($GLOBALS[$key])){
  229. $output = $props["meaning"];
  230. }else{
  231. $GLOBALS[$key] = 1;
  232. $output = $props["meaning"].'('.$props["word"].')';
  233. }
  234. }else{
  235. $output = $props["word"];
  236. }
  237. break;
  238. case 'tex':
  239. if(isset($props["meaning"])){
  240. $key = 'term-'.$props["word"];
  241. if(isset($GLOBALS[$key])){
  242. $output = $props["meaning"];
  243. }else{
  244. $GLOBALS[$key] = 1;
  245. $output = $props["meaning"].'('.$props["word"].')';
  246. }
  247. }else{
  248. $output = $props["word"];
  249. }
  250. break;
  251. case 'simple':
  252. if(isset($props["meaning"])){
  253. $output = $props["meaning"];
  254. }else{
  255. $output = $props["word"];
  256. }
  257. break;
  258. default:
  259. if(isset($props["meaning"])){
  260. $output = $props["meaning"];
  261. }else{
  262. $output = $props["word"];
  263. }
  264. break;
  265. }
  266. return $output;
  267. }
  268. private function render_note(){
  269. $note = $this->get_param($this->param,"text",1);
  270. $trigger = $this->get_param($this->param,"trigger",2);
  271. $props = ["note" => $note ];
  272. $innerString = "";
  273. if(!empty($trigger)){
  274. $props["trigger"] = $trigger;
  275. $innerString = $props["trigger"];
  276. }
  277. if($this->format==='unity'){
  278. $props["note"] = MdRender::render($props["note"],
  279. $this->channel_id,
  280. null,
  281. 'read',
  282. 'translation',
  283. 'markdown',
  284. 'unity'
  285. );
  286. }
  287. $output = $note;
  288. switch ($this->format) {
  289. case 'react':
  290. $output=[
  291. 'props'=>base64_encode(\json_encode($props)),
  292. 'html'=>$innerString,
  293. 'tag'=>'span',
  294. 'tpl'=>'note',
  295. ];
  296. break;
  297. case 'unity':
  298. $output=[
  299. 'props'=>base64_encode(\json_encode($props)),
  300. 'tpl'=>'note',
  301. ];
  302. break;
  303. case 'html':
  304. if(isset($GLOBALS['note_sn'])){
  305. $GLOBALS['note_sn']++;
  306. }else{
  307. $GLOBALS['note_sn'] = 1;
  308. $GLOBALS['note'] = array();
  309. }
  310. $GLOBALS['note'][] = [
  311. 'sn' => 1,
  312. 'trigger' => $trigger,
  313. 'content' => MdRender::render($props["note"],
  314. $this->channel_id,
  315. null,
  316. 'read',
  317. 'translation',
  318. 'markdown',
  319. 'html'
  320. ),
  321. ];
  322. $link="<a href='#footnote-".$GLOBALS['note_sn']."' name='note-".$GLOBALS['note_sn']."'>";
  323. if(empty($trigger)){
  324. $output = $link. "<sup>[" . $GLOBALS['note_sn'] . "]</sup></a>";
  325. }else{
  326. $output = $link . $trigger . "</a>";
  327. }
  328. break;
  329. case 'text':
  330. $output = $trigger;
  331. break;
  332. case 'tex':
  333. $output = $trigger;
  334. break;
  335. case 'simple':
  336. $output = '';
  337. break;
  338. default:
  339. $output = '';
  340. break;
  341. }
  342. return $output;
  343. }
  344. private function render_nissaya(){
  345. $pali = $this->get_param($this->param,"pali",1);
  346. $meaning = $this->get_param($this->param,"meaning",2);
  347. $innerString = "";
  348. $props = [
  349. "pali" => $pali,
  350. "meaning" => $meaning,
  351. ];
  352. switch ($this->format) {
  353. case 'react':
  354. $output = [
  355. 'props'=>base64_encode(\json_encode($props)),
  356. 'html'=>$innerString,
  357. 'tag'=>'span',
  358. 'tpl'=>'nissaya',
  359. ];
  360. break;
  361. case 'unity':
  362. $output = [
  363. 'props'=>base64_encode(\json_encode($props)),
  364. 'tpl'=>'nissaya',
  365. ];
  366. break;
  367. case 'text':
  368. $output = $pali.'၊'.$meaning;
  369. break;
  370. case 'tex':
  371. $output = $pali.'၊'.$meaning;
  372. break;
  373. case 'simple':
  374. $output = $pali.'၊'.$meaning;
  375. break;
  376. default:
  377. $output = $pali.'၊'.$meaning;
  378. break;
  379. }
  380. return $output;
  381. }
  382. private function render_exercise(){
  383. $id = $this->get_param($this->param,"id",1);
  384. $title = $this->get_param($this->param,"title",1);
  385. $props = [
  386. "id" => $id,
  387. "title" => $title,
  388. "channel" => $this->channel_id[0],
  389. ];
  390. switch ($this->format) {
  391. case 'react':
  392. $output = [
  393. 'props'=>base64_encode(\json_encode($props)),
  394. 'html'=>"",
  395. 'tag'=>'span',
  396. 'tpl'=>'exercise',
  397. ];
  398. break;
  399. case 'unity':
  400. $output = [
  401. 'props'=>base64_encode(\json_encode($props)),
  402. 'tpl'=>'exercise',
  403. ];
  404. break;
  405. case 'text':
  406. $output = $title;
  407. break;
  408. case 'tex':
  409. $output = $title;
  410. break;
  411. case 'simple':
  412. $output = $title;
  413. break;
  414. default:
  415. $output = '';
  416. break;
  417. }
  418. return $output;
  419. }
  420. private function render_article(){
  421. $type = $this->get_param($this->param,"type",1);
  422. $id = $this->get_param($this->param,"id",2);
  423. $title = $this->get_param($this->param,"title",3);
  424. $channel = $this->get_param($this->param,"channel",4,$this->channel_id[0]);
  425. $style = $this->get_param($this->param,"style",5);
  426. $props = [
  427. "type" => $type,
  428. "id" => $id,
  429. "channel" => $channel,
  430. 'style' => $style,
  431. ];
  432. if(!empty($title)){
  433. $props['title'] = $title;
  434. }
  435. switch ($this->format) {
  436. case 'react':
  437. $output = [
  438. 'props'=>base64_encode(\json_encode($props)),
  439. 'html'=>"",
  440. 'text'=>$title,
  441. 'tag'=>'span',
  442. 'tpl'=>'article',
  443. ];
  444. break;
  445. case 'unity':
  446. $output = [
  447. 'props'=>base64_encode(\json_encode($props)),
  448. 'tpl'=>'article',
  449. ];
  450. break;
  451. case 'text':
  452. $output = $title;
  453. break;
  454. case 'tex':
  455. $output = $title;
  456. break;
  457. case 'simple':
  458. $output = $title;
  459. break;
  460. default:
  461. $output = '';
  462. break;
  463. }
  464. return $output;
  465. }
  466. private function render_quote(){
  467. $paraId = $this->get_param($this->param,"para",1);
  468. $channelId = $this->channel_id[0];
  469. $props = RedisClusters::remember("/quote/{$channelId}/{$paraId}",
  470. config('mint.cache.expire'),
  471. function() use($paraId,$channelId){
  472. $para = \explode('-',$paraId);
  473. $output = [
  474. "paraId" => $paraId,
  475. "channel" => $channelId,
  476. "innerString" => $paraId,
  477. ];
  478. if(count($para)<2){
  479. return $output;
  480. }
  481. $PaliText = PaliText::where("book",$para[0])
  482. ->where("paragraph",$para[1])
  483. ->select(['toc','path'])
  484. ->first();
  485. if($PaliText){
  486. $output["pali"] = $PaliText->toc;
  487. $output["paliPath"] = \json_decode($PaliText->path);
  488. $output["innerString"]= $PaliText->toc;
  489. }
  490. return $output;
  491. });
  492. switch ($this->format) {
  493. case 'react':
  494. $output = [
  495. 'props'=>base64_encode(\json_encode($props)),
  496. 'html'=>$props["innerString"],
  497. 'tag'=>'span',
  498. 'tpl'=>'quote',
  499. ];
  500. break;
  501. case 'unity':
  502. $output = [
  503. 'props'=>base64_encode(\json_encode($props)),
  504. 'tpl'=>'quote',
  505. ];
  506. break;
  507. case 'text':
  508. $output = $props["innerString"];
  509. break;
  510. case 'tex':
  511. $output = $props["innerString"];
  512. break;
  513. case 'simple':
  514. $output = $props["innerString"];
  515. break;
  516. default:
  517. $output = $props["innerString"];
  518. break;
  519. }
  520. return $output;
  521. }
  522. private function render_quote_link(){
  523. $type = $this->get_param($this->param,"type",1);
  524. $bookName = $this->get_param($this->param,"bookname",2,false);
  525. $volume = $this->get_param($this->param,"volume",3,false);
  526. $page = $this->get_param($this->param,"page",4,false);
  527. $style = $this->get_param($this->param,"style",5,'modal');
  528. $book = $this->get_param($this->param,"book",6,false);
  529. $para = $this->get_param($this->param,"para",7,false);
  530. if(!$bookName || !$volume || !$page){
  531. /**
  532. * 没有指定书名,根据book para 查询
  533. */
  534. if($book && $para){
  535. $pageInfo = PageNumber::where('type',strtoupper($type))
  536. ->where('book',$book)
  537. ->where('paragraph','<=',$para)
  538. ->orderBy('paragraph','desc')
  539. ->first();
  540. if(!$bookName){
  541. foreach (BookTitle::get() as $value) {
  542. if($value['id']===$pageInfo->pcd_book_id){
  543. switch (strtoupper($type)) {
  544. case 'M':
  545. $key = 'm_title';
  546. break;
  547. case 'P':
  548. $key = 'p_title';
  549. break;
  550. case 'V':
  551. $key = 'v_title';
  552. break;
  553. default:
  554. $key = 'term';
  555. break;
  556. }
  557. $bookName = $value[$key];
  558. }
  559. }
  560. }
  561. if(!$volume){
  562. $volume = $pageInfo->volume;
  563. }
  564. if(!$page){
  565. $page = $pageInfo->page;
  566. }
  567. }
  568. }
  569. $props = [
  570. 'type' => $type,
  571. 'bookName' => $bookName,
  572. 'volume' => $volume,
  573. 'page' => $page,
  574. 'style' => $style,
  575. ];
  576. if($book && $para){
  577. $props['book'] = $book;
  578. $props['para'] = $para;
  579. }
  580. //获取原文channel
  581. if(isset($this->channelInfo[0])){
  582. $lang = $this->channelInfo[0]->lang;
  583. }else{
  584. $lang = 'en';
  585. }
  586. if($lang==='zh'){
  587. $lang = 'zh-hans';
  588. }
  589. $termChannel = ChannelApi::getSysChannel("_System_Grammar_Term_{$lang}_");
  590. $bookNameLocal = DhammaTerm::where('channal',$termChannel)
  591. ->where('tag',':abbr:')
  592. ->where('word',$bookName)
  593. ->value('meaning');
  594. if($bookNameLocal){
  595. $props['bookNameLocal'] = $bookNameLocal;
  596. }
  597. $text = "{$bookNameLocal}. {$volume}. {$page}";
  598. switch ($this->format) {
  599. case 'react':
  600. $output = [
  601. 'props'=>base64_encode(\json_encode($props)),
  602. 'html'=>'',
  603. 'tag'=>'span',
  604. 'tpl'=>'quote-link',
  605. ];
  606. break;
  607. case 'unity':
  608. $output = [
  609. 'props'=>base64_encode(\json_encode($props)),
  610. 'tpl'=>'quote-link',
  611. ];
  612. break;
  613. default:
  614. $output = $text;
  615. break;
  616. }
  617. return $output;
  618. }
  619. private function render_sent(){
  620. $sid = $this->get_param($this->param,"sid",1);
  621. $channel = $this->get_param($this->param,"channel",2);
  622. if(!empty($channel)){
  623. $channels = explode(',',$channel);
  624. }else{
  625. $channels = $this->channel_id;
  626. }
  627. $sentInfo = explode('@',trim($sid));
  628. $sentId = $sentInfo[0];
  629. if(isset($sentInfo[1])){
  630. $channels = [$sentInfo[1]];
  631. }
  632. $Sent = new CorpusController();
  633. $props = $Sent->getSentTpl($sentId,$channels,
  634. $this->mode,true,
  635. $this->format);
  636. if($props === false){
  637. $props['error']="句子模版渲染错误。句子参数个数不符。应该是四个。";
  638. }
  639. if($this->mode==='read'){
  640. $tpl = "sentread";
  641. }else{
  642. $tpl = "sentedit";
  643. }
  644. switch ($this->format) {
  645. case 'react':
  646. $output = [
  647. 'props'=>base64_encode(\json_encode($props)),
  648. 'html'=>"",
  649. 'tag'=>'span',
  650. 'tpl'=>$tpl,
  651. ];
  652. break;
  653. case 'unity':
  654. $output = [
  655. 'props'=>base64_encode(\json_encode($props)),
  656. 'tpl'=>$tpl,
  657. ];
  658. break;
  659. case 'text':
  660. $output = '';
  661. if(isset($props['translation']) && is_array($props['translation'])){
  662. foreach ($props['translation'] as $key => $value) {
  663. $output .= $value['html'];
  664. }
  665. }
  666. break;
  667. case 'html':
  668. $output = '';
  669. if(isset($props['translation']) && is_array($props['translation'])){
  670. foreach ($props['translation'] as $key => $value) {
  671. $output .= '<span class="sentence">'.$value['html'].'</span>';
  672. }
  673. }
  674. break;
  675. case 'tex':
  676. $output = '';
  677. if(isset($props['translation']) && is_array($props['translation'])){
  678. foreach ($props['translation'] as $key => $value) {
  679. $output .= $value['html'];
  680. }
  681. }
  682. break;
  683. case 'simple':
  684. $output = '';
  685. if(isset($props['translation']) &&
  686. is_array($props['translation']) &&
  687. count($props['translation']) > 0
  688. ){
  689. $sentences = $props['translation'];
  690. foreach ($sentences as $key => $value) {
  691. $output .= $value['html'];
  692. }
  693. }
  694. if(empty($output)){
  695. if(isset($props['origin']) &&
  696. is_array($props['origin']) &&
  697. count($props['origin']) > 0
  698. ){
  699. $sentences = $props['origin'];
  700. foreach ($sentences as $key => $value) {
  701. $output .= $value['html'];
  702. }
  703. }
  704. }
  705. break;
  706. default:
  707. $output = '';
  708. break;
  709. }
  710. return $output;
  711. }
  712. private function render_mermaid(){
  713. $text = json_decode(base64_decode($this->get_param($this->param,"text",1)));
  714. $props = ["text" => implode("\n",$text)];
  715. switch ($this->format) {
  716. case 'react':
  717. $output = [
  718. 'props'=>base64_encode(\json_encode($props)),
  719. 'html'=>"mermaid",
  720. 'tag'=>'div',
  721. 'tpl'=>'mermaid',
  722. ];
  723. break;
  724. case 'unity':
  725. $output = [
  726. 'props'=>base64_encode(\json_encode($props)),
  727. 'tpl'=>'mermaid',
  728. ];
  729. break;
  730. case 'text':
  731. $output = 'mermaid';
  732. break;
  733. case 'tex':
  734. $output = 'mermaid';
  735. break;
  736. case 'simple':
  737. $output = 'mermaid';
  738. break;
  739. default:
  740. $output = 'mermaid';
  741. break;
  742. }
  743. return $output;
  744. }
  745. private function get_param(array $param,string $name,int $id,string $default=''){
  746. if(isset($param[$name])){
  747. return trim($param[$name]);
  748. }else if(isset($param["{$id}"])){
  749. return trim($param["{$id}"]);
  750. }else{
  751. return $default;
  752. }
  753. }
  754. }