Passed
Push — master ( f437d8...92f70a )
by Julito
10:14
created

ExtraFieldValue   F

Complexity

Total Complexity 151

Size/Duplication

Total Lines 1167
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 622
dl 0
loc 1167
rs 1.978
c 0
b 0
f 0
wmc 151

19 Methods

Rating   Name   Duplication   Size   Complexity  
A get_count() 0 9 1
A getExtraField() 0 3 1
A __construct() 0 8 1
A getAllValuesForAnItem() 0 50 5
A deleteValuesByItem() 0 14 1
A delete_all_values_by_field_id() 0 7 1
B getAllValuesByItem() 0 65 8
C get_values_by_handler_and_field_id() 0 72 12
A searchValuesByField() 0 25 2
A get_item_id_from_field_variable_and_field_value() 0 38 5
A delete_values_by_handler_and_field_id() 0 12 1
F saveFieldValues() 0 284 55
F save() 0 200 35
A getAllValuesByItemAndFieldAndValue() 0 23 2
C get_values_by_handler_and_field_variable() 0 76 13
A deleteValuesByHandlerAndFieldAndValue() 0 26 3
A getValuesByFieldId() 0 19 2
A getAllValuesByItemAndField() 0 21 2
A compareItemValues() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like ExtraFieldValue often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExtraFieldValue, and based on these observations, apply Extract Interface, too.

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

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

457
                /** @scrutinizer ignore-call */ 
458
                $field_values = self::getAllValuesByItemAndFieldAndValue(
Loading history...
458
                    $params['item_id'],
459
                    $params['field_id'],
460
                    $value
461
                );
462
            } else {
463
                $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

463
                /** @scrutinizer ignore-call */ 
464
                $field_values = self::get_values_by_handler_and_field_id(
Loading history...
464
                    $params['item_id'],
465
                    $params['field_id']
466
                );
467
            }
468
469
            $params['value'] = $value_to_insert;
470
            //$params['author_id'] = api_get_user_id();
471
472
            // Insert
