Passed
Push — master ( 87de88...fdfb7f )
by Andreas
11:09
created

org_openpsa_contacts_interface   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 216
Duplicated Lines 0 %

Test Coverage

Coverage 15.52%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 113
c 2
b 0
f 0
dl 0
loc 216
ccs 18
cts 116
cp 0.1552
rs 9.0399
wmc 42

8 Methods

Rating   Name   Duplication   Size   Complexity  
A _on_reindex() 0 13 1
B _update_from_hcard() 0 35 11
A _check_person_url() 0 18 4
B _get_data_from_url() 0 42 9
A check_url() 0 26 5
A find_root_group() 0 31 4
A _check_group_url() 0 14 3
A resolve_object_link() 0 11 5

How to fix   Complexity   

Complex Class

Complex classes like org_openpsa_contacts_interface often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use org_openpsa_contacts_interface, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package org.openpsa.contacts
4
 * @author Nemein Oy http://www.nemein.com/
5
 * @copyright Nemein Oy http://www.nemein.com/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
use midcom\datamanager\datamanager;
10
11
/**
12
 * OpenPSA Contact registers/user manager
13
 *
14
 * @package org.openpsa.contacts
15
 */
16
class org_openpsa_contacts_interface extends midcom_baseclasses_components_interface
17
implements midcom_services_permalinks_resolver
18
{
19
    /**
20
     * Prepares the component's indexer client
21
     */
22
    public function _on_reindex($topic, midcom_helper_configuration $config, midcom_services_indexer $indexer)
23
    {
24
        $qb_organisations = org_openpsa_contacts_group_dba::new_query_builder();
25
        $organisation_dm = datamanager::from_schemadb($config->get('schemadb_group'));
0 ignored issues
show
Bug introduced by
It seems like $config->get('schemadb_group') can also be of type false; however, parameter $path of midcom\datamanager\datamanager::from_schemadb() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

25
        $organisation_dm = datamanager::from_schemadb(/** @scrutinizer ignore-type */ $config->get('schemadb_group'));
Loading history...
26
27
        $qb_persons = org_openpsa_contacts_person_dba::new_query_builder();
28
        $person_dm = datamanager::from_schemadb($config->get('schemadb_person'));
29
30
        $indexer = new org_openpsa_contacts_midcom_indexer($topic, $indexer);
31
        $indexer->add_query('organisations', $qb_organisations, $organisation_dm);
32
        $indexer->add_query('persons', $qb_persons, $person_dm);
33
34
        return $indexer;
35
    }
36
37
    /**
38
     * Locates the root group
39
     */
40 16
    public static function find_root_group() : midcom_db_group
41
    {
42 16
        static $root_group;
43
44
        //Check if we have already initialized
45 16
        if (!empty($root_group)) {
46 15
            return $root_group;
47
        }
48
49 1
        $qb = midcom_db_group::new_query_builder();
50 1
        $qb->add_constraint('owner', '=', 0);
51 1
        $qb->add_constraint('name', '=', '__org_openpsa_contacts');
52
53 1
        if ($results = $qb->execute()) {
54
            return $root_group = end($results);
55
        }
56
57 1
        debug_add("OpenPSA Contacts root group could not be found", MIDCOM_LOG_WARN);
58
59
        //Attempt to  auto-initialize the group.
60 1
        $root_group = new midcom_db_group();
61 1
        $root_group->owner = 0;
62 1
        $root_group->name = '__org_openpsa_contacts';
63 1
        $root_group->official = midcom::get()->i18n->get_string($root_group->name, 'org.openpsa.contacts');
64 1
        midcom::get()->auth->request_sudo('org.openpsa.contacts');
65 1
        $ret = $root_group->create();
66 1
        midcom::get()->auth->drop_sudo();
67 1
        if (!$ret) {
68
            throw new midcom_error("Could not auto-initialize the module, group creation failed: " . midcom_connection::get_error_string());
69
        }
70 1
        return $root_group;
71
    }
72
73
    public function resolve_object_link(midcom_db_topic $topic, midcom_core_dbaobject $object) : ?string
74
    {
75
        if (   $object instanceof org_openpsa_contacts_group_dba
76
            || $object instanceof midcom_db_group) {
77
            return "group/{$object->guid}/";
78
        }
79
        if (   $object instanceof org_openpsa_contacts_person_dba
80
            || $object instanceof midcom_db_person) {
81
            return "person/{$object->guid}/";
82
        }
83
        return null;
84
    }
85
86
    private function _get_data_from_url(string $url) : array
87
    {
88
        $data = [];
89
90
        // TODO: Error handling
91
        $client = new org_openpsa_httplib();
92
        $html = $client->get($url);
93
94
        // Check for ICBM coordinate information
95
        if ($icbm = org_openpsa_httplib_helpers::get_meta_value($html, 'icbm')) {
96
            $data['icbm'] = $icbm;
97
        }
98
99
        // Check for RSS feed
100
        if ($rss_url = org_openpsa_httplib_helpers::get_link_values($html, 'alternate')) {
101
            $data['rss_url'] = $rss_url[0]['href'];
102
103
            // We have a feed URL, but we should check if it is GeoRSS as well
104
            $items = net_nemein_rss_fetch::raw_fetch($data['rss_url'])->get_items();
105
106
            if (   !empty($items)
107
                && (   $items[0]->get_latitude()
108
                    || $items[0]->get_longitude())) {
109
                // This is a GeoRSS feed
110
                $data['georss_url'] = $data['rss_url'];
111
            }
112
        }
113
114
        $microformats = Mf2\parse($html);
115
        $hcards = [];
116
        foreach ($microformats['items'] as $item) {
117
            if (in_array('h-card', $item['type'])) {
118
                $hcards[] = $item['properties'];
119
            }
120
        }
121
122
        if (!empty($hcards)) {
123
            // We have found hCard data here
124
            $data['hcards'] = $hcards;
125
        }
126
127
        return $data;
128
    }
129
130
    /**
131
     * AT handler for fetching Semantic Web data for person or group
132
     */
133
    public function check_url(array $args, midcom_baseclasses_components_cron_handler $handler) : bool
134
    {
135
        if (array_key_exists('person', $args)) {
136
            $type = 'person';
137
        } elseif (array_key_exists('group', $args)) {
138
            $type = 'group';
139
        } else {
140
            $handler->print_error('Person or Group GUID not set, aborting');
141
            return false;
142
        }
143
144
        $classname = 'org_openpsa_contacts_' . $type . '_dba';
145
        $method = '_check_' . $type . '_url';
146
        $guid = $args[$type];
147
148
        try {
149
            $object = new $classname($guid);
150
        } catch (midcom_error $e) {
151
            $handler->print_error($type . " {$guid} not found, error " . $e->getMessage());
152
            return false;
153
        }
154
        if (!$object->homepage) {
155
            $handler->print_error($type . " {$object->guid} has no homepage, skipping");
156
            return false;
157
        }
158
        return $this->$method($object);
159
    }
160
161
    private function _check_group_url(org_openpsa_contacts_group_dba $group) : bool
162
    {
163
        $data = $this->_get_data_from_url($group->homepage);
164
165
        // TODO: We can use a lot of other data too
166
        if (array_key_exists('hcards', $data)) {
167
            // Process those hCard values that are interesting for us
168
            foreach ($data['hcards'] as $hcard) {
169
                $this->_update_from_hcard($group, $hcard);
170
            }
171
172
            $group->update();
173
        }
174
        return true;
175
    }
176
177
    private function _check_person_url(org_openpsa_contacts_person_dba $person) : bool
178
    {
179
        $data = $this->_get_data_from_url($person->homepage);
180
181
        if (array_key_exists('rss_url', $data)) {
182
            // Instead of using the ICBM position data directly we can subscribe to it so we get modifications too
183
            $person->set_parameter('net.nemein.rss', 'url', $data['rss_url']);
184
        }
185
186
        if (array_key_exists('hcards', $data)) {
187
            // Process those hCard values that are interesting for us
188
            foreach ($data['hcards'] as $hcard) {
189
                $this->_update_from_hcard($person, $hcard);
190
            }
191
192
            $person->update();
193
        }
194
        return true;
195
    }
196
197
    private function _update_from_hcard(midcom_core_dbaobject $object, array $hcard)
198
    {
199
        foreach ($hcard as $key => $val) {
200
            switch ($key) {
201
                case 'email':
202
                    $object->email = reset($val);
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
203
                    break;
204
205
                case 'tel':
206
                    $object->workphone = reset($val);
0 ignored issues
show
Bug Best Practice introduced by
The property workphone does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
207
                    break;
208
209
                case 'note':
210
                    $object->extra = reset($val);
0 ignored issues
show
Bug Best Practice introduced by
The property extra does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
211
                    break;
212
213
                case 'photo':
214
                    // TODO: Importing the photo would be cool
215
                    break;
216
217
                case 'adr':
218
                    $adr = reset($val);
219
                    if (array_key_exists('street-address', $adr['properties'])) {
220
                        $object->street = reset($adr['properties']['street-address']);
0 ignored issues
show
Bug Best Practice introduced by
The property street does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
221
                    }
222
                    if (array_key_exists('postal-code', $adr['properties'])) {
223
                        $object->postcode = reset($adr['properties']['postal-code']);
0 ignored issues
show
Bug Best Practice introduced by
The property postcode does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
224
                    }
225
                    if (array_key_exists('locality', $adr['properties'])) {
226
                        $object->city = reset($adr['properties']['locality']);
0 ignored issues
show
Bug Best Practice introduced by
The property city does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
227
                    }
228
                    if (array_key_exists('country-name', $adr['properties'])) {
229
                        $object->country = reset($adr['properties']['country-name']);
0 ignored issues
show
Bug Best Practice introduced by
The property country does not exist on midcom_core_dbaobject. Since you implemented __set, consider adding a @property annotation.
Loading history...
230
                    }
231
                    break;
232
            }
233
        }
234
    }
235
}
236