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

180
                        self::/** @scrutinizer ignore-call */ 
181
                              save($newParams, $showQuery);
Loading history...
181
                    }
182
                    break;
183
                case ExtraField::FIELD_TYPE_TAG:
184
                    if (EntityExtraField::USER_FIELD_TYPE == $type) {
185
                        UserManager::delete_user_tags(
186
                            $params['item_id'],
187
                            $extraFieldInfo['id']
188
                        );
189
190
                        UserManager::process_tags(
191
                            $value,
192
                            $params['item_id'],
193
                            $extraFieldInfo['id']
194
                        );
195
                        break;
196
                    }
197
198
                    $em = Database::getManager();
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
214
                    foreach ($tagValues as $tagValue) {
215
                        if (empty($tagValue)) {
216
                            continue;
217
                        }
218
219
                        $tagsResult = $em->getRepository(Tag::class)
220
                            ->findBy([
221
                                'tag' => $tagValue,
222
                                'fieldId' => $extraFieldInfo['id'],
223
                            ]);
224
225
                        if (empty($tagsResult)) {
226
                            $tag = new Tag();
227
                            $tag->setFieldId($extraFieldInfo['id']);
228
                            $tag->setTag($tagValue);
229
230
                            $tags[] = $tag;
231
                        } else {
232
                            $tags = array_merge($tags, $tagsResult);
233
                        }
234
                    }
235
236
                    foreach ($tags as $tag) {
237
                        $tagUses = $em
238
                            ->getRepository(ExtraFieldRelTag::class)
239
                            ->findBy([
240
                                'tagId' => $tag->getId(),
241
                            ]);
242
243
                        $tag->setCount(count($tagUses) + 1);
244
                        $em->persist($tag);
245
                    }
246
247
                    $em->flush();
248
249
                    foreach ($tags as $tag) {
250
                        $fieldRelTag = new ExtraFieldRelTag();
251
                        $fieldRelTag->setFieldId($extraFieldInfo['id']);
252
                        $fieldRelTag->setItemId($params['item_id']);
253
                        $fieldRelTag->setTagId($tag->getId());
254
                        $em->persist($fieldRelTag);
255
                    }
256
257
                    $em->flush();
258
                    break;
259
                case ExtraField::FIELD_TYPE_FILE_IMAGE:
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');
0 ignored issues
show
Deprecated Code introduced by
The function UserManager::getUserPathById() has been deprecated: use Resources ( Ignorable by Annotation )

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

271
                            $fileDir = /** @scrutinizer ignore-deprecated */ UserManager::getUserPathById($params['item_id'], 'system');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
272
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
0 ignored issues
show
Deprecated Code introduced by
The function UserManager::getUserPathById() has been deprecated: use Resources ( Ignorable by Annotation )

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

272
                            $fileDirStored = /** @scrutinizer ignore-deprecated */ UserManager::getUserPathById($params['item_id'], 'last');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
273
                            break;
274
                        case 'work':
275
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
276
                            $fileDirStored = 'work/';
277
                            break;
278
                    }
279
280
                    $fileName = ExtraField::FIELD_TYPE_FILE_IMAGE."_{$params['item_id']}.png";
281
282
                    if (!file_exists($fileDir)) {
283
                        mkdir($fileDir, $dirPermissions, true);
284
                    }
285
286
                    if (!empty($value['tmp_name']) && isset($value['error']) && 0 == $value['error']) {
287
                        // Crop the image to adjust 16:9 ratio
288
                        if (isset($params['extra_'.$field_variable.'_crop_result'])) {
289
                            $crop = new Image($value['tmp_name']);
0 ignored issues
show
Deprecated Code introduced by
The class Image has been deprecated. ( Ignorable by Annotation )

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

289
                            $crop = /** @scrutinizer ignore-deprecated */ new Image($value['tmp_name']);
Loading history...
290
                            $crop->crop($params['extra_'.$field_variable.'_crop_result']);
291
                        }
292
293
                        $imageExtraField = new Image($value['tmp_name']);
0 ignored issues
show
Deprecated Code introduced by
The class Image has been deprecated. ( Ignorable by Annotation )

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

293
                        $imageExtraField = /** @scrutinizer ignore-deprecated */ new Image($value['tmp_name']);
Loading history...
294
                        $imageExtraField->resize(400);
295
                        $imageExtraField->send_image($fileDir.$fileName, -1, 'png');
296
                        $newParams = [
297
                            'item_id' => $params['item_id'],
298
                            'field_id' => $extraFieldInfo['id'],
299
                            'value' => $fileDirStored.$fileName,
300
                            'comment' => $comment,
301
                        ];
302
                        $this->save($newParams);
303
                    }