473
            if (empty($field_values)) {
474
                /* Enable this when field_loggeable is introduced as a table field (2.0)
475
                if ($extraFieldInfo['field_loggeable'] == 1) {
476
                */
477
                if (false) {
478
                    global $app;
479
                    switch ($this->type) {
480
                        case 'question':
481
                            $extraFieldValue = new ChamiloLMS\Entity\QuestionFieldValues();
482
                            $extraFieldValue->setUserId(api_get_user_id());
483
                            $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...
484
                            break;
485
                        case 'course':
486
                            $extraFieldValue = new ChamiloLMS\Entity\CourseFieldValues();
487
                            $extraFieldValue->setUserId(api_get_user_id());
488
                            $extraFieldValue->setQuestionId($params[$this->handler_id]);
489
                            break;
490
                        case 'user':
491
                            $extraFieldValue = new ChamiloLMS\Entity\UserFieldValues();
492
                            $extraFieldValue->setUserId($params[$this->handler_id]);
493
                            $extraFieldValue->setAuthorId(api_get_user_id());
494
                            break;
495
                        case 'session':
496
                            $extraFieldValue = new ChamiloLMS\Entity\SessionFieldValues();
497
                            $extraFieldValue->setUserId(api_get_user_id());
498
                            $extraFieldValue->setSessionId($params[$this->handler_id]);
499
                            break;
500
                    }
501
                    if (isset($extraFieldValue)) {
502
                        if (!empty($params['value'])) {
503
                            $extraFieldValue->setComment($params['comment']);
504
                            $extraFieldValue->setFieldValue($params['value']);
505
                            $extraFieldValue->setFieldId($params['field_id']);
506
                            $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
507
                            $app['orm.ems']['db_write']->persist($extraFieldValue);
508
                            $app['orm.ems']['db_write']->flush();
509
                        }
510
                    }
511
                } else {
512
                    if ($extraFieldInfo['field_type'] == ExtraField::FIELD_TYPE_TAG) {
513
                        $option = new ExtraFieldOption($this->type);
514
                        $optionExists = $option->get($params['value']);
515
                        if (empty($optionExists)) {
516
                            $optionParams = [
517
                                'field_id' => $params['field_id'],
518
                                'option_value' => $params['value'],
519
                            ];
520
                            $optionId = $option->saveOptions($optionParams);
521
                        } else {
522
                            $optionId = $optionExists['id'];
523
                        }
524
525
                        $params['value'] = $optionId;
526
                        if ($optionId) {
527
                            return parent::save($params, $showQuery);
528
                        }
529
                    } else {
530
                        return parent::save($params, $showQuery);
531
                    }
532
                }
533
            } else {
534
                // Update
535
                /* Enable this when field_loggeable is introduced as a table field (2.0)
536
                if ($extraFieldInfo['field_loggeable'] == 1) {
537
                */
538
                if (false) {
539
                    global $app;
540
                    switch ($this->type) {
541
                        case 'question':
542
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\QuestionFieldValues')->find($field_values['id']);
543
                            $extraFieldValue->setUserId(api_get_user_id());
544
                            $extraFieldValue->setQuestionId($params[$this->handler_id]);
545
                            break;
546
                        case 'course':
547
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\CourseFieldValues')->find($field_values['id']);
548
                            $extraFieldValue->setUserId(api_get_user_id());
549
                            $extraFieldValue->setCourseCode($params[$this->handler_id]);
550
                            break;
551
                        case 'user':
552
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\UserFieldValues')->find($field_values['id']);
553
                            $extraFieldValue->setUserId(api_get_user_id());
554
                            $extraFieldValue->setAuthorId(api_get_user_id());
555
                            break;
556
                        case 'session':
557
                            $extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\SessionFieldValues')->find($field_values['id']);
558
                            $extraFieldValue->setUserId(api_get_user_id());
559
                            $extraFieldValue->setSessionId($params[$this->handler_id]);
560
                            break;
561
                    }
562
563
                    if (isset($extraFieldValue)) {
564
                        if (!empty($params['value'])) {
565
                            /*
566
                             *  If the field value is similar to the previous value then the comment will be the same
567
                                in order to no save in the log an empty record
568
                            */
569
                            if ($extraFieldValue->getFieldValue() == $params['value']) {
570
                                if (empty($params['comment'])) {
571
                                    $params['comment'] = $extraFieldValue->getComment();
572
                                }
573
                            }
574
575
                            $extraFieldValue->setComment($params['comment']);
576
                            $extraFieldValue->setFieldValue($params['value']);
577
                            $extraFieldValue->setFieldId($params['field_id']);
578
                            $extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
579
                            $app['orm.ems']['db_write']->persist($extraFieldValue);
580
                            $app['orm.ems']['db_write']->flush();
581
                        }
582
                    }
583
                } else {
584
                    $params['id'] = $field_values['id'];
585
586
                    return parent::update($params, $showQuery);
587
                }
588
            }
589
        }
590
    }
591
592
    /**
593
     * Returns the value of the given extra field on the given resource.
594
     *
595
     * @param int  $item_id   Item ID (It could be a session_id, course_id or user_id)
596
     * @param int  $field_id  Field ID (the ID from the *_field table)
597
     * @param bool $transform Whether to transform the result to a human readable strings
598
     *
599
     * @return mixed A structured array with the field_id and field_value, or false on error
600
     * @assert (-1,-1) === false
601
     */
602
    public function get_values_by_handler_and_field_id($item_id, $field_id, $transform = false)
603
    {
604
        $field_id = (int) $field_id;
605
        $item_id = Database::escape_string($item_id);
606
607
        $sql = "SELECT s.*, field_type FROM {$this->table} s
608
                INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id)
609
                WHERE
610
                    item_id = '$item_id' AND
611
                    field_id = '".$field_id."' AND
612
                    sf.extra_field_type = ".$this->getExtraField()->getExtraFieldType()."
613
                ORDER BY id";
614
        $result = Database::query($sql);
