Passed
Push — 1.11.x ( 7b46f8...2e5b11 )
by Angel Fernando Quiroz
09:08 queued 12s
created

ExtraFieldValue::getValuesByFieldId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 19
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
7
use Chamilo\CoreBundle\Entity\ExtraFieldValues;
8
use Chamilo\CoreBundle\Entity\Tag;
9
use ChamiloSession as Session;
10
11
/**
12
 * Class ExtraFieldValue
13
 * Declaration for the ExtraFieldValue class, managing the values in extra
14
 * fields for any data type.
15
 */
16
class ExtraFieldValue extends Model
17
{
18
    public $type = '';
19
    public $columns = [
20
        'id',
21
        'field_id',
22
        'value',
23
        'comment',
24
        'item_id',
25
        'created_at',
26
        'updated_at',
27
    ];
28
    /** @var ExtraField */
29
    public $extraField;
30
31
    /**
32
     * Formats the necessary elements for the given datatype.
33
     *
34
     * @param string $type The type of data to which this extra field
35
     *                     applies (user, course, session, ...)
36
     *
37
     * @assert (-1) === false
38
     */
39
    public function __construct($type)
40
    {
41
        parent::__construct();
42
        $this->type = $type;
43
        $extraField = new ExtraField($this->type);
44
        $this->extraField = $extraField;
45
        $this->table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
46
        $this->table_handler_field = Database::get_main_table(TABLE_EXTRA_FIELD);
47
    }
48
49
    /**
50
     * @return ExtraField
51
     */
52
    public function getExtraField()
53
    {
54
        return $this->extraField;
55
    }
56
57
    /**
58
     * Gets the number of values stored in the table (all fields together)
59
     * for this type of resource.
60
     *
61
     * @return int Number of rows in the table
62
     * @assert () !== false
63
     */
64
    public function get_count()
65
    {
66
        $em = Database::getManager();
67
        $query = $em->getRepository('ChamiloCoreBundle:ExtraFieldValues')->createQueryBuilder('e');
68
        $query->select('count(e.id)');
69
        $query->where('e.extraFieldType = :type');
70
        $query->setParameter('type', $this->getExtraField()->getExtraFieldType());
71
72
        return $query->getQuery()->getSingleScalarResult();
73
    }
74
75
    /**
76
     * Save the extra fields values
77
     * In order to save this function needs a item_id (user id, course id, etc)
78
     * This function is used with $extraField->addElements().
79
     *
80
     * @param array $params              array for the insertion into the *_field_values table (each label must be prefixed by 'extra_')
81
     * @param bool  $onlySubmittedFields Only save parameters in the $param array
82
     * @param bool  $showQuery
83
     * @param array $saveOnlyThisFields
84
     * @param array $avoidFields         do not insert/modify this field
85
     * @param bool  $forceSave
86
     *
87
     * @return mixed false on empty params, void otherwise
88
     * @assert (array()) === false
89
     */
90
    public function saveFieldValues(
91
        $params,
92
        $onlySubmittedFields = false,
93
        $showQuery = false,
94
        $saveOnlyThisFields = [],
95
        $avoidFields = [],
96
        $forceSave = false,
97
        $deleteOldValues = true
98
    ) {
99
        foreach ($params as $key => $value) {
100
            $found = strpos($key, '__persist__');
101
102
            if (false === $found) {
103
                continue;
104
            }
105
106
            $tempKey = str_replace('__persist__', '', $key);
107
            if (!isset($params[$tempKey])) {
108
                $params[$tempKey] = [];
109
            }
110
        }
111
112
        if (empty($params['item_id'])) {
113
            return false;
114
        }
115
116
        $type = $this->getExtraField()->getExtraFieldType();
117
118
        $extraField = new ExtraField($this->type);
119
        $extraFields = $extraField->get_all(null, 'option_order');
120
121
        // Parse params.
122
        foreach ($extraFields as $fieldDetails) {
123
            if (false === $forceSave) {
124
                // if the field is not visible to the user in the end, we need to apply special rules.
125
                if (1 != $fieldDetails['visible_to_self']) {
126
                    if (isset($params['origin']) && 'profile' == $params['origin']) {
127
                        continue;
128
                    } else {
129
                        //only admins should be able to add those values
130
                        if (!api_is_platform_admin(true, true)) {
131
                            // although if not admin but sent through a CLI script, we should accept it as well
132
                            if (PHP_SAPI != 'cli') {
133
                                continue; //not a CLI script, so don't write the value to DB
134
                            }
135
                        }
136
                    }
137
                }
138
            }
139
140
            $field_variable = $fieldDetails['variable'];
141
142
            if ($onlySubmittedFields && !isset($params['extra_'.$field_variable])) {
143
                continue;
144
            }
145
146
            if (!empty($avoidFields)) {
147
                if (in_array($field_variable, $avoidFields)) {
148
                    continue;
149
                }
150
            }
151
152
            if (!empty($saveOnlyThisFields)) {
153
                if (!in_array($field_variable, $saveOnlyThisFields)) {
154
                    continue;
155
                }
156
            }
157
158
            $value = '';
159
            if (isset($params['extra_'.$field_variable])) {
160
                $value = $params['extra_'.$field_variable];
161
            }
162
            $extraFieldInfo = $this->getExtraField()->get_handler_field_info_by_field_variable($field_variable);
163
164
            if (!$extraFieldInfo) {
165
                continue;
166
            }
167
168
            $commentVariable = 'extra_'.$field_variable.'_comment';
169
            $comment = isset($params[$commentVariable]) ? $params[$commentVariable] : null;
170
            $dirPermissions = api_get_permissions_for_new_directories();
171
172
            switch ($extraFieldInfo['field_type']) {
173
                case ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
174
                case ExtraField::FIELD_TYPE_GEOLOCALIZATION:
175
                    if (!empty($value)) {
176
                        if (isset($params['extra_'.$extraFieldInfo['variable'].'_coordinates'])) {
177
                            $value = $value.'::'.$params['extra_'.$extraFieldInfo['variable'].'_coordinates'];
178
                        }
179
                        $newParams = [
180
                            'item_id' => $params['item_id'],
181
                            'field_id' => $extraFieldInfo['id'],
182
                            'value' => $value,
183
                            'comment' => $comment,
184
                        ];
185
                        self::save($newParams, $showQuery);
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraFieldValue::save() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

185
                        self::/** @scrutinizer ignore-call */ 
186
                              save($newParams, $showQuery);
Loading history...
186
                    }
187
                    break;
188
                case ExtraField::FIELD_TYPE_TAG:
189
                    if (EntityExtraField::USER_FIELD_TYPE == $type) {
190
                        UserManager::delete_user_tags(
191
                            $params['item_id'],
192
                            $extraFieldInfo['id']
193
                        );
194
195
                        UserManager::process_tags(
196
                            $value,
197
                            $params['item_id'],
198
                            $extraFieldInfo['id']
199
                        );
200
                        break;
201
                    }
202
203
                    $em = Database::getManager();
204
205
                    $currentTags = $em
206
                        ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
207
                        ->findBy([
208
                            'fieldId' => $extraFieldInfo['id'],
209
                            'itemId' => $params['item_id'],
210
                        ]);
211
212
                    if ($deleteOldValues) {
213
                        foreach ($currentTags as $extraFieldtag) {
214
                            $em->remove($extraFieldtag);
215
                        }
216
                    }
217
                    $em->flush();
218
                    $tagValues = is_array($value) ? $value : [$value];
219
                    $tags = [];
220
221
                    foreach ($tagValues as $tagValue) {
222
                        if (empty($tagValue)) {
223
                            continue;
224
                        }
225
226
                        $tagsResult = $em->getRepository('ChamiloCoreBundle:Tag')
227
                            ->findBy([
228
                                'tag' => $tagValue,
229
                                'fieldId' => $extraFieldInfo['id'],
230
                            ]);
231
232
                        if (empty($tagsResult)) {
233
                            $tag = new Tag();
234
                            $tag->setFieldId($extraFieldInfo['id']);
235
                            $tag->setTag($tagValue);
236
237
                            $tags[] = $tag;
238
                        } else {
239
                            $tags = array_merge($tags, $tagsResult);
240
                        }
241
                    }
242
243
                    foreach ($tags as $tag) {
244
                        $tagUses = $em
245
                            ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
246
                            ->findBy([
247
                                'tagId' => $tag->getId(),
248
                            ]);
249
250
                        $tag->setCount(count($tagUses) + 1);
251
                        $em->persist($tag);
252
                    }
253
254
                    $em->flush();
255
256
                    foreach ($tags as $tag) {
257
                        $fieldRelTag = new ExtraFieldRelTag();
258
                        $fieldRelTag->setFieldId($extraFieldInfo['id']);
259
                        $fieldRelTag->setItemId($params['item_id']);
260
                        $fieldRelTag->setTagId($tag->getId());
261
                        $em->persist($fieldRelTag);
262
                    }
263
264
                    $em->flush();
265
                    break;
266
                case ExtraField::FIELD_TYPE_FILE_IMAGE:
267
                    $fileDir = $fileDirStored = '';
268
                    switch ($this->type) {
269
                        case 'course':
270
                            $fileDir = api_get_path(SYS_UPLOAD_PATH)."courses/";
271
                            $fileDirStored = "courses/";
272
                            break;
273
                        case 'session':
274
                            $fileDir = api_get_path(SYS_UPLOAD_PATH)."sessions/";
275
                            $fileDirStored = "sessions/";
276
                            break;
277
                        case 'user':
278
                            $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
279
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
280
                            break;
281
                        case 'work':
282
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
283
                            $fileDirStored = 'work/';
284
                            break;
285
                    }
286
287
                    $fileName = ExtraField::FIELD_TYPE_FILE_IMAGE."_{$params['item_id']}.png";
288
289
                    if (!file_exists($fileDir)) {
290
                        mkdir($fileDir, $dirPermissions, true);
291
                    }
292
293
                    if (!empty($value['tmp_name']) && isset($value['error']) && $value['error'] == 0) {
294
                        // Crop the image to adjust 16:9 ratio
295
                        if (isset($params['extra_'.$field_variable.'_crop_result'])) {
296
                            $crop = new Image($value['tmp_name']);
297
                            $crop->crop($params['extra_'.$field_variable.'_crop_result']);
298
                        }
299
300
                        $imageExtraField = new Image($value['tmp_name']);
301
                        $imageExtraField->resize(400);
302
                        $imageExtraField->send_image($fileDir.$fileName, -1, 'png');
303
                        $newParams = [
304
                            'item_id' => $params['item_id'],
305
                            'field_id' => $extraFieldInfo['id'],
306
                            'value' => $fileDirStored.$fileName,
307
                            'comment' => $comment,
308
                        ];
309
                        $this->save($newParams);
310
                    }
311
                    break;
312
                case ExtraField::FIELD_TYPE_FILE:
313
                    $fileDir = $fileDirStored = '';
314
                    switch ($this->type) {
315
                        case 'course':
316
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'courses/';
317
                            $fileDirStored = "courses/";
318
                            break;
319
                        case 'session':
320
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'sessions/';
321
                            $fileDirStored = "sessions/";
322
                            break;
323
                        case 'user':
324
                            $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
325
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
326
                            break;
327
                        case 'work':
328
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
329
                            $fileDirStored = "work/";
330
                            break;
331
                        case 'scheduled_announcement':
332
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'scheduled_announcement/';
333
                            $fileDirStored = 'scheduled_announcement/';
334
                            break;
335
                    }
336
337
                    $cleanedName = api_replace_dangerous_char($value['name']);
338
                    $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
339
                    if (!file_exists($fileDir)) {
340
                        mkdir($fileDir, $dirPermissions, true);
341
                    }
342
343
                    if (!empty($value['tmp_name']) && isset($value['error']) && $value['error'] == 0) {
344
                        $cleanedName = api_replace_dangerous_char($value['name']);
345
                        $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
346
                        moveUploadedFile($value, $fileDir.$fileName);
347
348
                        $new_params = [
349
                            'item_id' => $params['item_id'],
350
                            'field_id' => $extraFieldInfo['id'],
351
                            'value' => $fileDirStored.$fileName,
352
                        ];
353
354
                        if ('session' !== $this->type && 'course' !== $this->type) {
355
                            $new_params['comment'] = $comment;
356
                        }
357
358
                        $this->save($new_params);
359
                    }
360
                    break;
361
                case ExtraField::FIELD_TYPE_CHECKBOX:
362
                    $fieldToSave = 0;
363
                    if (is_array($value)) {
364
                        if (isset($value['extra_'.$field_variable])) {
365
                            $fieldToSave = 1;
366
                        }
367
                    }
368
369
                    $newParams = [
370
                        'item_id' => $params['item_id'],
371
                        'field_id' => $extraFieldInfo['id'],
372
                        'value' => $fieldToSave,
373
                        'comment' => $comment,
374
                    ];
375
                    $this->save($newParams);
376
377
                    break;
378
                case ExtraField::FIELD_TYPE_DATE:
379
                    $d = DateTime::createFromFormat('Y-m-d', $value);
380
                    $valid = $d && $d->format('Y-m-d') === $value;
381
                    if ($valid) {
382
                        $newParams = [
383
                            'item_id' => $params['item_id'],
384
                            'field_id' => $extraFieldInfo['id'],
385
                            'value' => $value,
386
                            'comment' => $comment,
387
                        ];
388
                        $this->save($newParams, $showQuery);
389
                    }
390
                    break;
391
                case ExtraField::FIELD_TYPE_DATETIME:
392
                    $d = DateTime::createFromFormat('Y-m-d H:i', $value);
393
                    $valid = $d && $d->format('Y-m-d H:i') === $value;
394
                    if ($valid) {
395
                        $newParams = [
396
                            'item_id' => $params['item_id'],
397
                            'field_id' => $extraFieldInfo['id'],
398
                            'value' => $value,
399
                            'comment' => $comment,
400
                        ];
401
                        $this->save($newParams, $showQuery);
402
                    }
403
                    break;
404
                default:
405
                    $newParams = [
406
                        'item_id' => $params['item_id'],
407
                        'field_id' => $extraFieldInfo['id'],
408
                        'value' => $value,
409
                        'comment' => $comment,
410
                    ];
411
                    $this->save($newParams, $showQuery);
412
            }
413
        }
414
    }
415
416
    /**
417
     * Save values in the *_field_values table.
418
     *
419
     * @param array $params    Structured array with the values to save
420
     * @param bool  $showQuery Whether to show the insert query (passed to the parent save() method)
421
     *
422
     * @return mixed The result sent from the parent method
423
     * @assert (array()) === false
424
     */
425
    public function save($params, $showQuery = false)
426
    {
427
        $extra_field = $this->getExtraField();
428
429
        // Setting value to insert.
430
        $value = $params['value'];
431
        $value_to_insert = null;
432
433
        if (is_array($value)) {
434
            $value_to_insert = implode(';', $value);
435
        } else {
436
            $value_to_insert = $value;
437
        }
438
439
        $params['value'] = $value_to_insert;
440
441
        // If field id exists
442
        if (isset($params['field_id'])) {
443
            $extraFieldInfo = $extra_field->get($params['field_id']);
444
        } else {
445
            // Try the variable
446
            $extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable(
447
                $params['variable']
448
            );
449
            if ($extraFieldInfo) {
450
                $params['field_id'] = $extraFieldInfo['id'];
451
            }
452
        }
453
454
        if ($extraFieldInfo) {
455
            switch ($extraFieldInfo['field_type']) {
456
                case ExtraField::FIELD_TYPE_RADIO:
457
                case ExtraField::FIELD_TYPE_SELECT:
458
                    break;
459
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
460
                    //$field_options = $session_field_option->get_field_options_by_field($params['field_id']);
461
                    //$params['field_value'] = split(';', $value_to_insert);
462
                    /*
463
                        if ($field_options) {
464
                            $check = false;
465
                            foreach ($field_options as $option) {
466
                                if (in_array($option['option_value'], $values)) {
467
                                    $check = true;
468
                                    break;
469
                                }
470
                           }
471
                           if (!$check) {
472
                               return false; //option value not found
473
                           }
474
                       } else {
475
                           return false; //enumerated type but no option found
476
                       }*/
477
                    break;
478
                case ExtraField::FIELD_TYPE_TEXT:
479
                case ExtraField::FIELD_TYPE_TEXTAREA:
480
                    break;
481
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
482
                case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
483
                    if (is_array($value)) {
484
                        $value_to_insert = null;
485
                        if (isset($value['extra_'.$extraFieldInfo['variable']]) &&
486
                            isset($value['extra_'.$extraFieldInfo['variable'].'_second'])
487
                        ) {
488
                            $value_to_insert = $value['extra_'.$extraFieldInfo['variable']].'::'.$value['extra_'.$extraFieldInfo['variable'].'_second'];
489
                        }
490
                    }
491
                    break;
492
                default:
493
                    break;
494
            }
495
496
            if (ExtraField::FIELD_TYPE_TAG == $extraFieldInfo['field_type']) {
497
                $field_values = self::getAllValuesByItemAndFieldAndValue(
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraFieldValue::getAllV...yItemAndFieldAndValue() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

497
                /** @scrutinizer ignore-call */ 
498
                $field_values = self::getAllValuesByItemAndFieldAndValue(
Loading history...
498
                    $params['item_id'],
499
                    $params['field_id'],
500
                    $value
501
                );
502
            } else {
503
                $field_values = self::get_values_by_handler_and_field_id(
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraFieldValue::get_val..._handler_and_field_id() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

503
                /** @scrutinizer ignore-call */ 
504
                $field_values = self::get_values_by_handler_and_field_id(
Loading history...
504
                    $params['item_id'],
505
                    $params['field_id']
506
                );
507
            }
508
509
            $params['value'] = $value_to_insert;
510
            //$params['author_id'] = api_get_user_id();
511
512
            // Insert
513
            if (empty($field_values)) {
514
                /* Enable this when field_loggeable is introduced as a table field (2.0)
515
                if ($extraFieldInfo['field_loggeable'] == 1) {
516
                */
517
                if (false) {
518
                    global $app;
519
                    switch ($this->type) {
520
                        case 'question':
521
                            $extraFieldValue = new ChamiloLMS\Entity\QuestionFieldValues();
522
                            $extraFieldValue->setUserId(api_get_user_id());
523
                            $extraFieldValue->setQuestionId($params[$this->handler_id]);
0 ignored issues
show
Bug Best Practice introduced by
The property handler_id does not exist on ExtraFieldValue. Did you maybe forget to declare it?
Loading history...
524
                            break;
525
                        case 'course':
526
                            $extraFieldValue = new ChamiloLMS\Entity\CourseFieldValues();
527
                            $extraFieldValue->setUserId(api_get_user_id());
528
                            $extraFieldValue->setQuestionId($params[$this->handler_id]);
529
                            break;
530
                        case 'user':
531
                            $extraFieldValue = new ChamiloLMS\Entity\UserFieldValues();
532
                            $extraFieldValue->setUserId($params[$this->handler_id]);
533
                            $extraFieldValue->setAuthorId(api_get_user_id());
534
                            break;
535
                        case 'session':
536
                            $extraFieldValue = new ChamiloLMS\Entity\SessionFieldValues();
537
                            $extraFieldValue->setUserId(api_get_user_id());
538
                            $extraFieldValue->setSessionId($params[$this->handler_id]);
539
                            break;
540
                    }
541
                    if (isset($extraFieldValue)) {
542
                        if (!empty($params['value'])) {
543
                            $extraFieldValue->setComment($params['comment']);
544
                            $extraFieldValue->setFieldValue($params['value']);
545
                            $extraFieldValue->setFieldId($params['field_id']);
546
                            $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
547
                            $app['orm.ems']['db_write']->persist($extraFieldValue);
548
                            $app['orm.ems']['db_write']->flush();
549
                        }
550
                    }
551
                } else {
552
                    if ($extraFieldInfo['field_type'] == ExtraField::FIELD_TYPE_TAG) {
553
                        $option = new ExtraFieldOption($this->type);
554
                        $optionExists = $option->get($params['value']);
555
                        if (empty($optionExists)) {
556
                            $optionParams = [
557
                                'field_id' => $params['field_id'],
558
                                'option_value' => $params['value'],
559
                            ];
560
                            $optionId = $option->saveOptions($optionParams);
561
                        } else {
562
                            $optionId = $optionExists['id'];
563
                        }
564
565
                        $params['value'] = $optionId;
566
                        if ($optionId) {
567
                            return parent::save($params, $showQuery);
568
                        }
569
                    } else {
570
                        return parent::save($params, $showQuery);
571
                    }
572
                }
573
            } else {
574
                // Update
575
                /* Enable this when field_loggeable is introduced as a table field (2.0)
576
                if ($extraFieldInfo['field_loggeable'] == 1) {
577
                */
578
                if (false) {
579
                    global $app;
580
                    switch ($this->type) {
581
                        case 'question':
582
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\QuestionFieldValues')->find($field_values['id']);
583
                            $extraFieldValue->setUserId(api_get_user_id());
584
                            $extraFieldValue->setQuestionId($params[$this->handler_id]);
585
                            break;
586
                        case 'course':
587
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\CourseFieldValues')->find($field_values['id']);
588
                            $extraFieldValue->setUserId(api_get_user_id());
589
                            $extraFieldValue->setCourseCode($params[$this->handler_id]);
590
                            break;
591
                        case 'user':
592
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\UserFieldValues')->find($field_values['id']);
593
                            $extraFieldValue->setUserId(api_get_user_id());
594
                            $extraFieldValue->setAuthorId(api_get_user_id());
595
                            break;
596
                        case 'session':
597
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\SessionFieldValues')->find($field_values['id']);
598
                            $extraFieldValue->setUserId(api_get_user_id());
599
                            $extraFieldValue->setSessionId($params[$this->handler_id]);
600
                            break;
601
                    }
602
603
                    if (isset($extraFieldValue)) {
604
                        if (!empty($params['value'])) {
605
                            /*
606
                             *  If the field value is similar to the previous value then the comment will be the same
607
                                in order to no save in the log an empty record
608
                            */
609
                            if ($extraFieldValue->getFieldValue() == $params['value']) {
610
                                if (empty($params['comment'])) {
611
                                    $params['comment'] = $extraFieldValue->getComment();
612
                                }
613
                            }
614
615
                            $extraFieldValue->setComment($params['comment']);
616
                            $extraFieldValue->setFieldValue($params['value']);
617
                            $extraFieldValue->setFieldId($params['field_id']);
618
                            $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
619
                            $app['orm.ems']['db_write']->persist($extraFieldValue);
620
                            $app['orm.ems']['db_write']->flush();
621
                        }
622
                    }
623
                } else {
624
                    $params['id'] = $field_values['id'];
625
626
                    return parent::update($params, $showQuery);
627
                }
628
            }
629
        }
630
    }
631
632
    /**
633
     * Returns the value of the given extra field on the given resource.
634
     *
635
     * @param int  $item_id   Item ID (It could be a session_id, course_id or user_id)
636
     * @param int  $field_id  Field ID (the ID from the *_field table)
637
     * @param bool $transform Whether to transform the result to a human readable strings
638
     *
639
     * @return mixed A structured array with the field_id and field_value, or false on error
640
     * @assert (-1,-1) === false
641
     */
642
    public function get_values_by_handler_and_field_id($item_id, $field_id, $transform = false)
643
    {
644
        $field_id = (int) $field_id;
645
        $item_id = Database::escape_string($item_id);
646
647
        $sql = "SELECT s.*, field_type FROM {$this->table} s
648
                INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id)
649
                WHERE
650
                    item_id = $item_id AND
651
                    field_id = $field_id AND
652
                    sf.extra_field_type = ".$this->getExtraField()->getExtraFieldType()."
653
                ORDER BY id";
654
        $result = Database::query($sql);
655
        if (Database::num_rows($result)) {
656
            $result = Database::fetch_array($result, 'ASSOC');
657
            if ($transform) {
658
                if (!empty($result['value'])) {
659
                    switch ($result['field_type']) {
660
                        case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
661
                            $field_option = new ExtraFieldOption($this->type);
662
                            $options = explode('::', $result['value']);
663
                            // only available for PHP 5.4  :( $result['field_value'] = $field_option->get($options[0])['id'].' -> ';
664
                            $result = $field_option->get($options[0]);
665
                            $result_second = $field_option->get($options[1]);
666
                            if (!empty($result)) {
667
                                $result['value'] = $result['display_text'].' -> ';
668
                                $result['value'] .= $result_second['display_text'];
669
                            }
670
                            break;
671
                        case ExtraField::FIELD_TYPE_SELECT:
672
                            $field_option = new ExtraFieldOption($this->type);
673
                            $extra_field_option_result = $field_option->get_field_option_by_field_and_option(
674
                                $result['field_id'],
675
                                $result['value']
676
                            );
677
678
                            if (isset($extra_field_option_result[0])) {
679
                                $result['value'] = $extra_field_option_result[0]['display_text'];
680
                            }
681
                            break;
682
                        case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
683
                            $options = explode('::', $result['value']);
684
685
                            $field_option = new ExtraFieldOption($this->type);
686
                            $result = $field_option->get($options[0]);
687
688
                            if (!empty($result)) {
689
                                $result['value'] = $result['display_text']
690
                                    .'&rarr;'
691
                                    .$options[1];
692
                            }
693
                            break;
694
                        case ExtraField::FIELD_TYPE_TRIPLE_SELECT:
695
                            $optionIds = explode(';', $result['value']);
696
                            $optionValues = [];
697
698
                            foreach ($optionIds as $optionId) {
699
                                $objEfOption = new ExtraFieldOption('user');
700
                                $optionInfo = $objEfOption->get($optionId);
701
702
                                $optionValues[] = $optionInfo['display_text'];
703
                            }
704
705
                            $result['value'] = implode(' / ', $optionValues);
706
                            break;
707
                    }
708
                }
709
            }
710
711
            return $result;
712
        }
713
714
        return false;
715
    }
716
717
    /**
718
     * @param string $tag
719
     * @param int    $field_id
720
     * @param int    $limit
721
     *
722
     * @return array
723
     */
724
    public function searchValuesByField($tag, $field_id, $limit = 10)
725
    {
726
        $field_id = (int) $field_id;
727
        $limit = (int) $limit;
728
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
729
730
        $tag = Database::escape_string($tag);
731
        $sql = "SELECT DISTINCT s.value, s.field_id
732
                FROM {$this->table} s
733
                INNER JOIN {$this->table_handler_field} sf
734
                ON (s.field_id = sf.id)
735
                WHERE
736
                    field_id = $field_id AND
737
                    value LIKE '%$tag%' AND
738
                    sf.extra_field_type = $extraFieldType
739
                ORDER BY value
740
                LIMIT 0, $limit
741
                ";
742
        $result = Database::query($sql);
743
        $values = [];
744
        if (Database::num_rows($result)) {
745
            $values = Database::store_result($result, 'ASSOC');
746
        }
747
748
        return $values;
749
    }
750
751
    /**
752
     * Gets a structured array of the original item and its extra values, using
753
     * a specific original item and a field name (like "branch", or "birthdate").
754
     *
755
     * @param int    $item_id            Item ID from the original table
756
     * @param string $field_variable     The name of the field we are looking for
757
     * @param bool   $transform
758
     * @param bool   $filterByVisibility
759
     * @param int    $visibility
760
     *
761
     * @return mixed Array of results, or false on error or not found
762
     * @assert (-1,'') === false
763
     */
764
    public function get_values_by_handler_and_field_variable(
765
        $item_id,
766
        $field_variable,
767
        $transform = false,
768
        $filterByVisibility = false,
769
        $visibility = 0
770
    ) {
771
        $item_id = (int) $item_id;
772
        $field_variable = Database::escape_string($field_variable);
773
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
774
775
        $sql = "SELECT s.*, field_type
776
                FROM {$this->table} s
777
                INNER JOIN {$this->table_handler_field} sf
778
                ON (s.field_id = sf.id)
779
                WHERE
780
                    item_id = $item_id  AND
781
                    variable = '$field_variable' AND
782
                    sf.extra_field_type = $extraFieldType
783
                ";
784
        if ($filterByVisibility) {
785
            $visibility = (int) $visibility;
786
            $sql .= " AND visible_to_self = $visibility ";
787
        }
788
        $sql .= ' ORDER BY id';
789
790
        $result = Database::query($sql);
791
        if (Database::num_rows($result)) {
792
            $result = Database::fetch_array($result, 'ASSOC');
793
            if ($transform) {
794
                if ($result['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
795
                    if (!empty($result['value'])) {
796
                        $field_option = new ExtraFieldOption($this->type);
797
                        $options = explode('::', $result['value']);
798
                        $result = $field_option->get($options[0]);
799
                        $result_second = $field_option->get($options[1]);
800
                        if (!empty($result)) {
801
                            $result['value'] = $result['display_text'].' -> ';
802
                            $result['value'] .= $result_second['display_text'];
803
                        }
804
                    }
805
                }
806
                if ($result['field_type'] == ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD) {
807
                    if (!empty($result['value'])) {
808
                        $options = explode('::', $result['value']);
809
                        $field_option = new ExtraFieldOption($this->type);
810
                        $result = $field_option->get($options[0]);
811
                        if (!empty($result)) {
812
                            $result['value'] = $result['display_text'].'&rarr;'.$options[1];
813
                        }
814
                    }
815
                }
816
                if ($result['field_type'] == ExtraField::FIELD_TYPE_TRIPLE_SELECT) {
817
                    if (!empty($result['value'])) {
818
                        $optionIds = explode(';', $result['value']);
819
                        $optionValues = [];
820
821
                        foreach ($optionIds as $optionId) {
822
                            $objEfOption = new ExtraFieldOption('user');
823
                            $optionInfo = $objEfOption->get($optionId);
824
                            $optionValues[] = $optionInfo['display_text'];
825
                        }
826
827
                        $result['value'] = implode(' / ', $optionValues);
828
                    }
829
                }
830
831
                if ($result['field_type'] == Extrafield::FIELD_TYPE_SELECT && !empty($result['value'])) {
832
                    $fopt = (new ExtraFieldOption('user'))
833
                        ->get_field_option_by_field_and_option($result['field_id'], $result['value']);
834
                    $fopt = current(is_array($fopt) ? $fopt : []);
835
836
                    $result['value'] = $fopt['display_text'] ?? $result['value'];
837
                }
838
            }
839
840
            return $result;
841
        }
842
843
        return false;
844
    }
845
846
    /**
847
     * Gets the ID from the item (course, session, etc) for which
848
     * the given field is defined with the given value.
849
     *
850
     * @param string $variable  Field (type of data) we want to check
851
     * @param string $value     Data we are looking for in the given field
852
     * @param bool   $transform Whether to transform the result to a human readable strings
853
     * @param bool   $last      Whether to return the last element or simply the first one we get
854
     * @param bool   $useLike
855
     *
856
     * @return mixed Give the ID if found, or false on failure or not found
857
     * @assert (-1,-1) === false
858
     */
859
    public function get_item_id_from_field_variable_and_field_value(
860
        $variable,
861
        $value,
862
        $transform = false,
863
        $last = false,
864
        $all = false,
865
        $useLike = false
866
    ) {
867
        $value = Database::escape_string($value);
868
        $variable = Database::escape_string($variable);
869
870
        $valueCondition = " value  = '$value' AND ";
871
        if ($useLike) {
872
            $valueCondition = " value LIKE '%".$value."%' AND ";
873
        }
874
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
875
876
        $sql = "SELECT item_id FROM {$this->table} s
877
                INNER JOIN {$this->table_handler_field} sf
878
                ON (s.field_id = sf.id)
879
                WHERE
880
                    $valueCondition
881
                    variable = '".$variable."' AND
882
                    sf.extra_field_type = $extraFieldType
883
                ORDER BY item_id
884
                ";
885
886
        if ($last) {
887
            // If we want the last element instead of the first
888
            // This is useful in special cases where there might
889
            // (erroneously) be more than one row for an item
890
            $sql .= ' DESC';
891
        }
892
        $result = Database::query($sql);
893
        if ($result !== false && Database::num_rows($result)) {
894
            if ($all) {
895
                $result = Database::store_result($result, 'ASSOC');
896
            } else {
897
                $result = Database::fetch_array($result, 'ASSOC');
898
            }
899
900
            return $result;
901
        }
902
903
        return false;
904
    }
905
906
    /**
907
     * Get all the values stored for one specific field.
908
     *
909
     * @param int $fieldId
910
     *
911
     * @return array|bool
912
     */
913
    public function getValuesByFieldId($fieldId)
914
    {
915
        $fieldId = (int) $fieldId;
916
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
917
918
        $sql = "SELECT s.* FROM {$this->table} s
919
                INNER JOIN {$this->table_handler_field} sf
920
                ON (s.field_id = sf.id)
921
                WHERE
922
                    field_id = $fieldId AND
923
                    sf.extra_field_type = $extraFieldType
924
                ORDER BY s.value";
925
        $result = Database::query($sql);
926
927
        if (Database::num_rows($result)) {
928
            return Database::store_result($result, 'ASSOC');
929
        }
930
931
        return false;
932
    }
933
934
    /**
935
     * @param int $itemId
936
     * @param int $fieldId
937
     *
938
     * @return array
939
     */
940
    public function getAllValuesByItemAndField($itemId, $fieldId)
941
    {
942
        $fieldId = (int) $fieldId;
943
        $itemId = (int) $itemId;
944
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
945
946
        $sql = "SELECT s.* FROM {$this->table} s
947
                INNER JOIN {$this->table_handler_field} sf
948
                ON (s.field_id = sf.id)
949
                WHERE
950
                    field_id = $fieldId AND
951
                    item_id = $itemId AND
952
                    sf.extra_field_type = $extraFieldType
953
                ORDER BY s.value";
954
        $result = Database::query($sql);
955
956
        if (Database::num_rows($result)) {
957
            return Database::store_result($result, 'ASSOC');
958
        }
959
960
        return false;
961
    }
962
963
    /**
964
     * @param int $itemId
965
     *
966
     * @return array
967
     */
968
    public function getAllValuesByItem($itemId)
969
    {
970
        $itemId = (int) $itemId;
971
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
972
973
        $sql = "SELECT s.value, sf.variable, sf.field_type, sf.id, sf.display_text
974
                FROM {$this->table} s
975
                INNER JOIN {$this->table_handler_field} sf
976
                ON (s.field_id = sf.id)
977
                WHERE
978
                    item_id = $itemId AND
979
                    sf.extra_field_type = $extraFieldType
980
                ORDER BY s.value";
981
982
        $result = Database::query($sql);
983
        $idList = [];
984
        if (Database::num_rows($result)) {
985
            $result = Database::store_result($result, 'ASSOC');
986
            $finalResult = [];
987
            foreach ($result as $item) {
988
                $finalResult[$item['id']] = $item;
989
            }
990
            $idList = array_column($result, 'id');
991
        }
992
993
        $em = Database::getManager();
994
995
        $extraField = new ExtraField($this->type);
996
        $allData = $extraField->get_all(['filter = ?' => 1]);
997
        $allResults = [];
998
        foreach ($allData as $field) {
999
            if (in_array($field['id'], $idList)) {
1000
                $allResults[] = $finalResult[$field['id']];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $finalResult does not seem to be defined for all execution paths leading up to this point.
Loading history...
1001
            } else {
1002
                if ($field['field_type'] == ExtraField::FIELD_TYPE_TAG) {
1003
                    $tagResult = [];
1004
                    $tags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1005
                        ->findBy(
1006
                            [
1007
                                'fieldId' => $field['id'],
1008
                                'itemId' => $itemId,
1009
                            ]
1010
                        );
1011
                    if ($tags) {
1012
                        /** @var ExtraFieldRelTag $extraFieldTag */
1013
                        foreach ($tags as $extraFieldTag) {
1014
                            /** @var \Chamilo\CoreBundle\Entity\Tag $tag */
1015
                            $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
1016
                            $tagResult[] = [
1017
                                'id' => $extraFieldTag->getTagId(),
1018
                                'value' => $tag->getTag(),
1019
                            ];
1020
                        }
1021
                    }
1022
                    $allResults[] = [
1023
                        'value' => $tagResult,
1024
                        'variable' => $field['variable'],
1025
                        'field_type' => $field['field_type'],
1026
                        'id' => $field['id'],
1027
                    ];
1028
                }
1029
            }
1030
        }
1031
1032
        return $allResults;
1033
    }
1034
1035
    /**
1036
     * @param int    $itemId
1037
     * @param int    $fieldId
1038
     * @param string $fieldValue
1039
     *
1040
     * @return array|bool
1041
     */
1042
    public function getAllValuesByItemAndFieldAndValue($itemId, $fieldId, $fieldValue)
1043
    {
1044
        $fieldId = (int) $fieldId;
1045
        $itemId = (int) $itemId;
1046
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
1047
1048
        $fieldValue = Database::escape_string($fieldValue);
1049
        $sql = "SELECT s.* FROM {$this->table} s
1050
                INNER JOIN {$this->table_handler_field} sf
1051
                ON (s.field_id = sf.id)
1052
                WHERE
1053
                    field_id = $fieldId AND
1054
                    item_id = $itemId AND
1055
                    value = '$fieldValue' AND
1056
                    sf.extra_field_type = $extraFieldType
1057
                ORDER BY value";
1058
1059
        $result = Database::query($sql);
1060
        if (Database::num_rows($result)) {
1061
            return Database::store_result($result, 'ASSOC');
1062
        }
1063
1064
        return false;
1065
    }
1066
1067
    /**
1068
     * Deletes all the values related to a specific field ID.
1069
     *
1070
     * @param int $field_id
1071
     *
1072
     * @assert ('a') == null
1073
     */
1074
    public function delete_all_values_by_field_id($field_id)
1075
    {
1076
        $field_id = (int) $field_id;
1077
        $sql = "DELETE FROM {$this->table}
1078
                WHERE
1079
                    field_id = $field_id ";
1080
        Database::query($sql);
1081
    }
1082
1083
    /**
1084
     * Deletes all values from an item.
1085
     *
1086
     * @param int $itemId (session id, course id, etc)
1087
     * @assert (-1,-1) == null
1088
     */
1089
    public function deleteValuesByItem($itemId)
1090
    {
1091
        $itemId = (int) $itemId;
1092
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
1093
1094
        $sql = "DELETE FROM {$this->table}
1095
                WHERE
1096
                    item_id = $itemId AND
1097
                    field_id IN (
1098
                        SELECT id FROM {$this->table_handler_field}
1099
                        WHERE extra_field_type = $extraFieldType
1100
                    )
1101
                ";
1102
        Database::query($sql);
1103
    }
1104
1105
    /**
1106
     * @param int $itemId
1107
     * @param int $fieldId
1108
     * @param int $fieldValue
1109
     *
1110
     * @return bool
1111
     */
1112
    public function deleteValuesByHandlerAndFieldAndValue($itemId, $fieldId, $fieldValue)
1113
    {
1114
        $itemId = (int) $itemId;
1115
        $fieldId = (int) $fieldId;
1116
1117
        $fieldData = $this->getExtraField()->get($fieldId);
1118
        if ($fieldData) {
1119
            $fieldValue = Database::escape_string($fieldValue);
1120
1121
            $sql = "DELETE FROM {$this->table}
1122
                WHERE
1123
                    item_id = $itemId AND
1124
                    field_id = $fieldId AND
1125
                    value = '$fieldValue'
1126
                ";
1127
            Database::query($sql);
1128
1129
            // Delete file from uploads
1130
            if ($fieldData['field_type'] == ExtraField::FIELD_TYPE_FILE) {
1131
                api_remove_uploaded_file($this->type, basename($fieldValue));
1132
            }
1133
1134
            return true;
1135
        }
1136
1137
        return false;
1138
    }
1139
1140
    /**
1141
     * Get all values for an item.
1142
     *
1143
     * @param int  $itemId          The item ID
1144
     * @param bool $visibleToSelf   Get the visible extra field only
1145
     * @param bool $visibleToOthers
1146
     *
1147
     * @return array
1148
     */
1149
    public function getAllValuesForAnItem($itemId, $visibleToSelf = null, $visibleToOthers = null)
1150
    {
1151
        $em = Database::getManager();
1152
        $qb = $em->createQueryBuilder();
1153
        $qb = $qb->select('fv')
1154
            ->from('ChamiloCoreBundle:ExtraFieldValues', 'fv')
1155
            ->join('fv.field', 'f')
1156
            ->where(
1157
                $qb->expr()->eq('fv.itemId', ':item')
1158
            )
1159
            ->andWhere(
1160
                $qb->expr()->eq('f.extraFieldType', ':extra_field_type')
1161
            );
1162
1163
        if (is_bool($visibleToSelf)) {
1164
            $qb
1165
                ->andWhere($qb->expr()->eq('f.visibleToSelf', ':visibleToSelf'))
1166
                ->setParameter('visibleToSelf', $visibleToSelf);
1167
        }
1168
1169
        if (is_bool($visibleToOthers)) {
1170
            $qb
1171
                ->andWhere($qb->expr()->eq('f.visibleToOthers', ':visibleToOthers'))
1172
                ->setParameter('visibleToOthers', $visibleToOthers);
1173
        }
1174
1175
        $fieldValues = $qb
1176
            ->setParameter('item', $itemId)
1177
            ->setParameter('extra_field_type', $this->getExtraField()->getExtraFieldType())
1178
            ->getQuery()
1179
            ->getResult();
1180
1181
        $fieldOptionsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldOptions');
1182
1183
        $valueList = [];
1184
        /** @var ExtraFieldValues $fieldValue */
1185
        foreach ($fieldValues as $fieldValue) {
1186
            $item = ['value' => $fieldValue];
1187
            switch ($fieldValue->getField()->getFieldType()) {
1188
                case ExtraField::FIELD_TYPE_SELECT:
1189
                    $item['option'] = $fieldOptionsRepo->findOneBy([
1190
                        'field' => $fieldValue->getField(),
1191
                        'value' => $fieldValue->getValue(),
1192
                    ]);
1193
                    break;
1194
            }
1195
            $valueList[] = $item;
1196
        }
1197
1198
        return $valueList;
1199
    }
1200
1201
    public function copy($sourceId, $destinationId)
1202
    {
1203
        if (empty($sourceId) || empty($destinationId)) {
1204
            return false;
1205
        }
1206
1207
        $extraField = new ExtraField($this->type);
1208
        $allFields = $extraField->get_all();
1209
        $extraFieldValue = new ExtraFieldValue($this->type);
1210
        foreach ($allFields as $field) {
1211
            $variable = $field['variable'];
1212
            $sourceValues = $extraFieldValue->get_values_by_handler_and_field_variable($sourceId, $variable);
1213
            if (!empty($sourceValues) && isset($sourceValues['value']) && $sourceValues['value'] != '') {
1214
                $params = [
1215
                    'extra_'.$variable => $sourceValues['value'],
1216
                    'item_id' => $destinationId,
1217
                ];
1218
                $extraFieldValue->saveFieldValues($params, true);
1219
            }
1220
        }
1221
1222
        return true;
1223
    }
1224
}
1225