Passed
Push — master ( 3f9eef...ccbe5e )
by Julito
07:14
created

ExtraFieldValue::copy()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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

183
                        self::/** @scrutinizer ignore-call */ 
184
                              save($newParams, $showQuery);
Loading history...
184
                    }
185
                    break;
186
                case ExtraField::FIELD_TYPE_TAG:
187
                    if (EntityExtraField::USER_FIELD_TYPE == $type) {
188
                        UserManager::delete_user_tags(
189
                            $params['item_id'],
190
                            $extraFieldInfo['id']
191
                        );
192
                        UserManager::process_tags(
193
                            $value,
194
                            $params['item_id'],
195
                            $extraFieldInfo['id']
196
                        );
197
                        break;
198
                    }
199
200
                    $currentTags = $em
201
                        ->getRepository(ExtraFieldRelTag::class)
202
                        ->findBy([
203
                            'fieldId' => $extraFieldInfo['id'],
204
                            'itemId' => $params['item_id'],
205
                        ]);
206
207
                    foreach ($currentTags as $extraFieldtag) {
208
                        $em->remove($extraFieldtag);
209
                    }
210
                    $em->flush();
211
                    $tagValues = is_array($value) ? $value : [$value];
212
                    $tags = [];
213
                    foreach ($tagValues as $tagValue) {
214
                        if (empty($tagValue)) {
215
                            continue;
216
                        }
217
218
                        $tagsResult = $em->getRepository(Tag::class)
219
                            ->findBy([
220
                                'tag' => $tagValue,
221
                                'fieldId' => $extraFieldInfo['id'],
222
                            ]);
223
224
                        if (empty($tagsResult)) {
225
                            $tag = new Tag();
226
                            $tag->setFieldId($extraFieldInfo['id']);
227
                            $tag->setTag($tagValue);
228
229
                            $tags[] = $tag;
230
                        } else {
231
                            $tags = array_merge($tags, $tagsResult);
232
                        }
233
                    }
234
235
                    foreach ($tags as $tag) {
236
                        $tagUses = $em
237
                            ->getRepository(ExtraFieldRelTag::class)
238
                            ->findBy([
239
                                'tagId' => $tag->getId(),
240
                            ]);
241
242
                        $tag->setCount(count($tagUses) + 1);
243
                        $em->persist($tag);
244
                    }
245
246
                    $em->flush();
247
248
                    foreach ($tags as $tag) {
249
                        $fieldRelTag = new ExtraFieldRelTag();
250
                        $fieldRelTag->setFieldId($extraFieldInfo['id']);
251
                        $fieldRelTag->setItemId($params['item_id']);
252
                        $fieldRelTag->setTagId($tag->getId());
253
                        $em->persist($fieldRelTag);
254
                    }
255
256
                    $em->flush();
257
                    break;
258
                case ExtraField::FIELD_TYPE_FILE_IMAGE:
259
                    /*
260
                    $fileDir = $fileDirStored = '';
261
                    switch ($this->type) {
262
                        case 'course':
263
                            $fileDir = api_get_path(SYS_UPLOAD_PATH)."courses/";
264
                            $fileDirStored = "courses/";
265
                            break;
266
                        case 'session':
267
                            $fileDir = api_get_path(SYS_UPLOAD_PATH)."sessions/";
268
                            $fileDirStored = "sessions/";
269
                            break;
270
                        case 'user':
271
                            $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
272
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
273
                            break;
274
                        case 'work':
275
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
276
                            $fileDirStored = 'work/';
277
                            break;
278
                    }*/
279
                    $fileName = ExtraField::FIELD_TYPE_FILE_IMAGE."_{$params['item_id']}.png";
280
                    if (!empty($value['tmp_name']) && isset($value['error']) && 0 == $value['error']) {
281
                        $mimeType = mime_content_type($value['tmp_name']);
282
                        $file = new UploadedFile($value['tmp_name'], $fileName, $mimeType, null, true);
283
                        $asset = new Asset();
284
                        $asset
285
                            ->setCategory(Asset::EXTRA_FIELD)
286
                            ->setTitle($fileName)
287
                            ->setFile($file)
288
                        ;
289
                        $cropVariable = 'extra_'.$field_variable.'_crop_result';
290
                        if (isset($params[$cropVariable])) {
291
                            $asset->setCrop($params[$cropVariable]);
292
                        }
293
                        $em->persist($asset);
294
                        $em->flush();
295
                        $assetId = $asset->getId();
296
                        //$repo = Container::getAssetRepository();
297
                        if ($assetId) {
298
                            // Crop the image to adjust 16:9 ratio
299
                            /*$imageExtraField = new Image($value['tmp_name']);
300
                            $imageExtraField->resize(400);
301
                            $imageExtraField->send_image($fileDir.$fileName, -1, 'png');*/
302
                            $newParams = [
303
                                'item_id' => $params['item_id'],
304
                                'field_id' => $extraFieldInfo['id'],
305
                                'value' => $assetId,
306
                                'comment' => $comment,
307
                            ];
308
                            $this->save($newParams);
309
                        }
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']) && 0 == $value['error']) {
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
                        $mimeType = mime_content_type($value['tmp_name']);
354
                        $file = new UploadedFile($value['tmp_name'], $fileName, $mimeType, null, true);
355
                        $asset = new Asset();
356
                        $asset
357
                            ->setCategory(Asset::EXTRA_FIELD)
358
                            ->setTitle($fileName)
359
                            ->setFile($file)
360
                        ;
361
                        $em->persist($asset);
362
                        $em->flush();
363
                        $assetId = $asset->getId();
364
365
                        if ($assetId) {
366
                            $new_params = [
367
                                'item_id' => $params['item_id'],
368
                                'field_id' => $extraFieldInfo['id'],
369
                                'value' => $assetId,
370
                            ];
371
                            if ('session' !== $this->type && 'course' !== $this->type) {
372
                                $new_params['comment'] = $comment;
373
                            }
374
375
                            $this->save($new_params);
376
                        }
377
                    }
