Completed
Branch feature/pre-split (4c50c1)
by Anton
03:17
created

DuplicateTrait::duplicateCriteria()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 4
nop 1
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Entities\Nodes\Traits;
8
9
/**
10
 * Trait provides ability for Node to ensure that given data is unique in selection.
11
 */
12
trait DuplicateTrait
13
{
14
    /**
15
     * @invisible
16
     * @var array
17
     */
18
    private $duplicateCriteria = [];
19
20
    /**
21
     * Aggregated duplicate data.
22
     *
23
     * @invisible
24
     * @var array
25
     */
26
    private $duplicates = [];
27
28
    /**
29
     * In many cases (for example if you have inload of HAS_MANY relation) record data can be
30
     * replicated by many result rows (duplicated). To prevent wrong data linking we have to
31
     * deduplicate such records. This is only internal loader functionality and required due data
32
     * tree are built using php references.
33
     *
34
     * Method will return true if data is unique handled before and false in opposite case.
35
     * Provided data array will be automatically linked with it's unique state using references.
36
     *
37
     * @param array $data Reference to parsed record data, reference will be pointed to valid and
38
     *                    existed data segment if such data was already parsed.
39
     *
40
     * @return bool
41
     */
42
    protected function deduplicate(array &$data): bool
43
    {
44
        $criteria = $this->duplicateCriteria($data);
45
46
        if (isset($this->duplicates[$criteria])) {
47
            //Duplicate is presented, let's reduplicate
48
            $data = $this->duplicates[$criteria];
49
50
            //Duplicate is presented
51
            return false;
52
        }
53
54
        //Remember record to prevent future duplicates
55
        $this->duplicates[$criteria] = &$data;
56
57
        return true;
58
    }
59
60
    /**
61
     * Calculate duplication criteria.
62
     *
63
     * @param array $data
64
     *
65
     * @return mixed
66
     */
67
    private function duplicateCriteria(array &$data)
68
    {
69
        if (empty($this->duplicateCriteria)) {
70
            //It is recommended to use primary keys in every record as it will speed up de-duplication.
71
            $criteria = serialize($data);
72
73
            return $criteria;
74
        } elseif (count($this->duplicateCriteria) == 1) {
75
            $criteria = $data[$this->duplicateCriteria[0]];
76
77
            return $criteria;
78
        } else {
79
            $criteria = [];
80
            foreach ($this->duplicateCriteria as $column) {
81
                $criteria[] = $data[$column];
82
            }
83
84
            $criteria = join('.', $criteria);
85
86
            return $criteria;
87
        }
88
    }
89
}