304
                    break;
305
                case ExtraField::FIELD_TYPE_FILE:
306
                    $fileDir = $fileDirStored = '';
307
                    switch ($this->type) {
308
                        case 'course':
309
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'courses/';
310
                            $fileDirStored = "courses/";
311
                            break;
312
                        case 'session':
313
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'sessions/';
314
                            $fileDirStored = "sessions/";
315
                            break;
316
                        case 'user':
317
                            $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
0 ignored issues
show
Deprecated Code introduced by
The function UserManager::getUserPathById() has been deprecated: use Resources ( Ignorable by Annotation )

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

317
                            $fileDir = /** @scrutinizer ignore-deprecated */ UserManager::getUserPathById($params['item_id'], 'system');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
318
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
0 ignored issues
show
Deprecated Code introduced by
The function UserManager::getUserPathById() has been deprecated: use Resources ( Ignorable by Annotation )

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

318
                            $fileDirStored = /** @scrutinizer ignore-deprecated */ UserManager::getUserPathById($params['item_id'], 'last');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
319
                            break;
320
                        case 'work':
321
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
322
                            $fileDirStored = "work/";
323
                            break;
324
                        case 'scheduled_announcement':
325
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'scheduled_announcement/';
326
                            $fileDirStored = 'scheduled_announcement/';
327
                            break;
328
                    }
329
330
                    $cleanedName = api_replace_dangerous_char($value['name']);
331
                    $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
332
                    if (!file_exists($fileDir)) {
333
                        mkdir($fileDir, $dirPermissions, true);
334
                    }
335
336
                    if (!empty($value['tmp_name']) && isset($value['error']) && 0 == $value['error']) {
337
                        $cleanedName = api_replace_dangerous_char($value['name']);
338
                        $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
339
                        moveUploadedFile($value, $fileDir.$fileName);
340
341
                        $new_params = [
342
                            'item_id' => $params['item_id'],
343
                            'field_id' => $extraFieldInfo['id'],
344
                            'value' => $fileDirStored.$fileName,
345
                        ];
346
347
                        if ('session' !== $this->type && 'course' !== $this->type) {
348
                            $new_params['comment'] = $comment;
349
                        }
350
351
                        $this->save($new_params);
352
                    }
353
                    break;
354
                case ExtraField::FIELD_TYPE_CHECKBOX:
355
                    $fieldToSave = 0;
356
                    if (is_array($value)) {
357
                        if (isset($value['extra_'.$field_variable])) {
358
                            $fieldToSave = 1;
359
                        }
360
                    }
361
362
                    $newParams = [
363
                        'item_id' => $params['item_id'],
364
                        'field_id' => $extraFieldInfo['id'],
365
                        'value' => $fieldToSave,
366
                        'comment' => $comment,
367
                    ];
368
                    $this->save($newParams);
369
370
                    break;
371
                case ExtraField::FIELD_TYPE_DATE:
372
                    $d = DateTime::createFromFormat('Y-m-d', $value);
373
                    $valid = $d && $d->format('Y-m-d') === $value;
374
                    if ($valid) {
375
                        $newParams = [
376
                            'item_id' => $params['item_id'],
377
                            'field_id' => $extraFieldInfo['id'],
378
                            'value' => $value,
379
                            'comment' => $comment,
380
                        ];
381
                        $this->save($newParams, $showQuery);
382
                    }