615
        if (Database::num_rows($result)) {
616
            $result = Database::fetch_array($result, 'ASSOC');
617
            if ($transform) {
618
                if (!empty($result['value'])) {
619
                    switch ($result['field_type']) {
620
                        case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
621
                            $field_option = new ExtraFieldOption($this->type);
622
                            $options = explode('::', $result['value']);
623
                            // only available for PHP 5.4  :( $result['field_value'] = $field_option->get($options[0])['id'].' -> ';
624
                            $result = $field_option->get($options[0]);
625
                            $result_second = $field_option->get($options[1]);
626
                            if (!empty($result)) {
627
                                $result['value'] = $result['display_text'].' -> ';
628
                                $result['value'] .= $result_second['display_text'];
629
                            }
630
                            break;
631
                        case ExtraField::FIELD_TYPE_SELECT:
632
                            $field_option = new ExtraFieldOption($this->type);
633
                            $extra_field_option_result = $field_option->get_field_option_by_field_and_option(
634
                                $result['field_id'],
635
                                $result['value']
636
                            );
637
638
                            if (isset($extra_field_option_result[0])) {
639
                                $result['value'] = $extra_field_option_result[0]['display_text'];
640
                            }
641
                            break;
642
                        case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
643
                            $options = explode('::', $result['value']);
644
645
                            $field_option = new ExtraFieldOption($this->type);
646
                            $result = $field_option->get($options[0]);
647
648
                            if (!empty($result)) {
649
                                $result['value'] = $result['display_text']
650
                                    .'&rarr;'
651
                                    .$options[1];
652
                            }
653
                            break;
654
                        case ExtraField::FIELD_TYPE_TRIPLE_SELECT:
655
                            $optionIds = explode(';', $result['value']);
656
                            $optionValues = [];
657
658
                            foreach ($optionIds as $optionId) {
659
                                $objEfOption = new ExtraFieldOption('user');
660
                                $optionInfo = $objEfOption->get($optionId);
661
662
                                $optionValues[] = $optionInfo['display_text'];
663
                            }
664
665
                            $result['value'] = implode(' / ', $optionValues);
666
                            break;
667
                    }
668
                }
669
            }
670
671
            return $result;
672
        } else {
673
            return false;
674
        }
675
    }
676
677
    /**
678
     * @param string $tag
679
     * @param int    $field_id
680
     * @param int    $limit
681
     *
682
     * @return array
683
     */
684
    public function searchValuesByField($tag, $field_id, $limit = 10)
685
    {
686
        $field_id = (int) $field_id;
687
        $limit = (int) $limit;
688
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
689
690
        $tag = Database::escape_string($tag);
691
        $sql = "SELECT DISTINCT s.value, s.field_id
692
                FROM {$this->table} s
693
                INNER JOIN {$this->table_handler_field} sf
694
                ON (s.field_id = sf.id)
695
                WHERE
696
                    field_id = '".$field_id."' AND
697
                    value LIKE '%$tag%' AND
698
                    sf.extra_field_type = ".$extraFieldType."
699
                ORDER BY value
700
                LIMIT 0, $limit
701
                ";
702
        $result = Database::query($sql);
703
        $values = [];
704
        if (Database::num_rows($result)) {
705
            $values = Database::store_result($result, 'ASSOC');
706
        }
707
708
        return $values;
709
    }
710
711
    /**
712
     * Gets a structured array of the original item and its extra values, using
713
     * a specific original item and a field name (like "branch", or "birthdate").
714
     *
715
     * @param int    $item_id            Item ID from the original table
716
     * @param string $field_variable     The name of the field we are looking for
717
     * @param bool   $transform
718
     * @param bool   $filterByVisibility
719
     * @param int    $visibility
720
     *
721
     * @return mixed Array of results, or false on error or not found
722
     * @assert (-1,'') === false
723
     */
