extra_field_value.lib.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
  4. use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
  5. use Chamilo\CoreBundle\Entity\ExtraFieldValues;
  6. use Chamilo\CoreBundle\Entity\Tag;
  7. use ChamiloSession as Session;
  8. /**
  9. * Class ExtraFieldValue
  10. * Declaration for the ExtraFieldValue class, managing the values in extra
  11. * fields for any data type.
  12. *
  13. * @package chamilo.library
  14. */
  15. class ExtraFieldValue extends Model
  16. {
  17. public $type = '';
  18. public $columns = [
  19. 'id',
  20. 'field_id',
  21. 'value',
  22. 'comment',
  23. 'item_id',
  24. 'created_at',
  25. 'updated_at',
  26. ];
  27. /** @var ExtraField */
  28. public $extraField;
  29. /**
  30. * Formats the necessary elements for the given datatype.
  31. *
  32. * @param string $type The type of data to which this extra field
  33. * applies (user, course, session, ...)
  34. *
  35. * @assert (-1) === false
  36. */
  37. public function __construct($type)
  38. {
  39. parent::__construct();
  40. $this->type = $type;
  41. $extraField = new ExtraField($this->type);
  42. $this->extraField = $extraField;
  43. $this->table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
  44. $this->table_handler_field = Database::get_main_table(TABLE_EXTRA_FIELD);
  45. }
  46. /**
  47. * @return ExtraField
  48. */
  49. public function getExtraField()
  50. {
  51. return $this->extraField;
  52. }
  53. /**
  54. * Gets the number of values stored in the table (all fields together)
  55. * for this type of resource.
  56. *
  57. * @return int Number of rows in the table
  58. * @assert () !== false
  59. */
  60. public function get_count()
  61. {
  62. $em = Database::getManager();
  63. $query = $em->getRepository('ChamiloCoreBundle:ExtraFieldValues')->createQueryBuilder('e');
  64. $query->select('count(e.id)');
  65. $query->where('e.extraFieldType = :type');
  66. $query->setParameter('type', $this->getExtraField()->getExtraFieldType());
  67. return $query->getQuery()->getSingleScalarResult();
  68. }
  69. /**
  70. * Save the extra fields values
  71. * In order to save this function needs a item_id (user id, course id, etc)
  72. * This function is used with $extraField->addElements().
  73. *
  74. * @param array $params array for the insertion into the *_field_values table
  75. * @param bool $onlySubmittedFields Only save parameters in the $param array
  76. * @param bool $showQuery
  77. * @param array $saveOnlyThisFields
  78. * @param array $avoidFields do not insert/modify this field
  79. *
  80. * @return mixed false on empty params, void otherwise
  81. * @assert (array()) === false
  82. */
  83. public function saveFieldValues(
  84. $params,
  85. $onlySubmittedFields = false,
  86. $showQuery = false,
  87. $saveOnlyThisFields = [],
  88. $avoidFields = []
  89. ) {
  90. foreach ($params as $key => $value) {
  91. $found = strpos($key, '__persist__');
  92. if ($found === false) {
  93. continue;
  94. }
  95. $tempKey = str_replace('__persist__', '', $key);
  96. if (!isset($params[$tempKey])) {
  97. $params[$tempKey] = [];
  98. }
  99. }
  100. if (empty($params['item_id'])) {
  101. return false;
  102. }
  103. $type = $this->getExtraField()->getExtraFieldType();
  104. $extraField = new ExtraField($this->type);
  105. $extraFields = $extraField->get_all(null, 'option_order');
  106. // Parse params.
  107. foreach ($extraFields as $fieldDetails) {
  108. $field_variable = $fieldDetails['variable'];
  109. // if the field is not visible to the user in the end, we need to apply special rules
  110. if ($fieldDetails['visible_to_self'] != 1) {
  111. //only admins should be able to add those values
  112. if (!api_is_platform_admin(true, true)) {
  113. // although if not admin but sent through a CLI script, we should accept it as well
  114. if (PHP_SAPI != 'cli') {
  115. continue; //not a CLI script, so don't write the value to DB
  116. }
  117. }
  118. }
  119. if ($onlySubmittedFields && !isset($params['extra_'.$field_variable])) {
  120. continue;
  121. }
  122. if (!empty($avoidFields)) {
  123. if (in_array($field_variable, $avoidFields)) {
  124. continue;
  125. }
  126. }
  127. if (!empty($saveOnlyThisFields)) {
  128. if (!in_array($field_variable, $saveOnlyThisFields)) {
  129. continue;
  130. }
  131. }
  132. $value = '';
  133. if (isset($params['extra_'.$field_variable])) {
  134. $value = $params['extra_'.$field_variable];
  135. }
  136. $extraFieldInfo = $this->getExtraField()->get_handler_field_info_by_field_variable($field_variable);
  137. if (!$extraFieldInfo) {
  138. continue;
  139. }
  140. $commentVariable = 'extra_'.$field_variable.'_comment';
  141. $comment = isset($params[$commentVariable]) ? $params[$commentVariable] : null;
  142. $dirPermissions = api_get_permissions_for_new_directories();
  143. switch ($extraFieldInfo['field_type']) {
  144. case ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
  145. case ExtraField::FIELD_TYPE_GEOLOCALIZATION:
  146. if (!empty($value)) {
  147. if (isset($params['extra_'.$extraFieldInfo['variable'].'_coordinates'])) {
  148. $value = $value.'::'.$params['extra_'.$extraFieldInfo['variable'].'_coordinates'];
  149. }
  150. $newParams = [
  151. 'item_id' => $params['item_id'],
  152. 'field_id' => $extraFieldInfo['id'],
  153. 'value' => $value,
  154. 'comment' => $comment,
  155. ];
  156. self::save($newParams, $showQuery);
  157. }
  158. break;
  159. case ExtraField::FIELD_TYPE_TAG:
  160. if ($type == EntityExtraField::USER_FIELD_TYPE) {
  161. UserManager::delete_user_tags(
  162. $params['item_id'],
  163. $extraFieldInfo['id']
  164. );
  165. UserManager::process_tags(
  166. $value,
  167. $params['item_id'],
  168. $extraFieldInfo['id']
  169. );
  170. break;
  171. }
  172. $em = Database::getManager();
  173. $currentTags = $em
  174. ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
  175. ->findBy([
  176. 'fieldId' => $extraFieldInfo['id'],
  177. 'itemId' => $params['item_id'],
  178. ]);
  179. foreach ($currentTags as $extraFieldtag) {
  180. $em->remove($extraFieldtag);
  181. }
  182. $em->flush();
  183. $tagValues = is_array($value) ? $value : [$value];
  184. $tags = [];
  185. foreach ($tagValues as $tagValue) {
  186. if (empty($tagValue)) {
  187. continue;
  188. }
  189. $tagsResult = $em->getRepository('ChamiloCoreBundle:Tag')
  190. ->findBy([
  191. 'tag' => $tagValue,
  192. 'fieldId' => $extraFieldInfo['id'],
  193. ]);
  194. if (empty($tagsResult)) {
  195. $tag = new Tag();
  196. $tag->setFieldId($extraFieldInfo['id']);
  197. $tag->setTag($tagValue);
  198. $tags[] = $tag;
  199. } else {
  200. $tags = array_merge($tags, $tagsResult);
  201. }
  202. }
  203. foreach ($tags as $tag) {
  204. $tagUses = $em
  205. ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
  206. ->findBy([
  207. 'tagId' => $tag->getId(),
  208. ]);
  209. $tag->setCount(count($tagUses) + 1);
  210. $em->persist($tag);
  211. }
  212. $em->flush();
  213. foreach ($tags as $tag) {
  214. $fieldRelTag = new ExtraFieldRelTag();
  215. $fieldRelTag->setFieldId($extraFieldInfo['id']);
  216. $fieldRelTag->setItemId($params['item_id']);
  217. $fieldRelTag->setTagId($tag->getId());
  218. $em->persist($fieldRelTag);
  219. }
  220. $em->flush();
  221. break;
  222. case ExtraField::FIELD_TYPE_FILE_IMAGE:
  223. $fileDir = $fileDirStored = '';
  224. switch ($this->type) {
  225. case 'course':
  226. $fileDir = api_get_path(SYS_UPLOAD_PATH)."courses/";
  227. $fileDirStored = "courses/";
  228. break;
  229. case 'session':
  230. $fileDir = api_get_path(SYS_UPLOAD_PATH)."sessions/";
  231. $fileDirStored = "sessions/";
  232. break;
  233. case 'user':
  234. $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
  235. $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
  236. break;
  237. case 'work':
  238. $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
  239. $fileDirStored = 'work/';
  240. break;
  241. }
  242. $fileName = ExtraField::FIELD_TYPE_FILE_IMAGE."_{$params['item_id']}.png";
  243. if (!file_exists($fileDir)) {
  244. mkdir($fileDir, $dirPermissions, true);
  245. }
  246. if (!empty($value['tmp_name']) && isset($value['error']) && $value['error'] == 0) {
  247. // Crop the image to adjust 16:9 ratio
  248. if (isset($params['extra_'.$field_variable.'_crop_result'])) {
  249. $crop = new Image($value['tmp_name']);
  250. $crop->crop($params['extra_'.$field_variable.'_crop_result']);
  251. }
  252. $imageExtraField = new Image($value['tmp_name']);
  253. $imageExtraField->resize(400);
  254. $imageExtraField->send_image($fileDir.$fileName, -1, 'png');
  255. $newParams = [
  256. 'item_id' => $params['item_id'],
  257. 'field_id' => $extraFieldInfo['id'],
  258. 'value' => $fileDirStored.$fileName,
  259. 'comment' => $comment,
  260. ];
  261. $this->save($newParams);
  262. }
  263. break;
  264. case ExtraField::FIELD_TYPE_FILE:
  265. $fileDir = $fileDirStored = '';
  266. switch ($this->type) {
  267. case 'course':
  268. $fileDir = api_get_path(SYS_UPLOAD_PATH).'courses/';
  269. $fileDirStored = "courses/";
  270. break;
  271. case 'session':
  272. $fileDir = api_get_path(SYS_UPLOAD_PATH).'sessions/';
  273. $fileDirStored = "sessions/";
  274. break;
  275. case 'user':
  276. $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
  277. $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
  278. break;
  279. case 'work':
  280. $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
  281. $fileDirStored = "work/";
  282. break;
  283. case 'scheduled_announcement':
  284. $fileDir = api_get_path(SYS_UPLOAD_PATH).'scheduled_announcement/';
  285. $fileDirStored = 'scheduled_announcement/';
  286. break;
  287. }
  288. $cleanedName = api_replace_dangerous_char($value['name']);
  289. $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
  290. if (!file_exists($fileDir)) {
  291. mkdir($fileDir, $dirPermissions, true);
  292. }
  293. if (!empty($value['tmp_name']) && isset($value['error']) && $value['error'] == 0) {
  294. $cleanedName = api_replace_dangerous_char($value['name']);
  295. $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
  296. moveUploadedFile($value, $fileDir.$fileName);
  297. $new_params = [
  298. 'item_id' => $params['item_id'],
  299. 'field_id' => $extraFieldInfo['id'],
  300. 'value' => $fileDirStored.$fileName,
  301. ];
  302. if ($this->type !== 'session' && $this->type !== 'course') {
  303. $new_params['comment'] = $comment;
  304. }
  305. $this->save($new_params);
  306. }
  307. break;
  308. case ExtraField::FIELD_TYPE_CHECKBOX:
  309. $fieldToSave = 0;
  310. if (is_array($value)) {
  311. if (isset($value['extra_'.$field_variable])) {
  312. $fieldToSave = 1;
  313. }
  314. }
  315. $newParams = [
  316. 'item_id' => $params['item_id'],
  317. 'field_id' => $extraFieldInfo['id'],
  318. 'value' => $fieldToSave,
  319. 'comment' => $comment,
  320. ];
  321. $this->save($newParams);
  322. break;
  323. default:
  324. $newParams = [
  325. 'item_id' => $params['item_id'],
  326. 'field_id' => $extraFieldInfo['id'],
  327. 'value' => $value,
  328. 'comment' => $comment,
  329. ];
  330. $this->save($newParams, $showQuery);
  331. }
  332. }
  333. }
  334. /**
  335. * Save values in the *_field_values table.
  336. *
  337. * @param array $params Structured array with the values to save
  338. * @param bool $showQuery Whether to show the insert query (passed to the parent save() method)
  339. *
  340. * @return mixed The result sent from the parent method
  341. * @assert (array()) === false
  342. */
  343. public function save($params, $showQuery = false)
  344. {
  345. $extra_field = $this->getExtraField();
  346. // Setting value to insert.
  347. $value = $params['value'];
  348. $value_to_insert = null;
  349. if (is_array($value)) {
  350. $value_to_insert = implode(';', $value);
  351. } else {
  352. $value_to_insert = $value;
  353. }
  354. $params['value'] = $value_to_insert;
  355. // If field id exists
  356. if (isset($params['field_id'])) {
  357. $extraFieldInfo = $extra_field->get($params['field_id']);
  358. } else {
  359. // Try the variable
  360. $extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable(
  361. $params['variable']
  362. );
  363. $params['field_id'] = $extraFieldInfo['id'];
  364. }
  365. if ($extraFieldInfo) {
  366. switch ($extraFieldInfo['field_type']) {
  367. case ExtraField::FIELD_TYPE_RADIO:
  368. case ExtraField::FIELD_TYPE_SELECT:
  369. break;
  370. case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
  371. //$field_options = $session_field_option->get_field_options_by_field($params['field_id']);
  372. //$params['field_value'] = split(';', $value_to_insert);
  373. /*
  374. if ($field_options) {
  375. $check = false;
  376. foreach ($field_options as $option) {
  377. if (in_array($option['option_value'], $values)) {
  378. $check = true;
  379. break;
  380. }
  381. }
  382. if (!$check) {
  383. return false; //option value not found
  384. }
  385. } else {
  386. return false; //enumerated type but no option found
  387. }*/
  388. break;
  389. case ExtraField::FIELD_TYPE_TEXT:
  390. case ExtraField::FIELD_TYPE_TEXTAREA:
  391. break;
  392. case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
  393. case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
  394. if (is_array($value)) {
  395. $value_to_insert = null;
  396. if (isset($value['extra_'.$extraFieldInfo['variable']]) &&
  397. isset($value['extra_'.$extraFieldInfo['variable'].'_second'])
  398. ) {
  399. $value_to_insert = $value['extra_'.$extraFieldInfo['variable']].'::'.$value['extra_'.$extraFieldInfo['variable'].'_second'];
  400. }
  401. }
  402. break;
  403. default:
  404. break;
  405. }
  406. if ($extraFieldInfo['field_type'] == ExtraField::FIELD_TYPE_TAG) {
  407. $field_values = self::getAllValuesByItemAndFieldAndValue(
  408. $params['item_id'],
  409. $params['field_id'],
  410. $value
  411. );
  412. } else {
  413. $field_values = self::get_values_by_handler_and_field_id(
  414. $params['item_id'],
  415. $params['field_id']
  416. );
  417. }
  418. $params['value'] = $value_to_insert;
  419. //$params['author_id'] = api_get_user_id();
  420. // Insert
  421. if (empty($field_values)) {
  422. /* Enable this when field_loggeable is introduced as a table field (2.0)
  423. if ($extraFieldInfo['field_loggeable'] == 1) {
  424. */
  425. if (false) {
  426. global $app;
  427. switch ($this->type) {
  428. case 'question':
  429. $extraFieldValue = new ChamiloLMS\Entity\QuestionFieldValues();
  430. $extraFieldValue->setUserId(api_get_user_id());
  431. $extraFieldValue->setQuestionId($params[$this->handler_id]);
  432. break;
  433. case 'course':
  434. $extraFieldValue = new ChamiloLMS\Entity\CourseFieldValues();
  435. $extraFieldValue->setUserId(api_get_user_id());
  436. $extraFieldValue->setQuestionId($params[$this->handler_id]);
  437. break;
  438. case 'user':
  439. $extraFieldValue = new ChamiloLMS\Entity\UserFieldValues();
  440. $extraFieldValue->setUserId($params[$this->handler_id]);
  441. $extraFieldValue->setAuthorId(api_get_user_id());
  442. break;
  443. case 'session':
  444. $extraFieldValue = new ChamiloLMS\Entity\SessionFieldValues();
  445. $extraFieldValue->setUserId(api_get_user_id());
  446. $extraFieldValue->setSessionId($params[$this->handler_id]);
  447. break;
  448. }
  449. if (isset($extraFieldValue)) {
  450. if (!empty($params['value'])) {
  451. $extraFieldValue->setComment($params['comment']);
  452. $extraFieldValue->setFieldValue($params['value']);
  453. $extraFieldValue->setFieldId($params['field_id']);
  454. $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
  455. $app['orm.ems']['db_write']->persist($extraFieldValue);
  456. $app['orm.ems']['db_write']->flush();
  457. }
  458. }
  459. } else {
  460. if ($extraFieldInfo['field_type'] == ExtraField::FIELD_TYPE_TAG) {
  461. $option = new ExtraFieldOption($this->type);
  462. $optionExists = $option->get($params['value']);
  463. if (empty($optionExists)) {
  464. $optionParams = [
  465. 'field_id' => $params['field_id'],
  466. 'option_value' => $params['value'],
  467. ];
  468. $optionId = $option->saveOptions($optionParams);
  469. } else {
  470. $optionId = $optionExists['id'];
  471. }
  472. $params['value'] = $optionId;
  473. if ($optionId) {
  474. return parent::save($params, $showQuery);
  475. }
  476. } else {
  477. return parent::save($params, $showQuery);
  478. }
  479. }
  480. } else {
  481. // Update
  482. /* Enable this when field_loggeable is introduced as a table field (2.0)
  483. if ($extraFieldInfo['field_loggeable'] == 1) {
  484. */
  485. if (false) {
  486. global $app;
  487. switch ($this->type) {
  488. case 'question':
  489. $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\QuestionFieldValues')->find($field_values['id']);
  490. $extraFieldValue->setUserId(api_get_user_id());
  491. $extraFieldValue->setQuestionId($params[$this->handler_id]);
  492. break;
  493. case 'course':
  494. $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\CourseFieldValues')->find($field_values['id']);
  495. $extraFieldValue->setUserId(api_get_user_id());
  496. $extraFieldValue->setCourseCode($params[$this->handler_id]);
  497. break;
  498. case 'user':
  499. $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\UserFieldValues')->find($field_values['id']);
  500. $extraFieldValue->setUserId(api_get_user_id());
  501. $extraFieldValue->setAuthorId(api_get_user_id());
  502. break;
  503. case 'session':
  504. $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\SessionFieldValues')->find($field_values['id']);
  505. $extraFieldValue->setUserId(api_get_user_id());
  506. $extraFieldValue->setSessionId($params[$this->handler_id]);
  507. break;
  508. }
  509. if (isset($extraFieldValue)) {
  510. if (!empty($params['value'])) {
  511. /*
  512. * If the field value is similar to the previous value then the comment will be the same
  513. in order to no save in the log an empty record
  514. */
  515. if ($extraFieldValue->getFieldValue() == $params['value']) {
  516. if (empty($params['comment'])) {
  517. $params['comment'] = $extraFieldValue->getComment();
  518. }
  519. }
  520. $extraFieldValue->setComment($params['comment']);
  521. $extraFieldValue->setFieldValue($params['value']);
  522. $extraFieldValue->setFieldId($params['field_id']);
  523. $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
  524. $app['orm.ems']['db_write']->persist($extraFieldValue);
  525. $app['orm.ems']['db_write']->flush();
  526. }
  527. }
  528. } else {
  529. $params['id'] = $field_values['id'];
  530. return parent::update($params, $showQuery);
  531. }
  532. }
  533. }
  534. }
  535. /**
  536. * Returns the value of the given extra field on the given resource.
  537. *
  538. * @param int $item_id Item ID (It could be a session_id, course_id or user_id)
  539. * @param int $field_id Field ID (the ID from the *_field table)
  540. * @param bool $transform Whether to transform the result to a human readable strings
  541. *
  542. * @return mixed A structured array with the field_id and field_value, or false on error
  543. * @assert (-1,-1) === false
  544. */
  545. public function get_values_by_handler_and_field_id($item_id, $field_id, $transform = false)
  546. {
  547. $field_id = (int) $field_id;
  548. $item_id = Database::escape_string($item_id);
  549. $sql = "SELECT s.*, field_type FROM {$this->table} s
  550. INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id)
  551. WHERE
  552. item_id = '$item_id' AND
  553. field_id = '".$field_id."' AND
  554. sf.extra_field_type = ".$this->getExtraField()->getExtraFieldType()."
  555. ORDER BY id";
  556. $result = Database::query($sql);
  557. if (Database::num_rows($result)) {
  558. $result = Database::fetch_array($result, 'ASSOC');
  559. if ($transform) {
  560. if (!empty($result['value'])) {
  561. switch ($result['field_type']) {
  562. case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
  563. $field_option = new ExtraFieldOption($this->type);
  564. $options = explode('::', $result['value']);
  565. // only available for PHP 5.4 :( $result['field_value'] = $field_option->get($options[0])['id'].' -> ';
  566. $result = $field_option->get($options[0]);
  567. $result_second = $field_option->get($options[1]);
  568. if (!empty($result)) {
  569. $result['value'] = $result['display_text'].' -> ';
  570. $result['value'] .= $result_second['display_text'];
  571. }
  572. break;
  573. case ExtraField::FIELD_TYPE_SELECT:
  574. $field_option = new ExtraFieldOption($this->type);
  575. $extra_field_option_result = $field_option->get_field_option_by_field_and_option(
  576. $result['field_id'],
  577. $result['value']
  578. );
  579. if (isset($extra_field_option_result[0])) {
  580. $result['value'] = $extra_field_option_result[0]['display_text'];
  581. }
  582. break;
  583. case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
  584. $options = explode('::', $result['value']);
  585. $field_option = new ExtraFieldOption($this->type);
  586. $result = $field_option->get($options[0]);
  587. if (!empty($result)) {
  588. $result['value'] = $result['display_text']
  589. .'&rarr;'
  590. .$options[1];
  591. }
  592. break;
  593. case ExtraField::FIELD_TYPE_TRIPLE_SELECT:
  594. $optionIds = explode(';', $result['value']);
  595. $optionValues = [];
  596. foreach ($optionIds as $optionId) {
  597. $objEfOption = new ExtraFieldOption('user');
  598. $optionInfo = $objEfOption->get($optionId);
  599. $optionValues[] = $optionInfo['display_text'];
  600. }
  601. $result['value'] = implode(' / ', $optionValues);
  602. break;
  603. }
  604. }
  605. }
  606. return $result;
  607. } else {
  608. return false;
  609. }
  610. }
  611. /**
  612. * @param string $tag
  613. * @param int $field_id
  614. * @param int $limit
  615. *
  616. * @return array
  617. */
  618. public function searchValuesByField($tag, $field_id, $limit = 10)
  619. {
  620. $field_id = (int) $field_id;
  621. $limit = (int) $limit;
  622. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  623. $tag = Database::escape_string($tag);
  624. $sql = "SELECT DISTINCT s.value, s.field_id
  625. FROM {$this->table} s
  626. INNER JOIN {$this->table_handler_field} sf
  627. ON (s.field_id = sf.id)
  628. WHERE
  629. field_id = '".$field_id."' AND
  630. value LIKE '%$tag%' AND
  631. sf.extra_field_type = ".$extraFieldType."
  632. ORDER BY value
  633. LIMIT 0, $limit
  634. ";
  635. $result = Database::query($sql);
  636. $values = [];
  637. if (Database::num_rows($result)) {
  638. $values = Database::store_result($result, 'ASSOC');
  639. }
  640. return $values;
  641. }
  642. /**
  643. * Gets a structured array of the original item and its extra values, using
  644. * a specific original item and a field name (like "branch", or "birthdate").
  645. *
  646. * @param int $item_id Item ID from the original table
  647. * @param string $field_variable The name of the field we are looking for
  648. * @param bool $transform
  649. * @param bool $filterByVisibility
  650. * @param int $visibility
  651. *
  652. * @return mixed Array of results, or false on error or not found
  653. * @assert (-1,'') === false
  654. */
  655. public function get_values_by_handler_and_field_variable(
  656. $item_id,
  657. $field_variable,
  658. $transform = false,
  659. $filterByVisibility = false,
  660. $visibility = 0
  661. ) {
  662. $item_id = (int) $item_id;
  663. $field_variable = Database::escape_string($field_variable);
  664. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  665. $sql = "SELECT s.*, field_type
  666. FROM {$this->table} s
  667. INNER JOIN {$this->table_handler_field} sf
  668. ON (s.field_id = sf.id)
  669. WHERE
  670. item_id = '$item_id' AND
  671. variable = '".$field_variable."' AND
  672. sf.extra_field_type = $extraFieldType
  673. ";
  674. if ($filterByVisibility) {
  675. $visibility = (int) $visibility;
  676. $sql .= " AND visible_to_self = $visibility ";
  677. }
  678. $sql .= ' ORDER BY id';
  679. $result = Database::query($sql);
  680. if (Database::num_rows($result)) {
  681. $result = Database::fetch_array($result, 'ASSOC');
  682. if ($transform) {
  683. if ($result['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
  684. if (!empty($result['value'])) {
  685. $field_option = new ExtraFieldOption($this->type);
  686. $options = explode('::', $result['value']);
  687. $result = $field_option->get($options[0]);
  688. $result_second = $field_option->get($options[1]);
  689. if (!empty($result)) {
  690. $result['value'] = $result['display_text'].' -> ';
  691. $result['value'] .= $result_second['display_text'];
  692. }
  693. }
  694. }
  695. if ($result['field_type'] == ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD) {
  696. if (!empty($result['value'])) {
  697. $options = explode('::', $result['value']);
  698. $field_option = new ExtraFieldOption($this->type);
  699. $result = $field_option->get($options[0]);
  700. if (!empty($result)) {
  701. $result['value'] = $result['display_text']
  702. .'&rarr;'
  703. .$options[1];
  704. }
  705. }
  706. }
  707. if ($result['field_type'] == ExtraField::FIELD_TYPE_TRIPLE_SELECT) {
  708. if (!empty($result['value'])) {
  709. $optionIds = explode(';', $result['value']);
  710. $optionValues = [];
  711. foreach ($optionIds as $optionId) {
  712. $objEfOption = new ExtraFieldOption('user');
  713. $optionInfo = $objEfOption->get($optionId);
  714. $optionValues[] = $optionInfo['display_text'];
  715. }
  716. $result['value'] = implode(' / ', $optionValues);
  717. }
  718. }
  719. }
  720. return $result;
  721. } else {
  722. return false;
  723. }
  724. }
  725. /**
  726. * Gets the ID from the item (course, session, etc) for which
  727. * the given field is defined with the given value.
  728. *
  729. * @param string $field_variable Field (type of data) we want to check
  730. * @param string $field_value Data we are looking for in the given field
  731. * @param bool $transform Whether to transform the result to a human readable strings
  732. * @param bool $last Whether to return the last element or simply the first one we get
  733. *
  734. * @return mixed Give the ID if found, or false on failure or not found
  735. * @assert (-1,-1) === false
  736. */
  737. public function get_item_id_from_field_variable_and_field_value(
  738. $field_variable,
  739. $field_value,
  740. $transform = false,
  741. $last = false,
  742. $all = false
  743. ) {
  744. $field_value = Database::escape_string($field_value);
  745. $field_variable = Database::escape_string($field_variable);
  746. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  747. $sql = "SELECT item_id FROM {$this->table} s
  748. INNER JOIN {$this->table_handler_field} sf
  749. ON (s.field_id = sf.id)
  750. WHERE
  751. value = '$field_value' AND
  752. variable = '".$field_variable."' AND
  753. sf.extra_field_type = $extraFieldType
  754. ORDER BY item_id
  755. ";
  756. if ($last) {
  757. // If we want the last element instead of the first
  758. // This is useful in special cases where there might
  759. // (erroneously) be more than one row for an item
  760. $sql .= ' DESC';
  761. }
  762. $result = Database::query($sql);
  763. if ($result !== false && Database::num_rows($result)) {
  764. if ($all) {
  765. $result = Database::store_result($result, 'ASSOC');
  766. } else {
  767. $result = Database::fetch_array($result, 'ASSOC');
  768. }
  769. return $result;
  770. } else {
  771. return false;
  772. }
  773. }
  774. /**
  775. * Get all the values stored for one specific field.
  776. *
  777. * @param int $fieldId
  778. *
  779. * @return array|bool
  780. */
  781. public function getValuesByFieldId($fieldId)
  782. {
  783. $fieldId = (int) $fieldId;
  784. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  785. $sql = "SELECT s.* FROM {$this->table} s
  786. INNER JOIN {$this->table_handler_field} sf
  787. ON (s.field_id = sf.id)
  788. WHERE
  789. field_id = '".$fieldId."' AND
  790. sf.extra_field_type = $extraFieldType
  791. ORDER BY s.value";
  792. $result = Database::query($sql);
  793. if (Database::num_rows($result)) {
  794. return Database::store_result($result, 'ASSOC');
  795. }
  796. return false;
  797. }
  798. /**
  799. * @param int $itemId
  800. * @param int $fieldId
  801. *
  802. * @return array
  803. */
  804. public function getAllValuesByItemAndField($itemId, $fieldId)
  805. {
  806. $fieldId = (int) $fieldId;
  807. $itemId = (int) $itemId;
  808. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  809. $sql = "SELECT s.* FROM {$this->table} s
  810. INNER JOIN {$this->table_handler_field} sf
  811. ON (s.field_id = sf.id)
  812. WHERE
  813. field_id = $fieldId AND
  814. item_id = $itemId AND
  815. sf.extra_field_type = $extraFieldType
  816. ORDER BY s.value";
  817. $result = Database::query($sql);
  818. if (Database::num_rows($result)) {
  819. return Database::store_result($result, 'ASSOC');
  820. }
  821. return false;
  822. }
  823. /**
  824. * @param int $itemId
  825. *
  826. * @return array
  827. */
  828. public function getAllValuesByItem($itemId)
  829. {
  830. $itemId = (int) $itemId;
  831. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  832. $sql = "SELECT s.value, sf.variable, sf.field_type, sf.id, sf.display_text
  833. FROM {$this->table} s
  834. INNER JOIN {$this->table_handler_field} sf
  835. ON (s.field_id = sf.id)
  836. WHERE
  837. item_id = '$itemId' AND
  838. sf.extra_field_type = $extraFieldType
  839. ORDER BY s.value";
  840. $result = Database::query($sql);
  841. $idList = [];
  842. if (Database::num_rows($result)) {
  843. $result = Database::store_result($result, 'ASSOC');
  844. $finalResult = [];
  845. foreach ($result as $item) {
  846. $finalResult[$item['id']] = $item;
  847. }
  848. $idList = array_column($result, 'id');
  849. }
  850. $em = Database::getManager();
  851. $extraField = new ExtraField($this->type);
  852. $allData = $extraField->get_all(['filter = ?' => 1]);
  853. $allResults = [];
  854. foreach ($allData as $field) {
  855. if (in_array($field['id'], $idList)) {
  856. $allResults[] = $finalResult[$field['id']];
  857. } else {
  858. if ($field['field_type'] == ExtraField::FIELD_TYPE_TAG) {
  859. $tagResult = [];
  860. $tags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
  861. ->findBy(
  862. [
  863. 'fieldId' => $field['id'],
  864. 'itemId' => $itemId,
  865. ]
  866. );
  867. if ($tags) {
  868. /** @var ExtraFieldRelTag $extraFieldTag */
  869. foreach ($tags as $extraFieldTag) {
  870. /** @var \Chamilo\CoreBundle\Entity\Tag $tag */
  871. $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
  872. $tagResult[] = [
  873. 'id' => $extraFieldTag->getTagId(),
  874. 'value' => $tag->getTag(),
  875. ];
  876. }
  877. }
  878. $allResults[] = [
  879. 'value' => $tagResult,
  880. 'variable' => $field['variable'],
  881. 'field_type' => $field['field_type'],
  882. 'id' => $field['id'],
  883. ];
  884. }
  885. }
  886. }
  887. return $allResults;
  888. }
  889. /**
  890. * @param int $itemId
  891. * @param int $fieldId
  892. * @param string $fieldValue
  893. *
  894. * @return array|bool
  895. */
  896. public function getAllValuesByItemAndFieldAndValue($itemId, $fieldId, $fieldValue)
  897. {
  898. $fieldId = (int) $fieldId;
  899. $itemId = (int) $itemId;
  900. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  901. $fieldValue = Database::escape_string($fieldValue);
  902. $sql = "SELECT s.* FROM {$this->table} s
  903. INNER JOIN {$this->table_handler_field} sf
  904. ON (s.field_id = sf.id)
  905. WHERE
  906. field_id = '$fieldId' AND
  907. item_id = '$itemId' AND
  908. value = '$fieldValue' AND
  909. sf.extra_field_type = $extraFieldType
  910. ORDER BY value";
  911. $result = Database::query($sql);
  912. if (Database::num_rows($result)) {
  913. return Database::store_result($result, 'ASSOC');
  914. }
  915. return false;
  916. }
  917. /**
  918. * Deletes all the values related to a specific field ID.
  919. *
  920. * @param int $field_id
  921. *
  922. * @assert ('a') == null
  923. */
  924. public function delete_all_values_by_field_id($field_id)
  925. {
  926. $field_id = (int) $field_id;
  927. $sql = "DELETE FROM {$this->table}
  928. WHERE
  929. field_id = $field_id ";
  930. Database::query($sql);
  931. }
  932. /**
  933. * Deletes all values from an item.
  934. *
  935. * @param int $itemId (session id, course id, etc)
  936. * @assert (-1,-1) == null
  937. */
  938. public function deleteValuesByItem($itemId)
  939. {
  940. $itemId = (int) $itemId;
  941. $extraFieldType = $this->getExtraField()->getExtraFieldType();
  942. $sql = "DELETE FROM {$this->table}
  943. WHERE
  944. item_id = '$itemId' AND
  945. field_id IN (
  946. SELECT id FROM {$this->table_handler_field}
  947. WHERE extra_field_type = ".$extraFieldType."
  948. )
  949. ";
  950. Database::query($sql);
  951. }
  952. /**
  953. * @param int $itemId
  954. * @param int $fieldId
  955. * @param int $fieldValue
  956. *
  957. * @return bool
  958. */
  959. public function deleteValuesByHandlerAndFieldAndValue($itemId, $fieldId, $fieldValue)
  960. {
  961. $itemId = (int) $itemId;
  962. $fieldId = (int) $fieldId;
  963. $fieldData = $this->getExtraField()->get($fieldId);
  964. if ($fieldData) {
  965. $fieldValue = Database::escape_string($fieldValue);
  966. $sql = "DELETE FROM {$this->table}
  967. WHERE
  968. item_id = '$itemId' AND
  969. field_id = '$fieldId' AND
  970. value = '$fieldValue'
  971. ";
  972. Database::query($sql);
  973. // Delete file from uploads
  974. if ($fieldData['field_type'] == ExtraField::FIELD_TYPE_FILE) {
  975. api_remove_uploaded_file($this->type, basename($fieldValue));
  976. }
  977. return true;
  978. }
  979. return false;
  980. }
  981. /**
  982. * Get all values for an item.
  983. *
  984. * @param int $itemId The item ID
  985. * @param bool $visibleToSelf Get the visible extra field only
  986. * @param bool $visibleToOthers
  987. *
  988. * @return array
  989. */
  990. public function getAllValuesForAnItem($itemId, $visibleToSelf = null, $visibleToOthers = null)
  991. {
  992. $em = Database::getManager();
  993. $qb = $em->createQueryBuilder();
  994. $qb = $qb->select('fv')
  995. ->from('ChamiloCoreBundle:ExtraFieldValues', 'fv')
  996. ->join('fv.field', 'f')
  997. ->where(
  998. $qb->expr()->eq('fv.itemId', ':item')
  999. )
  1000. ->andWhere(
  1001. $qb->expr()->eq('f.extraFieldType', ':extra_field_type')
  1002. );
  1003. if (is_bool($visibleToSelf)) {
  1004. $qb
  1005. ->andWhere($qb->expr()->eq('f.visibleToSelf', ':visibleToSelf'))
  1006. ->setParameter('visibleToSelf', $visibleToSelf);
  1007. }
  1008. if (is_bool($visibleToOthers)) {
  1009. $qb
  1010. ->andWhere($qb->expr()->eq('f.visibleToOthers', ':visibleToOthers'))
  1011. ->setParameter('visibleToOthers', $visibleToOthers);
  1012. }
  1013. $fieldValues = $qb
  1014. ->setParameter('item', $itemId)
  1015. ->setParameter('extra_field_type', $this->getExtraField()->getExtraFieldType())
  1016. ->getQuery()
  1017. ->getResult();
  1018. $fieldOptionsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldOptions');
  1019. $valueList = [];
  1020. /** @var ExtraFieldValues $fieldValue */
  1021. foreach ($fieldValues as $fieldValue) {
  1022. $item = ['value' => $fieldValue];
  1023. switch ($fieldValue->getField()->getFieldType()) {
  1024. case ExtraField::FIELD_TYPE_SELECT:
  1025. $item['option'] = $fieldOptionsRepo->findOneBy([
  1026. 'field' => $fieldValue->getField(),
  1027. 'value' => $fieldValue->getValue(),
  1028. ]);
  1029. break;
  1030. }
  1031. $valueList[] = $item;
  1032. }
  1033. return $valueList;
  1034. }
  1035. }