Entity::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 5
rs 10
1
<?php
2
/**
3
 * This script demonstrates how to keep entities in sync.
4
 * Entities must have unique id, and the source and target must be ordered by this id.
5
 *
6
 * If entity is added into source then add callback is called
7
 * If entity has been removed from source then remove callback is called
8
 * If there is a change in entity data, then add and remove callbacks are called.
9
 *
10
 * It is not guaranteed that on update the remove callback is called before the add callback.
11
 * The calling order depends on stringified source and target element comparison result.
12
 *
13
 * If it is important that on update the remove callback is called before the add callback
14
 * (for example the id field index has unique constraints) then you have several options.
15
 *
16
 * One way is to gather all removals and additions into memory and process them later.
17
 * This way you can detect if you need to insert, delete or update.
18
 *
19
 * Second one is to make add and remove callbacks more clever.
20
 *
21
 * Third one is to add last update date after the id in `__toString` method. But if you
22
 * have already timestamp then you probably can use some better algorithm which does
23
 * not require querying whole dataset ;)
24
 *
25
 * NB! Pay attention to the id in  `__toString` method. The id is normalized so
26
 * the stringified entities are ordered the same way as if they were
27
 * ordered just by id.
28
 */
29
30
require_once __DIR__ . '/../vendor/autoload.php';
31
32
require_once __DIR__ . '/../tests/Stringable.php'; // polyfill for PHP 7
33
34
/**
35
 * An instance representing entity.
36
 * This is what source and target iterator must return
37
 * and add and remove callback will have as input.
38
 */
39
class Entity implements Stringable
40
{
41
    public int $id;
42
    public string $name;
43
    public string $email;
44
45
    /**
46
     * @return string returns entity representation usable in strcmp function to compare with other entities.
47
     */
48
    public function __toString(): string
49
    {
50
        // NB! NB! NB! The id must be in equal length! This way it is avoided
51
        // that the lists order and entity order are not matching.
52
        // For example, let's have two entities: id=1,name=B and id=10,name=A.
53
        // After stringifing them we get "1B" and "10A".
54
        // The next expression is valid  and "10A" < "1B".
55
        // But in iterator the 1 is before 10 and therefore the B is before the A.
56
        $normalizedId = str_pad(strval($this->id), 5, "0", STR_PAD_RIGHT);
57
        return $normalizedId
58
            . $this->name
59
            . $this->email;
60
    }
61
62
    public function __construct(int $id, string $name, string $email)
63
    {
64
        $this->id = $id;
65
        $this->name = $name;
66
        $this->email = $email;
67
    }
68
}
69
70
$synchronization = new \Raigu\OrderedListsSynchronization\Synchronization();
71
$synchronization(
72
    $source = new ArrayIterator([
73
        new Entity(1, 'John Doe', '[email protected]'),
74
        new Entity(2, 'Jane Doe', '[email protected]'),
75
    ]),
76
    $source = new ArrayIterator([
77
        new Entity(1, 'John Doe', '[email protected]'),
78
        new Entity(2, 'Jane Doe', '[email protected]'),
79
    ]),
80
    $add = function (Entity $element) {
81
        echo "ADD: {$element->id} {$element->name} {$element->email}" . PHP_EOL;
82
    },
83
    $remove = function (Entity $element) {
84
        echo "REMOVE: {$element->id} {$element->name} {$element->email}" . PHP_EOL;
85
    }
86
);
87