Completed
Push — master ( 160801...bd59d4 )
by Andreas
27:08
created

mnrelation::save()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.128

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 6
nop 0
dl 0
loc 14
ccs 8
cts 10
cp 0.8
crap 4.128
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright CONTENT CONTROL GmbH, http://www.contentcontrol-berlin.de
4
 */
5
6
namespace midcom\datamanager\storage;
7
8
use midcom;
9
use midcom_error;
10
use midcom_connection;
11
12
/**
13
 * Experimental storage class
14
 */
15
class mnrelation extends delayed
16
{
17 40
    public function __construct($object, $config)
18
    {
19 40
        parent::__construct($object, $config);
20
        $defaults = [
21 40
            'sortable' => false,
22
            'allow_multiple' => true,
23
            'mapping_class_name' => null,
24
            'master_fieldname' => null,
25
            'member_fieldname' => null,
26
            'master_is_id' => false,
27
            'constraints' => [],
28
            'require_corresponding_option' => false,
29
            'sortable_sort_order' => 'DESC',
30
            'additional_fields' => [],
31
        ];
32 40
        $this->config['type_config'] = array_merge($defaults, $this->config['type_config']);
33 40
    }
34
35
    /**
36
     * {@inheritdoc}
37
     */
38 7
    public function save()
39
    {
40 7
        $selection = array_flip((array) $this->value);
41 7
        $existing = $this->load_objects();
42 7
        $new = array_diff_key($selection, $existing);
43 7
        $delete = array_diff_key($existing, $selection);
44
45 7
        foreach (array_keys($new) as $member_key) {
46 2
            $this->create_relation($member_key);
47
        }
48
49 7
        foreach ($delete as $key => $member) {
50
            if (!$member->delete()) {
51
                throw new midcom_error("Failed to delete member record for key {$key}: " . midcom_connection::get_error_string());
52
            }
53
        }
54 7
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 38
    public function load()
60
    {
61 38
        if (!$this->get_master_foreign_key()) {
62 16
            return $this->config['type_config']['allow_multiple'] ? [] : null;
63
        }
64 22
        if ($this->config['type_config']['allow_multiple']) {
65 22
            return array_keys($this->load_objects());
66
        }
67
        return key($this->load_objects());
68
    }
69
70 2
    private function create_relation($member_key)
71
    {
72 2
        $member = new $this->config['type_config']['mapping_class_name']();
73 2
        $member->{$this->config['type_config']['master_fieldname']} = $this->get_master_foreign_key();
74 2
        $member->{$this->config['type_config']['member_fieldname']} = $member_key;
75
76 2
        foreach ($this->config['type_config']['additional_fields'] as $fieldname => $value) {
77
            // Determine what to do if using dot (.) in the additional fields,
78 1
            if (preg_match('/^(.+)\.(.+)$/', $fieldname, $regs)) {
79
                $domain = $regs[1];
80
                $key = $regs[2];
81
82
                // Determine what should be done with conjunction
83
                switch ($domain) {
84
                    case 'metadata':
85
                        $member->metadata->$key = $value;
86
                        break;
87
88
                    case 'parameter':
89
                        $member->set_parameter('midcom.helper.datamanager2.mnrelation', $key, $value);
90
                        break;
91
                }
92
93
                continue;
94
            }
95
96 1
            $member->{$fieldname} = $value;
97
        }
98
99 2
        if (!$member->create()) {
100
            throw new midcom_error("Failed to create a new member record for key {$member_key}: " . midcom_connection::get_error_string());
101
        }
102 2
    }
103
104 25
    private function load_objects() : array
105
    {
106 25
        $qb = midcom::get()->dbfactory->new_query_builder($this->config['type_config']['mapping_class_name']);
107 25
        $qb->add_constraint($this->config['type_config']['master_fieldname'], '=', $this->get_master_foreign_key());
108
109 25
        if (   $this->config['type_config']['sortable']
110 25
            && preg_match('/^(ASC|DESC)/i', $this->config['type_config']['sortable_sort_order'], $regs)) {
111
            $order = strtoupper($regs[1]);
112
            $qb->add_order('metadata.score', $order);
113
        }
114
115 25
        foreach ($this->config['type_config']['constraints'] as $constraint) {
116 9
            $qb->add_constraint($this->config['type_config']['member_fieldname'] . '.' . $constraint['field'], $constraint['op'], $constraint['value']);
117
        }
118
119 25
        foreach ($this->config['type_config']['additional_fields'] as $fieldname => $value) {
120 8
            $qb->add_constraint($fieldname, '=', $value);
121
        }
122
123 25
        $indexed = [];
124 25
        $results = $qb->execute();
125 25
        foreach ($results as $result) {
126
            $indexed[$result->{$this->config['type_config']['member_fieldname']}] = $result;
127
        }
128 25
        return $indexed;
129
    }
130
131
    /**
132
     * Returns the foreign key of the master object. This is either the ID or the GUID of
133
     * the master object, depending on the $master_is_id member.
134
     *
135
     * @var string Foreign key for the master field in the mapping table.
136
     */
137 38
    private function get_master_foreign_key()
138
    {
139 38
        if ($this->config['type_config']['master_is_id']) {
140 32
            return $this->object->id;
141
        }
142 6
        return $this->object->guid;
143
    }
144
}
145