724
    public function get_values_by_handler_and_field_variable(
725
        $item_id,
726
        $field_variable,
727
        $transform = false,
728
        $filterByVisibility = false,
729
        $visibility = 0
730
    ) {
731
        $item_id = (int) $item_id;
732
        $field_variable = Database::escape_string($field_variable);
733
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
734
735
        $sql = "SELECT s.*, field_type
736
                FROM {$this->table} s
737
                INNER JOIN {$this->table_handler_field} sf
738
                ON (s.field_id = sf.id)
739
                WHERE
740
                    item_id = '$item_id'  AND
741
                    variable = '".$field_variable."' AND
742
                    sf.extra_field_type = $extraFieldType
743
                ";
744
        if ($filterByVisibility) {
745
            $visibility = (int) $visibility;
746
            $sql .= " AND visible_to_self = $visibility ";
747
        }
748
        $sql .= ' ORDER BY id';
749
750
        $result = Database::query($sql);
751
        if (Database::num_rows($result)) {
752
            $result = Database::fetch_array($result, 'ASSOC');
753
            if ($transform) {
754
                if ($result['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
755
                    if (!empty($result['value'])) {
756
                        $field_option = new ExtraFieldOption($this->type);
757
                        $options = explode('::', $result['value']);
758
                        $result = $field_option->get($options[0]);
759
                        $result_second = $field_option->get($options[1]);
760
                        if (!empty($result)) {
761
                            $result['value'] = $result['display_text'].' -> ';
762
                            $result['value'] .= $result_second['display_text'];
763
                        }
764
                    }
765
                }
766
                if ($result['field_type'] == ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD) {
767
                    if (!empty($result['value'])) {
768
                        $options = explode('::', $result['value']);
769
770
                        $field_option = new ExtraFieldOption($this->type);
771
                        $result = $field_option->get($options[0]);
772
773
                        if (!empty($result)) {
774
                            $result['value'] = $result['display_text']
775
                                .'&rarr;'
776
                                .$options[1];
777
                        }
778
                    }
779
                }
780
                if ($result['field_type'] == ExtraField::FIELD_TYPE_TRIPLE_SELECT) {
781
                    if (!empty($result['value'])) {
782
                        $optionIds = explode(';', $result['value']);
783
                        $optionValues = [];
784
785
                        foreach ($optionIds as $optionId) {
786
                            $objEfOption = new ExtraFieldOption('user');
787
                            $optionInfo = $objEfOption->get($optionId);
788
789
                            $optionValues[] = $optionInfo['display_text'];
790
                        }
791
792
                        $result['value'] = implode(' / ', $optionValues);
793
                    }
794
                }
795
            }
796
797
            return $result;
798
        } else {
799
            return false;
800
        }
801
    }
802
803
    /**
804
     * Gets the ID from the item (course, session, etc) for which
805
     * the given field is defined with the given value.
806
     *
807
     * @param string $field_variable Field (type of data) we want to check
808
     * @param string $field_value    Data we are looking for in the given field
809
     * @param bool   $transform      Whether to transform the result to a human readable strings
810
     * @param bool   $last           Whether to return the last element or simply the first one we get
811
     *
812
     * @return mixed Give the ID if found, or false on failure or not found
813
     * @assert (-1,-1) === false
814
     */
815
    public function get_item_id_from_field_variable_and_field_value(
816
        $field_variable,
817
        $field_value,
818
        $transform = false,
0 ignored issues
show
Unused Code introduced by
The parameter $transform is not used and could be removed. ( Ignorable by Annotation )

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

818
        /** @scrutinizer ignore-unused */ $transform = false,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
819
        $last = false,
820
        $all = false
821
    ) {
822
        $field_value = Database::escape_string($field_value);
823
        $field_variable = Database::escape_string($field_variable);
824
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
825
826
        $sql = "SELECT item_id FROM {$this->table} s
827
                INNER JOIN {$this->table_handler_field} sf
828
                ON (s.field_id = sf.id)
829
                WHERE
830
                    value  = '$field_value' AND
831
                    variable = '".$field_variable."' AND
832
                    sf.extra_field_type = $extraFieldType
833
                ORDER BY item_id
834
                ";
835
836
        if ($last) {
837
            // If we want the last element instead of the first
838
            // This is useful in special cases where there might
839
            // (erroneously) be more than one row for an item
840
            $sql .= ' DESC';
841
        }
842
        $result = Database::query($sql);
843
        if ($result !== false && Database::num_rows($result)) {
844
            if ($all) {
845
                $result = Database::store_result($result, 'ASSOC');
846
            } else {
847
                $result = Database::fetch_array($result, 'ASSOC');
848
            }
849
850
            return $result;
851
        } else {
852
            return false;
853
        }
854
    }
855
856
    /**
857
     * Get all the values stored for one specific field.
858
     *
859
     * @param int $fieldId
860
     *
861
     * @return array|bool
862
     */
863
    public function getValuesByFieldId($fieldId)
864
    {
865
        $fieldId = (int) $fieldId;
866
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
867
868
        $sql = "SELECT s.* FROM {$this->table} s
869
                INNER JOIN {$this->table_handler_field} sf
870
                ON (s.field_id = sf.id)
871
                WHERE
872
                    field_id = '".$fieldId."' AND
873
                    sf.extra_field_type = $extraFieldType
874
                ORDER BY s.value";
875
        $result = Database::query($sql);
876
877
        if (Database::num_rows($result)) {
878
            return Database::store_result($result, 'ASSOC');
879
        }
880
881
        return false;
882
    }
883
884
    /**
885
     * @param int $itemId
886
     * @param int $fieldId
887
     *
888
     * @return array
889
     */
890
    public function getAllValuesByItemAndField($itemId, $fieldId)
891
    {
892
        $fieldId = (int) $fieldId;
893
        $itemId = (int) $itemId;
894
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
895
896
        $sql = "SELECT s.* FROM {$this->table} s
897
                INNER JOIN {$this->table_handler_field} sf
898
                ON (s.field_id = sf.id)
899
                WHERE
900
                    field_id = $fieldId AND
901
                    item_id = $itemId AND
902
                    sf.extra_field_type = $extraFieldType
903
                ORDER BY s.value";
904
        $result = Database::query($sql);
905
906
        if (Database::num_rows($result)) {
907
            return Database::store_result($result, 'ASSOC');
908
        }
909
910
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
911
    }
912
913
    /**
914
     * @param int $itemId
915
     *
916
     * @return array
917
     */
918
    public function getAllValuesByItem($itemId)
919
    {
920
        $itemId = (int) $itemId;
921
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
922
923
        $sql = "SELECT s.value, sf.variable, sf.field_type, sf.id, sf.display_text
924
                FROM {$this->table} s
925
                INNER JOIN {$this->table_handler_field} sf
926
                ON (s.field_id = sf.id)
927
                WHERE
928
                    item_id = '$itemId' AND
929
                    sf.extra_field_type = $extraFieldType
930
                ORDER BY s.value";
931
932
        $result = Database::query($sql);
933
        $idList = [];
934
        if (Database::num_rows($result)) {
935
            $result = Database::store_result($result, 'ASSOC');
936
            $finalResult = [];
937
            foreach ($result as $item) {
938
                $finalResult[$item['id']] = $item;
939
            }
940
            $idList = array_column($result, 'id');
941
        }
942
943
        $em = Database::getManager();
944
945
        $extraField = new ExtraField($this->type);
946
        $allData = $extraField->get_all(['filter = ?' => 1]);
947
        $allResults = [];
948
        foreach ($allData as $field) {
949
            if (in_array($field['id'], $idList)) {
950
                $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...
951
            } else {
952
                if ($field['field_type'] == ExtraField::FIELD_TYPE_TAG) {
953
                    $tagResult = [];
954
                    $tags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
955
                        ->findBy(
956
                            [
957
                                'fieldId' => $field['id'],
958
                                'itemId' => $itemId,
959
                            ]
960
                        );
961
                    if ($tags) {
962
                        /** @var ExtraFieldRelTag $extraFieldTag */
963
                        foreach ($tags as $extraFieldTag) {
964
                            /** @var \Chamilo\CoreBundle\Entity\Tag $tag */
965
                            $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
966
                            $tagResult[] = [
967
                                'id' => $extraFieldTag->getTagId(),
968
                                'value' => $tag->getTag(),
969
                            ];
970
                        }
971
                    }
972
                    $allResults[] = [
973
                        'value' => $tagResult,
974
                        'variable' => $field['variable'],
975
                        'field_type' => $field['field_type'],
976
                        'id' => $field['id'],
977
                    ];
978
                }
979
            }
980
        }
981
982
        return $allResults;
983
    }
984
985
    /**
986
     * @param int    $itemId
987
     * @param int    $fieldId
988
     * @param string $fieldValue
989
     *
990
     * @return array|bool
991
     */
992
    public function getAllValuesByItemAndFieldAndValue($itemId, $fieldId, $fieldValue)
993
    {
994
        $fieldId = (int) $fieldId;
995
        $itemId = (int) $itemId;
996
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
997
998
        $fieldValue = Database::escape_string($fieldValue);
999
        $sql = "SELECT s.* FROM {$this->table} s
1000
                INNER JOIN {$this->table_handler_field} sf
1001
                ON (s.field_id = sf.id)
1002
                WHERE
1003
                    field_id = '$fieldId' AND
1004
                    item_id = '$itemId' AND
1005
                    value = '$fieldValue' AND
1006
                    sf.extra_field_type = $extraFieldType
1007
                ORDER BY value";
1008
1009
        $result = Database::query($sql);
1010
        if (Database::num_rows($result)) {
1011
            return Database::store_result($result, 'ASSOC');
1012
        }
1013
1014
        return false;
1015
    }
1016
1017
    /**
1018
     * Deletes all the values related to a specific field ID.
1019
     *
1020
     * @param int $field_id
1021
     *
1022
     * @assert ('a') == null
1023
     */
1024
    public function delete_all_values_by_field_id($field_id)
1025
    {
1026
        $field_id = (int) $field_id;
1027
        $sql = "DELETE FROM {$this->table}
1028
                WHERE
1029
                    field_id = $field_id ";
1030
        Database::query($sql);
1031
    }
1032
1033
    /**
1034
     * Deletes values of a specific field for a specific item.
1035
     *
1036
     * @param int $item_id  (session id, course id, etc)
1037
     * @param int $field_id
1038
     * @assert (-1,-1) == null
1039
     */
1040
    public function delete_values_by_handler_and_field_id($item_id, $field_id)
1041
    {
1042
        $field_id = (int) $field_id;
1043
        $item_id = (int) $item_id;
1044
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
1045
1046
        $sql = "DELETE FROM {$this->table}
1047
                WHERE
1048
                    item_id = '$item_id' AND
1049
                    field_id = '$field_id'
1050
                ";
1051
        Database::query($sql);
1052
    }
1053
1054
    /**
1055
     * Deletes all values from an item.
1056
     *
1057
     * @param int $itemId (session id, course id, etc)
1058
     * @assert (-1,-1) == null
1059
     */
1060
    public function deleteValuesByItem($itemId)
1061
    {
1062
        $itemId = (int) $itemId;
1063
        $extraFieldType = $this->getExtraField()->getExtraFieldType();
1064
1065
        $sql = "DELETE FROM {$this->table}
1066
                WHERE
1067
                    item_id = '$itemId' AND
1068
                    field_id IN (
1069
                        SELECT id FROM {$this->table_handler_field}
1070
                        WHERE extra_field_type = ".$extraFieldType."
1071
                    )
1072
                ";
1073
        Database::query($sql);
1074
    }
1075
1076
    /**
1077
     * @param int $itemId
1078
     * @param int $fieldId
1079
     * @param int $fieldValue
1080
     *
1081
     * @return bool
1082
     */
1083
    public function deleteValuesByHandlerAndFieldAndValue($itemId, $fieldId, $fieldValue)
1084
    {
1085
        $itemId = (int) $itemId;
1086
        $fieldId = (int) $fieldId;
1087
1088
        $fieldData = $this->getExtraField()->get($fieldId);
1089
        if ($fieldData) {
1090
            $fieldValue = Database::escape_string($fieldValue);
1091
1092
            $sql = "DELETE FROM {$this->table}
1093
                WHERE
1094
                    item_id = '$itemId' AND
1095
                    field_id = '$fieldId' AND
1096
                    value = '$fieldValue'
1097
                ";
1098
            Database::query($sql);
1099
1100
            // Delete file from uploads
1101
            if ($fieldData['field_type'] == ExtraField::FIELD_TYPE_FILE) {
1102
                api_remove_uploaded_file($this->type, basename($fieldValue));
1103
            }
1104
1105
            return true;
1106
        }
1107
1108
        return false;
1109
    }
1110
1111
    /**
1112
     * Not yet implemented - Compares the field values of two items.
1113
     *
1114
     * @param int $item_id         Item 1
1115
     * @param int $item_to_compare Item 2
1116
     *
1117
     * @todo
1118
     *
1119
     * @return mixed Differential array generated from the comparison
1120
     */
1121
    public function compareItemValues($item_id, $item_to_compare)
0 ignored issues
show
Unused Code introduced by
The parameter $item_to_compare is not used and could be removed. ( Ignorable by Annotation )

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

1121
    public function compareItemValues($item_id, /** @scrutinizer ignore-unused */ $item_to_compare)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $item_id is not used and could be removed. ( Ignorable by Annotation )

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

1121
    public function compareItemValues(/** @scrutinizer ignore-unused */ $item_id, $item_to_compare)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1122
    {
1123
    }
1124
1125
    /**
1126
     * Get all values for an item.
1127
     *
1128
     * @param int  $itemId          The item ID
1129
     * @param bool $visibleToSelf   Get the visible extra field only
1130
     * @param bool $visibleToOthers
1131
     *
1132
     * @return array
1133
     */
1134
    public function getAllValuesForAnItem($itemId, $visibleToSelf = null, $visibleToOthers = null)
1135
    {
1136
        $em = Database::getManager();
1137
        $qb = $em->createQueryBuilder();
1138
        $qb = $qb->select('fv')
1139
            ->from('ChamiloCoreBundle:ExtraFieldValues', 'fv')
1140
            ->join('fv.field', 'f')
1141
            ->where(
1142
                $qb->expr()->eq('fv.itemId', ':item')
1143
            )
1144
            ->andWhere(
1145
                $qb->expr()->eq('f.extraFieldType', ':extra_field_type')
1146
            );
1147
1148
        if (is_bool($visibleToSelf)) {
1149
            $qb
1150
                ->andWhere($qb->expr()->eq('f.visibleToSelf', ':visibleToSelf'))
1151
                ->setParameter('visibleToSelf', $visibleToSelf);
1152
        }
1153
1154
        if (is_bool($visibleToOthers)) {
1155
            $qb
1156
                ->andWhere($qb->expr()->eq('f.visibleToOthers', ':visibleToOthers'))
1157
                ->setParameter('visibleToOthers', $visibleToOthers);
1158
        }
1159
1160
        $fieldValues = $qb
1161
            ->setParameter('item', $itemId)
1162
            ->setParameter('extra_field_type', $this->getExtraField()->getExtraFieldType())
1163
            ->getQuery()
1164
            ->getResult();
1165
1166
        $fieldOptionsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldOptions');
1167
1168
        $valueList = [];
1169
        /** @var ExtraFieldValues $fieldValue */
1170
        foreach ($fieldValues as $fieldValue) {
1171
            $item = ['value' => $fieldValue];
1172
            switch ($fieldValue->getField()->getFieldType()) {
1173
                case ExtraField::FIELD_TYPE_SELECT:
1174
                    $item['option'] = $fieldOptionsRepo->findOneBy([
1175
                        'field' => $fieldValue->getField(),
1176
                        'value' => $fieldValue->getValue(),
1177
                    ]);
1178
                    break;
1179
            }
1180
            $valueList[] = $item;
1181
        }
1182
1183
        return $valueList;
1184
    }
1185
}
1186