383
                    break;
384
                case ExtraField::FIELD_TYPE_DATETIME:
385
                    $d = DateTime::createFromFormat('Y-m-d H:i', $value);
386
                    $valid = $d && $d->format('Y-m-d H:i') === $value;
387
                    if ($valid) {
388
                        $newParams = [
389
                            'item_id' => $params['item_id'],
390
                            'field_id' => $extraFieldInfo['id'],
391
                            'value' => $value,
392
                            'comment' => $comment,
393
                        ];
394
                        $this->save($newParams, $showQuery);
395
                    }
396
                    break;
397
                default:
398
                    $newParams = [
399
                        'item_id' => $params['item_id'],
400
                        'field_id' => $extraFieldInfo['id'],
401
                        'value' => $value,
402
                        'comment' => $comment,
403
                    ];
404
                    $this->save($newParams, $showQuery);
405
            }
406
        }
407
    }
408
409
    /**
410
     * Save values in the *_field_values table.
411
     *
412
     * @param array $params    Structured array with the values to save
413
     * @param bool  $showQuery Whether to show the insert query (passed to the parent save() method)
414
     *
415
     * @return mixed The result sent from the parent method
416
     * @assert (array()) === false
417
     */
418
    public function save($params, $showQuery = false)
419
    {
420
        $extra_field = $this->getExtraField();
421
422
        // Setting value to insert.
423
        $value = $params['value'];
424
        $value_to_insert = null;
425
426
        if (is_array($value)) {
427
            $value_to_insert = implode(';', $value);
428
        } else {
429
            $value_to_insert = $value;
430
        }
431
432
        $params['value'] = $value_to_insert;
433
434
        // If field id exists
435
        if (isset($params['field_id'])) {
436
            $extraFieldInfo = $extra_field->get($params['field_id']);
437
        } else {
438
            // Try the variable
439
            $extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable(
440
                $params['variable']
441
            );
442
            if ($extraFieldInfo) {
443
                $params['field_id'] = $extraFieldInfo['id'];
444
            }
445
        }
446
447
        if ($extraFieldInfo) {
448
            switch ($extraFieldInfo['field_type']) {
449
                case ExtraField::FIELD_TYPE_RADIO:
450
                case ExtraField::FIELD_TYPE_SELECT:
451
                    break;
452
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
453
                    //$field_options = $session_field_option->get_field_options_by_field($params['field_id']);
454
                    //$params['field_value'] = split(';', $value_to_insert);
455
                    /*
456
                        if ($field_options) {
457
                            $check = false;
458
                            foreach ($field_options as $option) {
459
                                if (in_array($option['option_value'], $values)) {
460
                                    $check = true;
461
                                    break;
462
                                }
463
                           }
464
                           if (!$check) {
465
                               return false; //option value not found
466
                           }
467
                       } else {
468
                           return false; //enumerated type but no option found
469
                       }*/
470
                    break;
471
                case ExtraField::FIELD_TYPE_TEXT:
472
                case ExtraField::FIELD_TYPE_TEXTAREA:
473
                    break;
474
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
475
                case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
476
                    if (is_array($value)) {
477
                        $value_to_insert = null;
478
                        if (isset($value['extra_'.$extraFieldInfo['variable']]) &&
479
                            isset($value['extra_'.$extraFieldInfo['variable'].'_second'])
480
                        ) {
481
                            $value_to_insert = $value['extra_'.$extraFieldInfo['variable']].'::'.$value['extra_'.$extraFieldInfo['variable'].'_second'];
482
                        }
483
                    }
484
                    break;
485
                default:
486
                    break;
487
            }
488
489
            if (ExtraField::FIELD_TYPE_TAG == $extraFieldInfo['field_type']) {
490
                $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

490
                /** @scrutinizer ignore-call */ 
491
                $field_values = self::getAllValuesByItemAndFieldAndValue(
Loading history...
491
                    $params['item_id'],
492
                    $params['field_id'],
493
                    $value
494
                );
495
            } else {
496
                $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

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