search.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. <?php
  2. //@2014-01-18 some tunning of searching by A.Binder
  3. function task_CRM_SEARCH() {
  4. $q = V::get('q', '', $_REQUEST);
  5. $f_limit = V::get('f-_limit', 10, $_REQUEST, 'int');
  6. $f_offset = V::get('f-_offset', 0, $_REQUEST, 'int');
  7. $active_tab = V::get('_active_tab', 0, $_REQUEST, 'int');
  8. $db = DB::getDB();
  9. $qProces = new CrmSearchProces($db);
  10. $qProces->set_search($q);
  11. $qProces->set_param('limit', $f_limit);
  12. if ($active_tab == 0) {
  13. $qProces->set_param('offset', $f_offset);
  14. }
  15. echo '<h1>' . "Wyszukiwanie: " . htmlspecialchars($q) . '</h1>';
  16. if (!$qProces->check_search()) {
  17. echo App::ui_widget('alert', "Wyszukiwane słowo musi mieć conajmniej 2 znaki");
  18. return;
  19. }
  20. $qZasob = new CrmSearchZasob($db);
  21. $qZasob->set_search($q);
  22. $qZasob->set_param('limit', $f_limit);
  23. if ($active_tab == 1) {
  24. $qZasob->set_param('offset', $f_offset);
  25. }
  26. $qWsk = new CrmSearchWskaznik($db);
  27. $qWsk->set_search($q);
  28. $qWsk->set_param('limit', $f_limit);
  29. if ($active_tab == 2) {
  30. $qWsk->set_param('offset', $f_offset);
  31. }
  32. $qProcesInit = new CrmSearchProcesInit($db);
  33. $qProcesInit->set_search($q);
  34. $qProcesInit->set_param('limit', $f_limit);
  35. if ($active_tab == 3) {
  36. $qProcesInit->set_param('offset', $f_offset);
  37. }
  38. Lib::loadClass('PageNav');
  39. ?>
  40. <div id="tabs">
  41. <ul>
  42. <li><a href="#tabs-1" style="outline:none">Procesy (<?php echo $qProces->get_total();?>)</a></li>
  43. <li><a href="#tabs-2" style="outline:none">Zasoby (<?php echo $qZasob->get_total();?>)</a></li>
  44. <li><a href="#tabs-3" style="outline:none">Wskaźniki (<?php echo $qWsk->get_total();?>)</a></li>
  45. <li><a href="#tabs-4" style="outline:none">Procesy Start (<?php echo $qProcesInit->get_total();?>)</a></li>
  46. </ul>
  47. <?php $tab_nr = 1; ?>
  48. <div id="tabs-<?php echo $tab_nr; ?>" style="padding:10px 0;">
  49. <?php
  50. $total = $qProces->get_total();
  51. if ($total <= 0) {
  52. echo App::ui_widget('info', "Nie znaleziono żadnych rekordów pasujacych do kryteriów wyszukiwania");
  53. }
  54. else {
  55. $list = $qProces->get_list();
  56. $nav = new PageNav($total, $qProces->get_param('offset'), $qProces->get_param('limit'));
  57. $nav->set_request_args(array('task'=>'CRM_SEARCH', 'q'=>$q, '_active_tab'=>($tab_nr - 1)));
  58. $nav->set_request_method_post();
  59. $nav->set_request_arg_page_nr_name('f-_offset');
  60. echo $nav->render('links_only');
  61. ?>
  62. <table cellspacing="0" cellpadding="0" border="1" class="tbl-view">
  63. <thead>
  64. <tr>
  65. <th>ID</th>
  66. <th>DESC</th>
  67. <th>OPIS</th>
  68. <th>hit_counter</th>
  69. </tr>
  70. </thead>
  71. <tbody>
  72. <?php
  73. $t = 0;
  74. foreach ($list as $r) {
  75. $desc = strip_tags($r->DESC);
  76. $desc = str_replace($q, '<b>'.$q.'</b>', $desc);
  77. $desc = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $desc);
  78. $opis = strip_tags($r->OPIS);
  79. if (strlen($opis) > 255) {
  80. $opis = substr($opis, 0, 255) . ' ...';
  81. }
  82. $opis = str_replace($q, '<b>'.$q.'</b>', $opis);
  83. $opis = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $opis);
  84. echo '<tr class="row-'.($t = 1 - $t).'">';
  85. echo '<td>' . App::link($r->ID, array('task'=>'CRM_PROCES', 'filtr_id'=>$r->ID), array('class'=>'external', 'target'=>'_blank')) . '</td>';
  86. echo '<td>' . $desc . '</td>';
  87. echo '<td>' . $opis . '</td>';
  88. echo '<td>' . $r->hit_counter . '</td>';
  89. echo '</tr>';
  90. }
  91. ?>
  92. </tbody>
  93. </table>
  94. <?php
  95. echo $nav->render();
  96. }
  97. ?>
  98. </div>
  99. <?php $tab_nr++; ?>
  100. <div id="tabs-<?php echo $tab_nr; ?>" style="padding:10px 0;">
  101. <?php
  102. $total = $qZasob->get_total();
  103. if ($total <= 0) {
  104. echo App::ui_widget('info', "Nie znaleziono żadnych rekordów pasujacych do kryteriów wyszukiwania");
  105. }
  106. else {
  107. $list = $qZasob->get_list();
  108. $nav = new PageNav($total, $qZasob->get_param('offset'), $qZasob->get_param('limit'));
  109. $nav->set_request_args(array('task'=>'CRM_SEARCH', 'q'=>$q, '_active_tab'=>($tab_nr - 1)));
  110. $nav->set_request_method_post();
  111. $nav->set_request_arg_page_nr_name('f-_offset');
  112. echo $nav->render('links_only');
  113. ?>
  114. <table cellspacing="0" cellpadding="0" border="1" class="tbl-view">
  115. <thead>
  116. <tr>
  117. <th>ID</th>
  118. <th>DESC</th>
  119. <th>OPIS</th>
  120. <th>hit_counter</th>
  121. </tr>
  122. </thead>
  123. <tbody>
  124. <?php
  125. $t = 0;
  126. foreach ($list as $r) {
  127. $desc = strip_tags($r->DESC);
  128. $desc = str_replace($q, '<b>'.$q.'</b>', $desc);
  129. $desc = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $desc);
  130. $opis = strip_tags($r->OPIS);
  131. if (strlen($opis) > 255) {
  132. $opis = substr($opis, 0, 255) . ' ...';
  133. }
  134. $opis = str_replace($q, '<b>'.$q.'</b>', $opis);
  135. $opis = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $opis);
  136. echo '<tr class="row-'.($t = 1 - $t).'">';
  137. echo '<td>' . App::link($r->ID, array('task'=>'CRM_LISTA_ZASOBOW', 'filtr_id'=>$r->ID), array('class'=>'external', 'target'=>'_blank')) . '</td>';
  138. echo '<td>' . $desc . '</td>';
  139. echo '<td>' . $opis . '</td>';
  140. echo '<td>' . $r->hit_counter . '</td>';
  141. echo '</tr>';
  142. }
  143. ?>
  144. </tbody>
  145. </table>
  146. <?php
  147. echo $nav->render();
  148. }
  149. ?>
  150. </div>
  151. <?php $tab_nr++; ?>
  152. <div id="tabs-<?php echo $tab_nr; ?>" style="padding:10px 0;">
  153. <?php
  154. $total = $qWsk->get_total();
  155. if ($total <= 0) {
  156. echo App::ui_widget('info', "Nie znaleziono żadnych rekordów pasujacych do kryteriów wyszukiwania");
  157. }
  158. else {
  159. $list = $qWsk->get_list();
  160. $nav = new PageNav($total, $qWsk->get_param('offset'), $qWsk->get_param('limit'));
  161. $nav->set_request_args(array('task'=>'CRM_SEARCH', 'q'=>$q, '_active_tab'=>($tab_nr - 1)));
  162. $nav->set_request_method_post();
  163. $nav->set_request_arg_page_nr_name('f-_offset');
  164. echo $nav->render('links_only');
  165. ?>
  166. <table cellspacing="0" cellpadding="0" border="1" class="tbl-view">
  167. <thead>
  168. <tr>
  169. <th>ID</th>
  170. <th>ID_PROCES</th>
  171. <th>ID_ZASOB</th>
  172. <th>OPIS_ZASOB</th>
  173. <th>hit_counter</th>
  174. </tr>
  175. </thead>
  176. <tbody>
  177. <?php
  178. $t = 0;
  179. foreach ($list as $r) {
  180. $desc = strip_tags($r->DESC);
  181. $desc = str_replace($q, '<b>'.$q.'</b>', $desc);
  182. $desc = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $desc);
  183. $opis = strip_tags($r->OPIS_ZASOB);
  184. if (strlen($opis) > 255) {
  185. $opis = substr($opis, 0, 255) . ' ...';
  186. }
  187. $opis = str_replace($q, '<b>'.$q.'</b>', $opis);
  188. $opis = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $opis);
  189. echo '<tr class="row-'.($t = 1 - $t).'">';
  190. echo '<td>' . $r->ID . '</td>';
  191. echo '<td>' . App::link($r->ID_PROCES, array('task'=>'CRM_PROCES', 'filtr_id'=>$r->ID_PROCES), array('class'=>'external', 'target'=>'_blank')) . '</td>';
  192. echo '<td>' . App::link($r->ID_ZASOB, array('task'=>'CRM_LISTA_ZASOBOW', 'filtr_id'=>$r->ID_ZASOB), array('class'=>'external', 'target'=>'_blank')) . '</td>';
  193. echo '<td>' . $opis . '</td>';
  194. echo '<td>' . $r->hit_counter . '</td>';
  195. echo '</tr>';
  196. }
  197. ?>
  198. </tbody>
  199. </table>
  200. <?php
  201. echo $nav->render();
  202. }
  203. ?>
  204. </div>
  205. <?php $tab_nr = 4; ?>
  206. <div id="tabs-<?php echo $tab_nr; ?>" style="padding:10px 0;">
  207. <?php
  208. $total = $qProcesInit->get_total();
  209. if ($total <= 0) {
  210. echo App::ui_widget('info', "Nie znaleziono żadnych rekordów pasujacych do kryteriów wyszukiwania");
  211. }
  212. else {
  213. $list = $qProcesInit->get_list();
  214. $nav = new PageNav($total, $qProcesInit->get_param('offset'), $qProcesInit->get_param('limit'));
  215. $nav->set_request_args(array('task'=>'CRM_SEARCH', 'q'=>$q, '_active_tab'=>($tab_nr - 1)));
  216. $nav->set_request_method_post();
  217. $nav->set_request_arg_page_nr_name('f-_offset');
  218. echo $nav->render('links_only');
  219. ?>
  220. <table cellspacing="0" cellpadding="0" border="1" class="tbl-view">
  221. <thead>
  222. <tr>
  223. <th>ID</th>
  224. <th>DESC</th>
  225. <th>OPIS</th>
  226. <th>hit_counter</th>
  227. </tr>
  228. </thead>
  229. <tbody>
  230. <?php
  231. $t = 0;
  232. foreach ($list as $r) {
  233. $desc = strip_tags($r->DESC);
  234. $desc = str_replace($q, '<b>'.$q.'</b>', $desc);
  235. $desc = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $desc);
  236. $opis = strip_tags($r->OPIS);
  237. if (strlen($opis) > 255) {
  238. $opis = substr($opis, 0, 255) . ' ...';
  239. }
  240. $opis = str_replace($q, '<b>'.$q.'</b>', $opis);
  241. $opis = str_replace(strtoupper($q), '<b>'.strtoupper($q).'</b>', $opis);
  242. echo '<tr class="row-'.($t = 1 - $t).'">';
  243. echo '<td>' . App::link($r->ID, array('task'=>'CRM_PROCES', 'filtr_id'=>$r->ID), array('class'=>'external', 'target'=>'_blank')) . '</td>';
  244. echo '<td>' . $desc . '</td>';
  245. echo '<td>' . $opis . '</td>';
  246. echo '<td>' . $r->hit_counter . '</td>';
  247. echo '</tr>';
  248. }
  249. ?>
  250. </tbody>
  251. </table>
  252. <?php
  253. echo $nav->render();
  254. }
  255. ?>
  256. </div>
  257. </div>
  258. <script type="text/javascript">
  259. jQuery(document).ready(function(){
  260. jQuery("#tabs").tabs({ active: <?php echo $active_tab; ?> });
  261. });
  262. </script>
  263. <?php
  264. }
  265. class CrmSearchBase {
  266. var $db = null;
  267. var $q = '';
  268. var $params = array();
  269. var $fields = array();
  270. var $_limit = 0;
  271. var $_total = null;
  272. var $_list = null;
  273. public function __construct($db) {
  274. $this->db = $db;
  275. }
  276. public function set_fields($fields) {
  277. $this->fields = $fields;
  278. }
  279. public function add_field($field, $label) {
  280. $this->fields[$field] = $label;
  281. }
  282. public function get_field_names() {
  283. return array_keys($this->fields);
  284. }
  285. public function get_field_labels() {
  286. return array_values($this->fields);
  287. }
  288. public function get_fields() {
  289. return $this->fields;
  290. }
  291. public function set_search($q) {
  292. $q = trim($q);
  293. $this->q = $this->db->_($q);
  294. }
  295. public function check_search() {
  296. return (!empty($this->q) && strlen($this->q) > 2);
  297. }
  298. public function set_param($key, $value) {
  299. $this->params[$key] = $value;
  300. }
  301. public function get_param($key) {
  302. return (array_key_exists($key, $this->params))? $this->params[$key] : null;
  303. }
  304. public function get_total() {
  305. if ($this->_total === null) {
  306. $this->_total = $this->_fetch_total();
  307. }
  308. return $this->_total;
  309. }
  310. public function get_list() {
  311. if ($this->_list === null) {
  312. $this->_list = $this->_fetch_list();
  313. }
  314. return $this->_list;
  315. }
  316. protected function _fetch_total() {
  317. return 0;
  318. }
  319. protected function _fetch_list() {
  320. $ret = array();
  321. return $ret;
  322. }
  323. }
  324. class CrmSearchProces extends CrmSearchBase {
  325. function _get_sql_where() {
  326. $sql_where = "
  327. p.`A_STATUS` in('NORMAL','WAITING')
  328. and (p.`DESC` like '%{$this->q}%' or p.`OPIS` like '%{$this->q}%' or p.`ID` like '{$this->q}')
  329. ";
  330. return $sql_where;
  331. }
  332. function _fetch_total() {
  333. $total = 0;
  334. $sql_where = $this->_get_sql_where();
  335. $sql = "select count(1) as cnt
  336. from `CRM_PROCES` as p
  337. where {$sql_where}
  338. ";
  339. $res = $this->db->query($sql);
  340. if ($r = $this->db->fetch($res)) {
  341. $total = $r->cnt;
  342. }
  343. return $total;
  344. }
  345. function _fetch_list() {
  346. $list = array();
  347. $sql_where = $this->_get_sql_where();
  348. $sql_limit = V::get('limit', 10, $this->params, 'int');
  349. $sql_offset = V::get('offset', 0, $this->params, 'int');
  350. $sql = "select p.`ID`, p.`DESC`, p.`OPIS`
  351. , if(p.`ID`='{$this->q}', 100
  352. , if(p.`DESC`='{$this->q}', 99
  353. , if(p.`DESC` like '{$this->q}%', 90
  354. , if(p.`DESC` like '%{$this->q}%', 80
  355. , if(p.`OPIS`='{$this->q}', 50
  356. , if(p.`OPIS` like '{$this->q}%', 40
  357. , if(p.`OPIS` like '%{$this->q}%', 30
  358. , 0
  359. )
  360. )
  361. )
  362. )
  363. )
  364. )
  365. )
  366. as hit_counter
  367. from `CRM_PROCES` as p
  368. where {$sql_where}
  369. order by hit_counter DESC, p.`ID` DESC
  370. limit {$sql_limit} offset {$sql_offset}
  371. ";
  372. $res = $this->db->query($sql);
  373. while ($r = $this->db->fetch($res)) {
  374. $list[$r->ID] = $r;
  375. }
  376. return $list;
  377. }
  378. }
  379. class CrmSearchProcesInit extends CrmSearchBase {
  380. function _get_sql_where() {
  381. $sql_where = "
  382. p.`A_STATUS` in('NORMAL','WAITING')
  383. and (p.`DESC` like '%{$this->q}%' or p.`OPIS` like '%{$this->q}%' or p.`ID` like '%{$this->q}%')
  384. and p.`TYPE`='PROCES_INIT'
  385. ";
  386. return $sql_where;
  387. }
  388. function _fetch_total() {
  389. $total = 0;
  390. $sql_where = $this->_get_sql_where();
  391. $sql = "select count(1) as cnt
  392. from `CRM_PROCES` as p
  393. where {$sql_where}
  394. ";
  395. $res = $this->db->query($sql);
  396. if ($r = $this->db->fetch($res)) {
  397. $total = $r->cnt;
  398. }
  399. return $total;
  400. }
  401. function _fetch_list() {
  402. $list = array();
  403. $sql_where = $this->_get_sql_where();
  404. $sql_limit = V::get('limit', 10, $this->params, 'int');
  405. $sql_offset = V::get('offset', 0, $this->params, 'int');
  406. $sql = "select p.`ID`, p.`DESC`, p.`OPIS`
  407. , if(p.`ID`='{$this->q}', 100
  408. , if(p.`DESC`='{$this->q}', 99
  409. , if(p.`DESC` like '{$this->q}%', 90
  410. , if(p.`DESC` like '%{$this->q}%', 80
  411. , if(p.`OPIS`='{$this->q}', 50
  412. , if(p.`OPIS` like '{$this->q}%', 40
  413. , if(p.`OPIS` like '%{$this->q}%', 30
  414. , 0
  415. )
  416. )
  417. )
  418. )
  419. )
  420. )
  421. ) as hit_counter
  422. from `CRM_PROCES` as p
  423. where {$sql_where}
  424. order by hit_counter DESC, p.`ID` DESC
  425. limit {$sql_limit} offset {$sql_offset}
  426. ";
  427. $res = $this->db->query($sql);
  428. while ($r = $this->db->fetch($res)) {
  429. $list[$r->ID] = $r;
  430. }
  431. return $list;
  432. }
  433. }
  434. class CrmSearchZasob extends CrmSearchBase {
  435. function _get_sql_where() {
  436. $sql_where = "
  437. z.`A_STATUS` in('NORMAL','WAITING')
  438. and (z.`DESC` like '%{$this->q}%' or z.`OPIS` like '%{$this->q}%' or z.`ID` like '{$this->q}')
  439. ";
  440. return $sql_where;
  441. }
  442. function _fetch_total() {
  443. $total = 0;
  444. $sql_where = $this->_get_sql_where();
  445. $sql = "select count(1) as cnt
  446. from `CRM_LISTA_ZASOBOW` as z
  447. where {$sql_where}
  448. ";
  449. $res = $this->db->query($sql);
  450. if ($r = $this->db->fetch($res)) {
  451. $total = $r->cnt;
  452. }
  453. return $total;
  454. }
  455. function _fetch_list() {
  456. $list = array();
  457. $sql_where = $this->_get_sql_where();
  458. $sql_limit = V::get('limit', 10, $this->params, 'int');
  459. $sql_offset = V::get('offset', 0, $this->params, 'int');
  460. $sql = "select z.`ID`, concat(z.`DESC`,' (',z.`TYPE`,')') as `DESC`, z.`OPIS`
  461. , if(z.`ID`='{$this->q}', 100
  462. , if(z.`DESC`='{$this->q}', 99
  463. , if(z.`DESC` like '{$this->q}%', 90
  464. , if(z.`DESC` like '%{$this->q}%', 80
  465. , if(z.`OPIS`='{$this->q}', 50
  466. , if(z.`OPIS` like '{$this->q}%', 40
  467. , if(z.`OPIS` like '%{$this->q}%', 30
  468. , 0
  469. )
  470. )
  471. )
  472. )
  473. )
  474. )
  475. ) as hit_counter
  476. from `CRM_LISTA_ZASOBOW` as z
  477. where {$sql_where}
  478. order by hit_counter DESC, z.`ID` DESC
  479. limit {$sql_limit} offset {$sql_offset}
  480. ";
  481. $res = $this->db->query($sql);
  482. while ($r = $this->db->fetch($res)) {
  483. $list[$r->ID] = $r;
  484. }
  485. return $list;
  486. }
  487. }
  488. class CrmSearchWskaznik extends CrmSearchBase {
  489. function _get_sql_where() {
  490. $sql_where = "
  491. w.`A_STATUS` in('NORMAL','WAITING')
  492. and p.`A_STATUS` in('NORMAL','WAITING')
  493. and z.`A_STATUS` in('NORMAL','WAITING')
  494. and (w.`OPIS_ZASOB` like '%{$this->q}%' or w.`ID_ZASOB` like '{$this->q}' or w.`ID_PROCES` like '{$this->q}' )
  495. ";
  496. return $sql_where;
  497. }
  498. function _fetch_total() {
  499. $total = 0;
  500. $sql_where = $this->_get_sql_where();
  501. $sql = "select count(1) as cnt
  502. from `CRM_WSKAZNIK` as w
  503. join `CRM_PROCES` as p on(p.`ID`=w.`ID_PROCES`)
  504. join `CRM_LISTA_ZASOBOW` as z on(z.`ID`=w.`ID_ZASOB`)
  505. where {$sql_where}
  506. ";
  507. $res = $this->db->query($sql);
  508. if ($r = $this->db->fetch($res)) {
  509. $total = $r->cnt;
  510. }
  511. return $total;
  512. }
  513. function _fetch_list() {
  514. $list = array();
  515. $sql_where = $this->_get_sql_where();
  516. $sql_limit = V::get('limit', 10, $this->params, 'int');
  517. $sql_offset = V::get('offset', 0, $this->params, 'int');
  518. $sql = "select w.`ID`, w.`ID_PROCES`, w.`ID_ZASOB`, w.`OPIS_ZASOB`
  519. , if(w.`ID_ZASOB`='{$this->q}', 100
  520. , if(w.`ID_PROCES`='{$this->q}', 100
  521. , if(w.`OPIS_ZASOB`='{$this->q}', 99
  522. , if(w.`OPIS_ZASOB` like '{$this->q}%', 90
  523. , if(w.`OPIS_ZASOB` like '%{$this->q}%', 80
  524. , 0
  525. )
  526. )
  527. )
  528. )
  529. ) as hit_counter
  530. from `CRM_WSKAZNIK` as w
  531. join `CRM_PROCES` as p on(p.`ID`=w.`ID_PROCES`)
  532. join `CRM_LISTA_ZASOBOW` as z on(z.`ID`=w.`ID_ZASOB`)
  533. where {$sql_where}
  534. order by hit_counter DESC, w.`ID` DESC
  535. limit {$sql_limit} offset {$sql_offset}
  536. ";
  537. $res = $this->db->query($sql);
  538. while ($r = $this->db->fetch($res)) {
  539. $list[$r->ID] = $r;
  540. }
  541. return $list;
  542. }
  543. }