378
                    break;
379
                case ExtraField::FIELD_TYPE_CHECKBOX:
380
                    $fieldToSave = 0;
381
                    if (is_array($value)) {
382
                        if (isset($value['extra_'.$field_variable])) {
383
                            $fieldToSave = 1;
384
                        }
385
                    }
386
387
                    $newParams = [
388
                        'item_id' => $params['item_id'],
389
                        'field_id' => $extraFieldInfo['id'],
390
                        'value' => $fieldToSave,
391
                        'comment' => $comment,
392
                    ];
393
                    $this->save($newParams);
394
395
                    break;
396
                case ExtraField::FIELD_TYPE_DATE:
397
                    $d = DateTime::createFromFormat('Y-m-d', $value);
398
                    $valid = $d && $d->format('Y-m-d') === $value;
399
                    if ($valid) {
400
                        $newParams = [
401
                            'item_id' => $params['item_id'],
402
                            'field_id' => $extraFieldInfo['id'],
403
                            'value' => $value,
404
                            'comment' => $comment,
405
                        ];
406
                        $this->save($newParams, $showQuery);
407
                    }
408
                    break;
409
                case ExtraField::FIELD_TYPE_DATETIME:
410
                    $d = DateTime::createFromFormat('Y-m-d H:i', $value);
411
                    $valid = $d && $d->format('Y-m-d H:i') === $value;
412
                    if ($valid) {
413
                        $newParams = [
414
                            'item_id' => $params['item_id'],
415
                            'field_id' => $extraFieldInfo['id'],
416
                            'value' => $value,
417
                            'comment' => $comment,
418
                        ];
419
                        $this->save($newParams, $showQuery);
420
                    }
421
                    break;
422
                default:
423
                    $newParams = [
424
                        'item_id' => $params['item_id'],
425
                        'field_id' => $extraFieldInfo['id'],
426
                        'value' => $value,
427
                        'comment' => $comment,
428
                    ];
429
                    $this->save($newParams, $showQuery);
430
            }
431
        }
432
    }
433
434
    /**
435
     * Save values in the *_field_values table.
436
     *
437
     * @param array $params    Structured array with the values to save
438
     * @param bool  $showQuery Whether to show the insert query (passed to the parent save() method)
439
     *
440
     * @return mixed The result sent from the parent method
441
     * @assert (array()) === false
442
     */
443
    public function save($params, $showQuery = false)
444
    {
445
        $extra_field = $this->getExtraField();
446
447
        // Setting value to insert.
448
        $value = $params['value'];
449
        $value_to_insert = null;
450
451
        if (is_array($value)) {
452
            $value_to_insert = implode(';', $value);
453
        } else {
454
            $value_to_insert = $value;
455
        }
456
457
        $params['value'] = $value_to_insert;
458
459
        // If field id exists
460
        if (isset($params['field_id'])) {
461
            $extraFieldInfo = $extra_field->get($params['field_id']);
462
        } else {
463
            // Try the variable
464
            $extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable(
465
                $params['variable']
466
            );
467
            if ($extraFieldInfo) {
468
                $params['field_id'] = $extraFieldInfo['id'];
469
            }
470
        }
471
472
        if ($extraFieldInfo) {
473
            switch ($extraFieldInfo['field_type']) {
474
                case ExtraField::FIELD_TYPE_RADIO:
475
                case ExtraField::FIELD_TYPE_SELECT:
476
                    break;
477
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
478
                    //$field_options = $session_field_option->get_field_options_by_field($params['field_id']);
479
                    //$params['field_value'] = split(';', $value_to_insert);
480
                    /*
481
                        if ($field_options) {
482
                            $check = false;
483
                            foreach ($field_options as $option) {
484
                                if (in_array($option['option_value'], $values)) {
485
                                    $check = true;
486
                                    break;
487
                                }
488
                           }
489
                           if (!$check) {
490
                               return false; //option value not found
491
                           }
492
                       } else {
493
                           return false; //enumerated type but no option found
494
                       }*/
495
                    break;
496
                case ExtraField::FIELD_TYPE_TEXT:
497
                case ExtraField::FIELD_TYPE_TEXTAREA:
498
                    break;
499
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
500
                case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
501
                    if (is_array($value)) {
502
                        $value_to_insert = null;
503
                        if (isset($value['extra_'.$extraFieldInfo['variable']]) &&
504
                            isset($value['extra_'.$extraFieldInfo['variable'].'_second'])
505
                        ) {
506
                            $value_to_insert = $value['extra_'.$extraFieldInfo['variable']].'::'.$value['extra_'.$extraFieldInfo['variable'].'_second'];
507
                        }
508
                    }
509
                    break;
510
                default:
511
                    break;
512
            }
513
514
            if (ExtraField::FIELD_TYPE_TAG == $extraFieldInfo['field_type']) {
515
                $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

515
                /** @scrutinizer ignore-call */ 
516
                $field_values = self::getAllValuesByItemAndFieldAndValue(
Loading history...
516
                    $params['item_id'],
517
                    $params['field_id'],
518
                    $value
519
                );
520
            } else {
521
                $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

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