MultiSearchUrl.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. <?php
  2. namespace app\common\components;
  3. use Yii;
  4. /**
  5. * author: Jack.Chen
  6. * create time: 15-3-31 上午9:46
  7. * description: 多条件搜索URL处理
  8. */
  9. class MultiSearchUrl{
  10. public $url;//基础URL
  11. public $conditions;//新传入的搜索条件
  12. public $existConditions;//已经存在的搜索条件
  13. public $keywordName = 'kw';//关键词参数名称keywordName
  14. public $filterTypes;//待过滤搜索条件类型
  15. public $conditionParamName='sch';
  16. public $splitFlag = '-';//条件之间的分割符
  17. public $orderTypeName = 'st';//排序条件键名
  18. public $keyword='';
  19. public $fieldConfig =[];
  20. public $sortConfig =[];
  21. public $filterAll = false;
  22. //初始化实例
  23. public static function getSelfInstance($params)
  24. {
  25. static $instance = null;
  26. if(is_null($instance))
  27. {
  28. $instance = new MultiSearchUrl();
  29. }
  30. if(is_array($params)) extract($params);
  31. if(isset($url))$instance->url = $url;
  32. if(isset($fieldConfig))$instance->fieldConfig = $fieldConfig;
  33. if(isset($sortConfig))$instance->sortConfig = $sortConfig;
  34. if(isset($conditions)&&!empty($conditions)){
  35. $instance->conditions = $conditions;
  36. }
  37. else
  38. {
  39. $instance->conditions = array();
  40. }
  41. foreach($instance->conditions as $k=>$v)
  42. {
  43. if($v==null)unset($instance->conditions[$k]);
  44. }
  45. if(isset($keywordName))$instance->keywordName = $keywordName;
  46. if(isset($filterAll))$instance->filterAll = $filterAll;
  47. if(!isset($filterAll))$instance->filterAll = false;
  48. if(isset($filterTypes)&&!empty($filterTypes)){
  49. $instance->filterTypes = $filterTypes;
  50. }
  51. else
  52. {
  53. $instance->filterTypes = array();
  54. }
  55. if(isset($_GET[$instance->keywordName]))$instance->keyword = safe_replace($_GET[$instance->keywordName]);
  56. $instance->existConditions = $instance->getSearchConditions();
  57. return $instance;
  58. }
  59. /**根据搜索条件组合后的Url(格式 a1-b2-c10)
  60. * @param $conditions
  61. * @return string
  62. */
  63. public function createSimpleSearchCondition()
  64. {
  65. $conditionStr = '';
  66. $conditionList = array();
  67. if(is_array($this->conditions))
  68. {
  69. foreach($this->conditions as $key=>$value)
  70. {
  71. $conditionList[] = $key.$value;
  72. }
  73. }
  74. asort($conditionList);
  75. if(!empty($conditionList))
  76. {
  77. $conditionStr = join($this->splitFlag,$conditionList);
  78. $this->url .= $conditionStr.'/';
  79. }
  80. return $this->url;
  81. }
  82. /**在已有搜索条件上组合传入的搜索条件生成新的Url
  83. * @return string
  84. */
  85. public function createSearchCondition()
  86. {
  87. //条件类型
  88. $types = array();
  89. $diffTypes = array();
  90. $inputTypes = array();
  91. if(is_array($this->existConditions))
  92. {
  93. foreach($this->existConditions as $condition)
  94. {
  95. $types[] = $this->_getTypeFromCondition($condition);
  96. }
  97. }
  98. //排除掉传入的相同选项类型
  99. if(!empty($types))$types = array_unique($types);
  100. if(!empty($this->conditions))$inputTypes = array_keys($this->conditions);
  101. if(isset($inputTypes)&&isset($diffTypes))$diffTypes = array_unique(array_diff($types,$inputTypes));
  102. //排除掉已经存在的搜索条件中不满足条件的项目(被过滤的项目和被新传入条件替换的项目)
  103. if(is_array($this->existConditions))
  104. {
  105. foreach($this->existConditions as $key=>$condition)
  106. {
  107. $type =$this->_getTypeFromCondition($condition);
  108. if(empty($diffTypes)||(!in_array($type,$diffTypes)&&!empty($diffTypes))||in_array($type,$this->filterTypes)||$this->filterAll==true)
  109. {
  110. unset($this->existConditions[$key]);
  111. }
  112. }
  113. }
  114. //对新传入条件排序
  115. $conditionStr = '';
  116. if(!empty($this->conditions))ksort($this->conditions);
  117. $conditionList = array();
  118. if(is_array($this->conditions))
  119. {
  120. foreach($this->conditions as $key=>$value)
  121. {
  122. if(!in_array($key,$diffTypes)||empty($this->existConditions))
  123. {
  124. $conditionList[] = $key.$value;
  125. }
  126. }
  127. }
  128. //合并已有条件和新条件
  129. if(is_array($this->existConditions)&&!empty($this->existConditions))
  130. {
  131. $conditionList = array_merge($conditionList,$this->existConditions);
  132. }
  133. return $this->_createUrl($conditionList);
  134. }
  135. /**选择不限帅选条件时候Url重新生成
  136. * @return string
  137. */
  138. public function stickOut()
  139. {
  140. $conditionList = array();
  141. if(!empty($this->existConditions))
  142. {
  143. foreach($this->existConditions as $condition)
  144. {
  145. $type = $this->_getTypeFromCondition($condition);
  146. if(!in_array($type,$this->filterTypes))
  147. {
  148. $conditionList[] = $condition;
  149. }
  150. }
  151. }
  152. return $this->_createUrl($conditionList);
  153. }
  154. /**获取当前帅选条件
  155. * @return array|mixed
  156. */
  157. public function getSearchConditions()
  158. {
  159. $searchCondition = isset($_GET[$this->conditionParamName])?safe_replace($_GET[$this->conditionParamName]):array();
  160. if(!empty($searchCondition))
  161. {
  162. $searchCondition = explode($this->splitFlag,$searchCondition);
  163. }
  164. return $searchCondition;
  165. }
  166. //当前条件类型
  167. public function getConditionsTypes()
  168. {
  169. //条件类型
  170. $types = array();
  171. if(is_array($this->existConditions))
  172. {
  173. foreach($this->existConditions as $condition)
  174. {
  175. $types[] = $this->_getTypeFromCondition($condition);
  176. }
  177. }
  178. return $types;
  179. }
  180. /**反序列化筛选条件
  181. * @return array
  182. */
  183. public function sqllizeConditions()
  184. {
  185. $where = '';
  186. $order = '';
  187. $sortValue=null;//当前排序条件键值
  188. $typeField = $this->getTypeFieldConfig(); //搜索条件键名和字段值对应关系
  189. if(is_array($this->existConditions))
  190. {
  191. foreach($this->existConditions as $condition)
  192. {
  193. if(strpos($condition,$this->keywordName) === 0){
  194. $type = $this->keywordName;
  195. $value = str_replace($this->keywordName,'',$condition);
  196. }
  197. else
  198. {
  199. $type = $this->_getTypeFromCondition($condition);
  200. $value = $this->_getValueFromCondition($condition);
  201. }
  202. if($type==$this->orderTypeName)//如果为排序条件
  203. {
  204. $sortInfo = $this->getSortConditionConfig($value);
  205. $order = " order by ".$sortInfo['order'];
  206. $sortValue = $value;
  207. }
  208. else
  209. {
  210. if(isset($typeField[$type]))
  211. {
  212. $field = $typeField[$type]['field'];
  213. $flag = $typeField[$type]['flag'];
  214. $sqlType = $typeField[$type]['type'];
  215. switch($sqlType)
  216. {
  217. case 'cat_id':
  218. $where .= " and $field $flag $value ";
  219. break;
  220. case 'cat_ids':
  221. $where .= " and $field $flag '%,".$value.",%' ";
  222. break;
  223. case 'boollist':
  224. $field = $field[$value-1];
  225. $where .= " and $field = 1 ";
  226. break;
  227. case 'commonlike':
  228. $where .= " and $field like '%".$value."%'";
  229. break;
  230. case 'leftlike':
  231. $where .= " and $field like '%".$value."'";
  232. break;
  233. case 'rightlike':
  234. $where .= " and $field like '".$value."%'";
  235. break;
  236. case 'equals':
  237. $fieldRs = explode(",",$field);
  238. $kk = 0;
  239. $songwhere = '';
  240. foreach($fieldRs as $frs)
  241. {
  242. if($kk==0){
  243. $songwhere = " $frs $flag $value ";
  244. }
  245. else
  246. {
  247. $songwhere .= " or $frs $flag $value ";
  248. }
  249. $kk++;
  250. }
  251. $where .= " and ($songwhere) ";
  252. break;
  253. case 'equal':
  254. $where .= " and $field $flag $value ";
  255. break;
  256. case 'gt':
  257. $where .= " and $field $flag $value ";
  258. break;
  259. case 'lt':
  260. $where .= " and $field $flag $value ";
  261. break;
  262. case 'linkmenu':
  263. $menu = \app\models\Linkmenu::findOne($value);
  264. $childIds = $menu->arr_child_ids;
  265. $where .= !empty($childIds)?" and $field in($childIds) ":" and $field $flag $value ";
  266. break;
  267. case 'day':
  268. $starttime = TIMESTAMP-$value*24*3600;
  269. $where .= " and $field $flag $starttime ";
  270. break;
  271. }
  272. }
  273. }
  274. }
  275. }
  276. return array('order'=>$order,'where'=>$where,'sortValue'=>$sortValue);
  277. }
  278. //根据搜索选项类型获取搜索选项值
  279. public function getSearchConditionValue($key,$onCondition)
  280. {
  281. if($onCondition)return;
  282. if(!empty($this->existConditions))
  283. {
  284. foreach($this->existConditions as $condition)
  285. {
  286. $type = $this->_getTypeFromCondition($condition);
  287. if($type==$key)
  288. {
  289. return $this->_getValueFromCondition($condition);
  290. //return preg_replace('/'.$key.'+/','',$condition);
  291. }
  292. }
  293. }
  294. }
  295. //根据最终的搜索条件生成URL
  296. private function _createUrl($conditionList)
  297. {
  298. asort($conditionList);
  299. if(strpos($this->url,'.html')!==false)
  300. {
  301. $this->url = str_replace('.html','',$this->url).'/';
  302. $suffix = '.html';
  303. }
  304. if(!empty($conditionList))
  305. {
  306. $conditionStr = join("-",$conditionList);
  307. $this->url.=$conditionStr.'/';
  308. /*if(!empty($this->keyword))//如果有关键词,在搜索条件后增加关键词条件
  309. {
  310. $this->url .= $this->keywordName.'/'.$this->keyword.'/';
  311. }*/
  312. }
  313. else
  314. {
  315. /*if(!empty($this->keyword))//如果有关键词,在搜索条件后增加关键词条件
  316. {
  317. $this->url .= $this->keywordName.'/'.$this->keyword.'/';
  318. }*/
  319. }
  320. if($suffix!='')
  321. {
  322. return rtrim($this->url,'/').$suffix;
  323. }
  324. else
  325. {
  326. return $this->url;
  327. }
  328. }
  329. //根据条件获取条件类型(如传入a1返回a)
  330. public function _getTypeFromCondition($condition)
  331. {
  332. return preg_replace('/[0-9_]+/','',$condition);
  333. }
  334. //根据条件获取条件值(如传入a1返回1)
  335. public function _getValueFromCondition($condition)
  336. {
  337. return preg_replace('/[a-zA-Z]+/','',$condition);
  338. }
  339. //根据搜索条件类型获取条件值
  340. public function getConditionValueByType($searchConditions,$searchType)
  341. {
  342. if(is_array($searchConditions))foreach($searchConditions as $condition)
  343. {
  344. $type = preg_replace('/[0-9]+/','',$condition);
  345. $value = preg_replace('/[a-zA-Z]+/','',$condition);
  346. if($type==$searchType)
  347. {
  348. return $value;
  349. }
  350. }
  351. }
  352. //获取搜索关键词
  353. public function getKeyword($searchConditions)
  354. {
  355. if(is_array($searchConditions))foreach($searchConditions as $condition)
  356. {
  357. if(strpos($condition,$this->keywordName) === 0){
  358. return str_replace($this->keywordName,'',$condition);
  359. }
  360. }
  361. }
  362. //搜索条件字段对应值配置
  363. public function getTypeFieldConfig()
  364. {
  365. $array = $this->fieldConfig;
  366. /*$array = array(
  367. 'r'=>array('type'=>'linkmenu','flag'=>'=', 'field'=>'region_id'),
  368. 'c'=>array('type'=>'equal','flag'=>'=','field'=>'cat_id'),
  369. 't'=>array('type'=>'equal','flag'=>'=','field'=>'doc_type'),
  370. 't1'=>array('type'=>'equal','flag'=>'=','field'=>'ext_type1'),
  371. 't2'=>array('type'=>'equal','flag'=>'=','field'=>'ext_type2'),
  372. 't3'=>array('type'=>'equal','flag'=>'=','field'=>'ext_type3'),
  373. );*/
  374. return $array;
  375. }
  376. //排序条件配置
  377. public function getSortConditionConfig($value = NULL)
  378. {
  379. $array = $this->sortConfig;
  380. /* $array = array(
  381. //文库
  382. '1'=>array('value'=>1, 'order'=>'create_time desc','title'=>'按发布时间排序','tips'=>'点击按发布时间排序'),
  383. '2'=>array('value'=>2, 'order'=>'down_num desc','title'=>'按下载数量排序','tips'=>'点击按下载数量排序'),
  384. '3'=>array('value'=>3, 'order'=>'views desc','title'=>'按浏览数排序','tips'=>'点击按浏览数排序'),
  385. //商城
  386. '7'=>array('value'=>7, 'order'=>'sales desc','title'=>'按销量排序','tips'=>'按销量排序'),
  387. '8'=>array('value'=>8, 'order'=>'sales asc','title'=>'按销量排序','tips'=>'按销量排序'),
  388. '9'=>array('value'=>9, 'order'=>'market_price desc','title'=>'按价格排序','tips'=>'按价格排序'),
  389. '10'=>array('value'=>10, 'order'=>'market_price asc','title'=>'按价格排序','tips'=>'按价格排序'),
  390. '11'=>array('value'=>11, 'order'=>'create_time desc','title'=>'按上架时间排序','tips'=>'按销量排序'),
  391. '12'=>array('value'=>12, 'order'=>'create_time asc','title'=>'按上架时间排序','tips'=>'按销量排序'),
  392. '999'=>array('value'=>999, 'order'=>'is_recommend desc','title'=>'推荐','tips'=>'推荐'),
  393. '1000'=>array('value'=>1000, 'order'=>'is_recommend asc','title'=>'推荐','tips'=>'推荐'),
  394. //论坛
  395. '13'=>array('value'=>13, 'order'=>'create_time desc','title'=>'按最新','tips'=>'按最新'),
  396. '14'=>array('value'=>14, 'order'=>'post_num desc','title'=>'按热议','tips'=>'按热议'),
  397. '15'=>array('value'=>15, 'order'=>'reward desc','title'=>'按报酬排序','tips'=>'按报酬排序'),
  398. '16'=>array('value'=>16, 'order'=>'reward asc','title'=>'按报酬排序','tips'=>'按报酬排序'),
  399. '17'=>array('value'=>17, 'order'=>'stock desc','title'=>'按需求数量排序','tips'=>'按需求数量排序'),
  400. '18'=>array('value'=>18, 'order'=>'stock asc','title'=>'按需求数量排序','tips'=>'按需求数量排序'),
  401. );*/
  402. if(!is_null($value))
  403. {
  404. return $array[$value];
  405. }
  406. else
  407. {
  408. return $array;
  409. }
  410. }
  411. }
  412. /* HTML 示例:
  413. <div class="ts_header">
  414. <div class="ts_head_grade">
  415. <p>所在年级:</p>
  416. <li <?php if(!in_array('c',$conditionsTypes)){ ?>class="on" <?php }?>> <a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'filterTypes'=>array('c')))->createSearchCondition();?>">全部</a></li>
  417. <?php if(!empty($catList)&&is_array($catList))foreach($catList as $cat){?>
  418. <li <?php if(in_array('c'.$cat['cat_id'],$searchConditions)){?> class="on" <?php }?>><a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'conditions'=>array('c'=>$cat['cat_id'])))->createSearchCondition();?>"><?php echo $cat['cat_name'];?>
  419. </a></li>
  420. <?php }?>
  421. <div class="clear"></div>
  422. </div>
  423. <?php if($childCatList){?>
  424. <div class="ts_head_hig" >
  425. <div class="ts_head_hig_cot" style="padding-left: 104px;">
  426. <?php if(!empty($childCatList)&&is_array($childCatList))foreach($childCatList as $cat){?>
  427. <li <?php if(in_array('c'.$cat['cat_id'],$searchConditions)){?> class="on" <?php }?>><a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'conditions'=>array('c'=>$cat['cat_id'])))->createSearchCondition();?>"><?php echo $cat['cat_name'];?>
  428. </a></li>
  429. <?php }?>
  430. <div class="clear"></div>
  431. </div>
  432. </div>
  433. <?php }?>
  434. <?php if($getTypeList){?>
  435. <div class="ts_head_class">
  436. <div class="ts_head_class_cot">
  437. <p>课程分类:</p>
  438. <li <?php if(!in_array('t',$conditionsTypes)){ ?>class="on" <?php }?>> <a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'filterTypes'=>array('t')))->createSearchCondition();?>">全部</a></li>
  439. <?php if(!empty($getTypeList)&&is_array($getTypeList))foreach($getTypeList as $type){?>
  440. <li <?php if(in_array('t'.$type['type_id'],$searchConditions)){?> class="on" <?php }?>><a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'conditions'=>array('t'=>$type['type_id'])))->createSearchCondition();?>"><?php echo $type['name'];?></a></li>
  441. <?php }?>
  442. <div class="clear"></div>
  443. </div>
  444. </div>
  445. <?php }?>
  446. <div class="ts_head_class">
  447. <div class="ts_head_class_cot">
  448. <p>授课方式:</p>
  449. <li <?php if(!in_array('tt',$conditionsTypes)){ ?>class="on" <?php }?>> <a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'filterTypes'=>array('tt')))->createSearchCondition();?>">全部</a></li>
  450. <?php if($teachTypeList)foreach($teachTypeList as $key=>$name){
  451. if($key==Yii::app()->params['weiCourseTypeId'])continue;
  452. ?>
  453. <li <?php if(in_array('tt'.$key,$searchConditions)){?> class="on" <?php }?>><a href="<?php echo MultiSearchUrl::getSelfInstance(array('url'=>Url::allCourse(),'conditions'=>array('tt'=>$key)))->createSearchCondition();?>"><?php echo $name;?></a></li>
  454. <?php }?>
  455. </div>
  456. </div>
  457. </div>
  458. */
  459. /*php示例
  460. public function actionAllCourse()
  461. {
  462. //初始化栏目信息
  463. $topCat = $this->categorys[Yii::app()->params['teacherCatId']];
  464. $catList = array();
  465. $catIds = explode(",",$topCat['arr_child_id']);
  466. if(is_array($catIds))foreach($catIds as $id)
  467. {
  468. $cat = $this->categorys[$id];
  469. if($cat['cat_id']!=$topCat['cat_id'])
  470. {
  471. $catList[] = $cat;
  472. }
  473. }
  474. //解析组合条件
  475. $searchConditions = MultiSearchUrl::getSelfInstance(array())->getSearchConditions();
  476. $childCatList = array();
  477. $currentCatId = $this->_getCatId($searchConditions);
  478. if($this->categorys[$currentCatId]['arr_child_id'])
  479. {
  480. $catIds = explode(",", $this->categorys[$currentCatId]['arr_child_id']);
  481. if(is_array($catIds))foreach($catIds as $id)
  482. {
  483. $cat = $this->categorys[$id];
  484. if($cat['cat_id']!=$currentCatId)
  485. {
  486. $childCatList[] = $cat;
  487. }
  488. }
  489. }
  490. //当选取三级栏目时候的处理
  491. if($currentCatId&&!$childCatList)
  492. {
  493. $catIds = explode(",", $this->categorys[$this->categorys[$currentCatId]['parent_id']]['arr_child_id']);
  494. if(is_array($catIds))foreach($catIds as $id)
  495. {
  496. $cat = $this->categorys[$id];
  497. if($cat['cat_id']!=$this->categorys[$currentCatId]['parent_id'])
  498. {
  499. $childCatList[] = $cat;
  500. }
  501. }
  502. }
  503. //类别
  504. if($currentCatId)
  505. {
  506. $typeList = json_decode(Yii::app()->filecache->get(CacheId::typeCacheId($this->siteId)),true);
  507. if($this->categorys[$currentCatId]['usable_type'])
  508. {
  509. $types = explode(",",$this->categorys[$currentCatId]['usable_type']);
  510. if(is_array($types))foreach($types as $typeId)
  511. {
  512. $getTypeList[] = $typeList[$typeId];
  513. }
  514. }
  515. }
  516. $teachTypeList = Yii::app()->params['options']['teachType'];
  517. $keyword = isset($_GET[MultiSearchUrl::getSelfInstance()->keywordName])?safe_replace($_GET[MultiSearchUrl::getSelfInstance()->keywordName]):'';
  518. //获取搜索条件类型
  519. $conditionsTypes = MultiSearchUrl::getSelfInstance()->getConditionsTypes();
  520. //分页参数
  521. $page = isset($_GET['page'])?intval($_GET['page']):1;
  522. $pageSize = Yii::app()->params['teacherPageSize'];
  523. $offset = ($page-1)*$pageSize;
  524. //解析SQL
  525. $sqlInfo = MultiSearchUrl::getSelfInstance(array())->sqllizeConditions();
  526. $where = " where status=1 ";
  527. $where .= !empty($sqlInfo['where'])?$sqlInfo['where']:'';
  528. $likeStr = !empty($keyword)?" and (title like '%".$keyword."%')":'';
  529. $orderStr = !empty($sqlInfo['order'])?$sqlInfo['order']:' order by point desc';
  530. $sqlCount = "select count(distinct(user_name)) as count from {{cource}} $where $likeStr";
  531. $sqlList = "select * from (select * from {{user}} where user_name in(select distinct(user_name) from {{cource}} $where ) $orderStr limit $offset,$pageSize ) a left join {{user_teacher}} b on a.user_id=b.user_id ";
  532. $countModel = Yii::app()->db->createCommand($sqlCount);
  533. $result = $countModel->queryAll();
  534. $count = $result[0]['count'];
  535. $listModel = Yii::app()->db->createCommand($sqlList);
  536. $resultlist = $listModel->queryAll();
  537. $pages = new CPagination($count);
  538. $pages->pageSize = intval($pageSize);
  539. $this->render('allcourse',array('resultlist'=>$resultlist,'pages'=>$pages,'catList'=>$catList,'searchConditions'=>$searchConditions,'conditionsTypes'=>$conditionsTypes,'childCatList'=>$childCatList,'getTypeList'=>$getTypeList,'teachTypeList'=>$teachTypeList));
  540. }
  541. */