skill.lib.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * This class provides methods for the notebook management.
  5. * Include/require it in your code to use its features.
  6. * @package chamilo.library
  7. */
  8. /**
  9. * Code
  10. */
  11. /**
  12. * @package chamilo.library
  13. */
  14. define ('SKILL_TYPE_REQUIREMENT', 'required');
  15. define ('SKILL_TYPE_ACQUIRED', 'acquired');
  16. define ('SKILL_TYPE_BOTH', 'both');
  17. require_once api_get_path(LIBRARY_PATH).'model.lib.php';
  18. class SkillProfile extends Model {
  19. var $columns = array('id', 'name','description');
  20. public function __construct() {
  21. $this->table = Database::get_main_table(TABLE_MAIN_SKILL_PROFILE);
  22. $this->table_rel_profile = Database::get_main_table(TABLE_MAIN_SKILL_REL_PROFILE);
  23. }
  24. public function get_profiles() {
  25. $sql = "SELECT * FROM $this->table p INNER JOIN $this->table_rel_profile sp ON(p.id = sp.profile_id) ";
  26. $result = Database::query($sql);
  27. $profiles = Database::store_result($result,'ASSOC');
  28. return $profiles;
  29. }
  30. public function save($params, $show_query = false) {
  31. if (!empty($params)) {
  32. $profile_id = parent::save($params, $show_query);
  33. if ($profile_id) {
  34. $skill_rel_profile = new SkillRelProfile();
  35. if (isset($params['skills'])) {
  36. foreach($params['skills'] as $skill_id) {
  37. $attributes = array('skill_id' => $skill_id, 'profile_id'=>$profile_id);
  38. $skill_rel_profile->save($attributes);
  39. }
  40. }
  41. return $profile_id;
  42. }
  43. }
  44. return false;
  45. }
  46. }
  47. class SkillRelProfile extends Model {
  48. var $columns = array('id', 'skill_id', 'profile_id');
  49. public function __construct() {
  50. $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_PROFILE);
  51. }
  52. public function get_skills_by_profile($profile_id) {
  53. $skills = $this->get_all(array('where'=>array('profile_id = ? ' => $profile_id)));
  54. $return_array = array();
  55. if (!empty($skills)) {
  56. foreach($skills as $skill_data) {
  57. $return_array[] = $skill_data['skill_id'];
  58. }
  59. }
  60. return $return_array;
  61. }
  62. }
  63. class SkillRelSkill extends Model {
  64. var $columns = array('skill_id', 'parent_id','relation_type', 'level');
  65. public function __construct() {
  66. $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_SKILL);
  67. }
  68. /**
  69. * Gets an element
  70. */
  71. public function get_skill_info($id) {
  72. if (empty($id)) { return array(); }
  73. $result = Database::select('*',$this->table, array('where'=>array('skill_id = ?'=>intval($id))), 'first');
  74. return $result;
  75. }
  76. public function get_skill_parents($skill_id, $add_child_info = true) {
  77. $skill_id = intval($skill_id);
  78. $sql = 'SELECT child.* FROM '.$this->table.' child LEFT JOIN '.$this->table.' parent
  79. ON child.parent_id = parent.skill_id
  80. WHERE child.skill_id = '.$skill_id.' ';
  81. $result = Database::query($sql);
  82. $skill = Database::store_result($result,'ASSOC');
  83. $skill = isset($skill[0]) ? $skill[0] : null;
  84. $parents = array();
  85. if (!empty($skill)) {
  86. if ($skill['parent_id'] != null) {
  87. $parents = self::get_skill_parents($skill['parent_id']);
  88. }
  89. if ($add_child_info) {
  90. $parents[] = $skill;
  91. }
  92. }
  93. return $parents;
  94. }
  95. public function get_direct_parents($skill_id) {
  96. $skill_id = intval($skill_id);
  97. $sql = 'SELECT parent_id as skill_id FROM '.$this->table.'
  98. WHERE skill_id = '.$skill_id.' ';
  99. $result = Database::query($sql);
  100. $skill = Database::store_result($result,'ASSOC');
  101. $skill = isset($skill[0]) ? $skill[0] : null;
  102. $parents = array();
  103. if (!empty($skill)) {
  104. $parents[] = $skill;
  105. }
  106. return $parents;
  107. }
  108. public function get_children($skill_id, $load_user_data = false, $user_id = false) {
  109. $skills = $this->find('all', array('where'=> array('parent_id = ? '=> $skill_id)));
  110. $skill_obj = new Skill();
  111. $skill_rel_user = new SkillRelUser();
  112. if ($load_user_data) {
  113. $passed_skills = $skill_rel_user->get_user_skills($user_id);
  114. $done_skills = array();
  115. foreach($passed_skills as $done_skill) {
  116. $done_skills[] = $done_skill['skill_id'];
  117. }
  118. }
  119. if (!empty($skills)) {
  120. foreach ($skills as &$skill) {
  121. $skill['data'] = $skill_obj->get($skill['skill_id']);
  122. if (isset($skill['data']) && !empty($skill['data'])) {
  123. if (!empty($done_skills)) {
  124. $skill['data']['passed'] = 0;
  125. if (in_array($skill['skill_id'], $done_skills)) {
  126. $skill['data']['passed'] = 1;
  127. }
  128. }
  129. } else {
  130. $skill = null;
  131. }
  132. }
  133. }
  134. return $skills;
  135. }
  136. function update_by_skill($params) {
  137. $result = Database::update($this->table, $params, array('skill_id = ? '=> $params['skill_id']));
  138. if ($result) {
  139. return true;
  140. }
  141. return false;
  142. }
  143. function relation_exists($skill_id, $parent_id) {
  144. $result = $this->find('all', array('where'=>array('skill_id = ? AND parent_id = ?' => array($skill_id, $parent_id))));
  145. if (!empty($result)) {
  146. return true;
  147. }
  148. return false;
  149. }
  150. }
  151. /**
  152. * @package chamilo.library
  153. */
  154. class SkillRelGradebook extends Model {
  155. var $columns = array('id', 'gradebook_id','skill_id');
  156. public function __construct() {
  157. $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_GRADEBOOK);
  158. }
  159. public function exists_gradebook_skill($gradebook_id, $skill_id) {
  160. $result = $this->find('all', array('where'=>array('gradebook_id = ? AND skill_id = ?' => array($gradebook_id, $skill_id))));
  161. if (!empty($result)) {
  162. return true;
  163. }
  164. return false;
  165. }
  166. /**
  167. * Gets an element
  168. */
  169. public function get_skill_info($skill_id, $gradebook_id) {
  170. if (empty($skill_id)) { return array(); }
  171. $result = Database::select('*',$this->table, array('where'=>array('skill_id = ? AND gradebook_id = ? '=>array($skill_id, $gradebook_id))),'first');
  172. return $result;
  173. }
  174. public function update_gradebooks_by_skill($skill_id, $gradebook_list) {
  175. $original_gradebook_list = $this->find('all', array('where'=>array('skill_id = ?' => array($skill_id))));
  176. $gradebooks_to_remove = array();
  177. $gradebooks_to_add = array();
  178. $original_gradebook_list_ids = array();
  179. if (!empty($original_gradebook_list)) {
  180. foreach ($original_gradebook_list as $gradebook) {
  181. if (!in_array($gradebook['gradebook_id'], $gradebook_list)) {
  182. $gradebooks_to_remove[] = $gradebook['id'];
  183. }
  184. }
  185. foreach($original_gradebook_list as $gradebook_item) {
  186. $original_gradebook_list_ids[] = $gradebook_item['gradebook_id'];
  187. }
  188. }
  189. if (!empty($gradebook_list))
  190. foreach($gradebook_list as $gradebook_id) {
  191. if (!in_array($gradebook_id, $original_gradebook_list_ids)) {
  192. $gradebooks_to_add[] = $gradebook_id;
  193. }
  194. }
  195. //var_dump($gradebooks_to_add, $gradebooks_to_remove);
  196. if (!empty($gradebooks_to_remove)) {
  197. foreach($gradebooks_to_remove as $id) {
  198. $this->delete($id);
  199. }
  200. }
  201. if (!empty($gradebooks_to_add)) {
  202. foreach($gradebooks_to_add as $gradebook_id) {
  203. $attributes = array('skill_id' => $skill_id, 'gradebook_id' => $gradebook_id);
  204. $this->save($attributes);
  205. }
  206. }
  207. }
  208. function update_by_skill($params) {
  209. $skill_info = $this->exists_gradebook_skill($params['gradebook_id'], $params['skill_id']);
  210. if ($skill_info) {
  211. return;
  212. } else {
  213. $result = $this->save($params);
  214. }
  215. if ($result) {
  216. return true;
  217. }
  218. return false;
  219. }
  220. }
  221. /**
  222. * @package chamilo.library
  223. */
  224. class SkillRelUser extends Model {
  225. var $columns = array('id', 'user_id','skill_id','acquired_skill_at','assigned_by');
  226. public function __construct() {
  227. $this->table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
  228. //$this->table_user = Database::get_main_table(TABLE_MAIN_USER);
  229. }
  230. public function get_user_by_skills($skill_list) {
  231. $users = array();
  232. if (!empty($skill_list)) {
  233. $skill_list = array_map('intval', $skill_list);
  234. $skill_list = implode("', '", $skill_list);
  235. $sql = "SELECT user_id FROM {$this->table} WHERE skill_id IN ('$skill_list') ";
  236. $result = Database::query($sql);
  237. $users = Database::store_result($result, 'ASSOC');
  238. }
  239. return $users;
  240. }
  241. public function get_user_skills($user_id) {
  242. if (empty($user_id)) { return array(); }
  243. $result = Database::select('skill_id',$this->table, array('where'=>array('user_id = ?'=>intval($user_id))), 'all');
  244. return $result;
  245. }
  246. }
  247. class Skill extends Model {
  248. var $columns = array('id', 'name','description', 'access_url_id');
  249. var $required = array('name');
  250. /** Array of colours by depth, for the coffee wheel. Each depth has 4 col */
  251. var $colours = array(
  252. 0 => array('#f9f0ab', '#ecc099', '#e098b0', '#ebe378'),
  253. 1 => array('#d5dda1', '#4a5072', '#8dae43', '#72659d'),
  254. 2 => array('#b28647', '#2e6093', '#393e64', '#1e8323'),
  255. 3 => array('#9f6652', '#9f6652', '#9f6652', '#9f6652'),
  256. 4 => array('#af643c', '#af643c', '#af643c', '#af643c'),
  257. 5 => array('#72659d', '#72659d', '#72659d', '#72659d'),
  258. 6 => array('#8a6e9e', '#8a6e9e', '#8a6e9e', '#8a6e9e'),
  259. 7 => array('#92538c', '#92538c', '#92538c', '#92538c'),
  260. 8 => array('#2e6093', '#2e6093', '#2e6093', '#2e6093'),
  261. 9 => array('#3a5988', '#3a5988', '#3a5988', '#3a5988'),
  262. 10 => array('#393e64', '#393e64', '#393e64', '#393e64'),
  263. );
  264. public function __construct() {
  265. $this->table = Database::get_main_table(TABLE_MAIN_SKILL);
  266. $this->table_skill_rel_gradebook = Database::get_main_table(TABLE_MAIN_SKILL_REL_GRADEBOOK);
  267. $this->table_skill_rel_user = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
  268. $this->table_course = Database::get_main_table(TABLE_MAIN_COURSE);
  269. $this->table_skill_rel_skill = Database::get_main_table(TABLE_MAIN_SKILL_REL_SKILL);
  270. $this->table_gradebook = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  271. }
  272. function get_skill_info($id) {
  273. $skill_rel_skill = new SkillRelSkill();
  274. $skill_info = $this->get($id);
  275. if (!empty($skill_info)) {
  276. $skill_info['extra'] = $skill_rel_skill->get_skill_info($id);
  277. $skill_info['gradebooks'] = self::get_gradebooks_by_skill($id);
  278. }
  279. return $skill_info;
  280. }
  281. function get_skills_info($skill_list) {
  282. $skill_list = array_map('intval', $skill_list);
  283. $skill_list = implode("', '", $skill_list);
  284. $sql = "SELECT * FROM {$this->table} WHERE id IN ('$skill_list') ";
  285. $result = Database::query($sql);
  286. $users = Database::store_result($result, 'ASSOC');
  287. return $users;
  288. }
  289. function get_all($load_user_data = false, $user_id = false, $id = null, $parent_id = null) {
  290. $id_condition = '';
  291. if (isset($id)) {
  292. $id = intval($id);
  293. $id_condition = " WHERE s.id = $id";
  294. }
  295. if (isset($parent_id)) {
  296. $parent_id = intval($parent_id);
  297. if (empty($id_condition)) {
  298. $id_condition = "WHERE ss.parent_id = $parent_id";
  299. } else {
  300. $id_condition = " AND ss.parent_id = $parent_id";
  301. }
  302. }
  303. $sql = "SELECT s.id, s.name, s.description, ss.parent_id, ss.relation_type".
  304. " FROM {$this->table} s INNER JOIN {$this->table_skill_rel_skill} ss ON (s.id = ss.skill_id) $id_condition";
  305. $result = Database::query($sql);
  306. $skills = array();
  307. if (Database::num_rows($result)) {
  308. while ($row = Database::fetch_array($result, 'ASSOC')) {
  309. $skill_rel_skill = new SkillRelSkill();
  310. $a = $skill_rel_skill->get_skill_parents($row['id']);
  311. $row['level'] = count($a)-1;
  312. $row['gradebooks'] = self::get_gradebooks_by_skill($row['id']);
  313. $skills[$row['id']] = $row;
  314. }
  315. }
  316. if ($load_user_data && $user_id) {
  317. $passed_skills = $this->get_user_skills($user_id);
  318. foreach ($skills as &$skill) {
  319. $skill['done_by_user'] = 0;
  320. if (in_array($skill['id'], $passed_skills)) {
  321. $skill['done_by_user'] = 1;
  322. }
  323. }
  324. }
  325. return $skills;
  326. }
  327. function get_gradebooks_by_skill($skill_id) {
  328. $skill_id = intval($skill_id);
  329. $sql = "SELECT g.* FROM {$this->table_gradebook} g INNER JOIN {$this->table_skill_rel_gradebook} sg
  330. ON g.id = sg.gradebook_id
  331. WHERE sg.skill_id = $skill_id";
  332. $result = Database::query($sql);
  333. $result = Database::store_result($result,'ASSOC');
  334. return $result;
  335. }
  336. function get_children($skill_id, $load_user_data = false) {
  337. $skill_rel_skill = new SkillRelSkill();
  338. if ($load_user_data) {
  339. $user_id = api_get_user_id();
  340. $skills = $skill_rel_skill->get_children($skill_id, true, $user_id);
  341. } else {
  342. $skills = $skill_rel_skill->get_children($skill_id);
  343. }
  344. return $skills;
  345. }
  346. /**
  347. * All parents from root to n
  348. */
  349. function get_parents($skill_id) {
  350. $skill_rel_skill = new SkillRelSkill();
  351. $skills = $skill_rel_skill->get_skill_parents($skill_id, true);
  352. foreach($skills as &$skill) {
  353. $skill['data'] = self::get($skill['skill_id']);
  354. }
  355. return $skills;
  356. }
  357. /**
  358. * All direct parents
  359. */
  360. function get_direct_parents($skill_id) {
  361. $skill_rel_skill = new SkillRelSkill();
  362. $skills = $skill_rel_skill->get_direct_parents($skill_id, true);
  363. foreach($skills as &$skill) {
  364. $skill['data'] = self::get($skill['skill_id']);
  365. $skill_info2 = $skill_rel_skill->get_skill_info($skill['skill_id']);
  366. $skill['data']['parent_id'] = $skill_info2['parent_id'];
  367. }
  368. return $skills;
  369. }
  370. public function add($params) {
  371. if (!isset($params['parent_id'])) {
  372. $params['parent_id'] = 1;
  373. }
  374. $skill_rel_skill = new SkillRelSkill();
  375. $skill_rel_gradebook = new SkillRelGradebook();
  376. //Saving name, description
  377. $skill_id = $this->save($params);
  378. if ($skill_id) {
  379. //Saving skill_rel_skill (parent_id, relation_type)
  380. $attributes = array(
  381. 'skill_id' => $skill_id,
  382. 'parent_id' => $params['parent_id'],
  383. 'relation_type' => $params['relation_type'],
  384. //'level' => $params['level'],
  385. );
  386. $skill_rel_skill->save($attributes);
  387. if (!empty($params['gradebook_id'])) {
  388. foreach ($params['gradebook_id'] as $gradebook_id) {
  389. $attributes = array();
  390. $attributes['gradebook_id'] = $gradebook_id;
  391. $attributes['skill_id'] = $skill_id;
  392. $skill_rel_gradebook->save($attributes);
  393. }
  394. }
  395. return $skill_id;
  396. }
  397. return null;
  398. }
  399. public function edit($params) {
  400. if (!isset($params['parent_id'])) {
  401. $params['parent_id'] = 1;
  402. }
  403. $skill_rel_skill = new SkillRelSkill();
  404. $skill_rel_gradebook = new SkillRelGradebook();
  405. //Saving name, description
  406. $this->update($params);
  407. $skill_id = $params['id'];
  408. if ($skill_id) {
  409. //Saving skill_rel_skill (parent_id, relation_type)
  410. $attributes = array(
  411. 'skill_id' => $skill_id,
  412. 'parent_id' => $params['parent_id'],
  413. 'relation_type' => $params['relation_type'],
  414. //'level' => $params['level'],
  415. );
  416. $skill_rel_skill->update_by_skill($attributes);
  417. $skill_rel_gradebook->update_gradebooks_by_skill($skill_id, $params['gradebook_id']);
  418. return $skill_id;
  419. }
  420. return null;
  421. }
  422. /**
  423. * Return true if the user has the skill
  424. *
  425. * @param int $userId User's id
  426. * @param int $skillId Skill's id
  427. * @param int $checkInParents if true, function will search also in parents of the given skill id
  428. *
  429. * @return bool
  430. */
  431. public function user_has_skill($user_id, $skill_id) {
  432. $skills = $this->get_user_skills($user_id);
  433. foreach($skills as $my_skill_id) {
  434. if ($my_skill_id == $skill_id) {
  435. return true;
  436. }
  437. }
  438. return false;
  439. }
  440. public function add_skill_to_user($user_id, $gradebook_id) {
  441. $skill_gradebook = new SkillRelGradebook();
  442. $skill_rel_user = new SkillRelUser();
  443. $skill_gradebooks = $skill_gradebook->get_all(array('where'=>array('gradebook_id = ?' =>$gradebook_id)));
  444. if (!empty($skill_gradebooks)) {
  445. foreach ($skill_gradebooks as $skill_gradebook) {
  446. $user_has_skill = $this->user_has_skill($user_id, $skill_gradebook['skill_id']);
  447. if (!$user_has_skill) {
  448. $params = array( 'user_id' => $user_id,
  449. 'skill_id' => $skill_gradebook['skill_id'],
  450. 'acquired_skill_at' => api_get_utc_datetime(),
  451. );
  452. $skill_rel_user->save($params);
  453. }
  454. }
  455. }
  456. }
  457. /**
  458. * Get user's skills
  459. *
  460. * @param int $userId User's id
  461. */
  462. public function get_user_skills($user_id, $get_skill_data = false) {
  463. $user_id = intval($user_id);
  464. $sql = 'SELECT DISTINCT s.id, s.name FROM '.$this->table_skill_rel_user.' u INNER JOIN '.$this->table.' s
  465. ON u.skill_id = s.id
  466. WHERE user_id = '.$user_id;
  467. $result = Database::query($sql);
  468. $skills = Database::store_result($result, 'ASSOC');
  469. $clean_skill = array();
  470. if (!empty($skills)) {
  471. foreach ($skills as $skill) {
  472. if ($get_skill_data) {
  473. $clean_skill[$skill['id']] = $skill;
  474. } else {
  475. $clean_skill[$skill['id']] = $skill['id'];
  476. }
  477. }
  478. }
  479. return $clean_skill;
  480. }
  481. public function get_skills_tree($user_id = null, $return_flat_array = false) {
  482. if (isset($user_id) && !empty($user_id)) {
  483. $skills = $this->get_all(true, $user_id);
  484. } else {
  485. $skills = $this->get_all();
  486. }
  487. $refs = array();
  488. $skills_tree = null;
  489. // Create references for all nodes
  490. $flat_array = array();
  491. if (!empty($skills)) {
  492. foreach($skills as &$skill) {
  493. if ($skill['parent_id'] == 0) {
  494. $skill['parent_id'] = 'root';
  495. }
  496. $skill['data'] = array('parent_id' => $skill['parent_id']); // because except main keys (id, name, children) others keys are not saved while in the space tree
  497. if ($user_id) {
  498. $skill['data']['achieved'] = $this->user_has_skill($user_id, $skill['id']);
  499. }
  500. $refs[$skill['id']] = &$skill;
  501. $flat_array[$skill['id']] = &$skill;
  502. }
  503. // Moving node to the children index of their parents
  504. foreach($skills as $skillInd => &$skill) {
  505. $refs[$skill['parent_id']]['children'][] = &$skill;
  506. $flat_array[$skillInd] = $skill;
  507. }
  508. $skills_tree = array(
  509. 'name' => get_lang('SkillRootName'),
  510. 'id' => 'root',
  511. 'children' => $refs['root']['children'],
  512. 'data' => array()
  513. );
  514. }
  515. //var_dump($flat_array);exit;
  516. if ($return_flat_array) {
  517. return $flat_array;
  518. }
  519. unset($skills);
  520. return $skills_tree;
  521. }
  522. /**
  523. * Get skills tree as a simplified JSON structure
  524. *
  525. */
  526. public function get_skills_tree_json($user_id = null, $return_flat_array = false) {
  527. $tree = $this->get_skills_tree($user_id, $return_flat_array);
  528. $simple_tree = array();
  529. foreach ($tree['children'] as $element) {
  530. $simple_tree[] = array('name' => $element['name'], 'children' => $this->get_skill_json($element['children']));
  531. }
  532. //$s = array('\/');
  533. //return str_replace($s,'/',json_encode($simple_tree[0]['children']));
  534. return json_encode($simple_tree[0]['children']);
  535. }
  536. /**
  537. * Get JSON element
  538. */
  539. public function get_skill_json($subtree, $depth = 1) {
  540. $simple_sub_tree = array();
  541. if (is_array($subtree)) {
  542. foreach ($subtree as $elem) {
  543. $tmp = array();
  544. $tmp['name'] = $elem['name'];//.'<a href="">'.$elem['id'].'</a>';
  545. if (is_array($elem['children'])) {
  546. $tmp['children'] = $this->get_skill_json($elem['children'], $depth+1);
  547. } else {
  548. $tmp['colour'] = $this->colours[$depth][rand(0,3)];
  549. }
  550. $simple_sub_tree[] = $tmp;
  551. }
  552. return $simple_sub_tree;
  553. }
  554. return null;
  555. }
  556. }