Completed
Push — master ( 7668ba...b7b643 )
by Andreas
08:40
created

org_openpsa_contacts_interface   F

Complexity

Total Complexity 51

Size/Duplication

Total Lines 314
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 20

Importance

Changes 0
Metric Value
dl 0
loc 314
rs 3.7763
c 0
b 0
f 0
wmc 51
lcom 1
cbo 20

8 Methods

Rating   Name   Duplication   Size   Complexity  
A _on_reindex() 0 15 1
B find_root_group() 0 44 5
B resolve_object_link() 0 14 5
B _get_data_from_url() 0 55 9
C check_url() 0 43 7
C _check_group_url() 0 41 7
B _check_person_url() 0 34 6
C _update_from_hcard() 0 44 11

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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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
/**
10
 * OpenPSA Contact registers/user manager
11
 *
12
 *
13
 * @package org.openpsa.contacts
14
 */
15
class org_openpsa_contacts_interface extends midcom_baseclasses_components_interface
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
16
implements midcom_services_permalinks_resolver
1 ignored issue
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
17
{
18
    /**
19
     * Prepares the component's indexer client
20
     */
21
    public function _on_reindex($topic, $config, &$indexer)
22
    {
23
        $qb_organisations = org_openpsa_contacts_group_dba::new_query_builder();
24
        $qb_organisations->add_constraint('orgOpenpsaObtype', '<>', org_openpsa_contacts_group_dba::MYCONTACTS);
25
        $organisation_schema = midcom_helper_datamanager2_schema::load_database($config->get('schemadb_group'));
26
27
        $qb_persons = org_openpsa_contacts_person_dba::new_query_builder();
28
        $person_schema = midcom_helper_datamanager2_schema::load_database($config->get('schemadb_person'));
29
30
        $indexer = new org_openpsa_contacts_midcom_indexer($topic, $indexer);
31
        $indexer->add_query('organisations', $qb_organisations, $organisation_schema);
32
        $indexer->add_query('persons', $qb_persons, $person_schema);
33
34
        return $indexer;
35
    }
36
37
    /**
38
     * Locates the root group
39
     */
40
    static function find_root_group($name = '__org_openpsa_contacts')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
41
    {
42
        static $root_groups = array();
43
44
        //Check if we have already initialized
45
        if (!empty($root_groups[$name]))
46
        {
47
            return $root_groups[$name];
48
        }
49
50
        $qb = midcom_db_group::new_query_builder();
51
        $qb->add_constraint('owner', '=', 0);
52
        $qb->add_constraint('name', '=', $name);
53
54
        $results = $qb->execute();
55
56
        if (!empty($results))
57
        {
58
            foreach ($results as $group)
59
            {
60
                $root_groups[$name] = $group;
61
            }
62
        }
63
        else
64
        {
65
            debug_add("OpenPSA Contacts root group could not be found", MIDCOM_LOG_WARN);
66
67
            //Attempt to  auto-initialize the group.
68
            midcom::get()->auth->request_sudo('org.openpsa.contacts');
69
            $grp = new midcom_db_group();
70
            $grp->owner = 0;
71
            $grp->name = $name;
72
            $grp->official = midcom::get()->i18n->get_l10n('org.openpsa.contacts')->get($name);
73
            $ret = $grp->create();
74
            midcom::get()->auth->drop_sudo();
75
            if (!$ret)
76
            {
77
                throw new midcom_error("Could not auto-initialize the module, group creation failed: " . midcom_connection::get_error_string());
78
            }
79
            $root_groups[$name] = $grp;
80
        }
81
82
        return $root_groups[$name];
83
    }
84
85
    public function resolve_object_link(midcom_db_topic $topic, midcom_core_dbaobject $object)
86
    {
87
        if (   $object instanceof org_openpsa_contacts_group_dba
88
            || $object instanceof midcom_db_group)
89
        {
90
            return "group/{$object->guid}/";
91
        }
92
        if (   $object instanceof org_openpsa_contacts_person_dba
93
            || $object instanceof midcom_db_person)
94
        {
95
            return "person/{$object->guid}/";
96
        }
97
        return null;
98
    }
99
100
    private function _get_data_from_url($url)
101
    {
102
        //We have to hang on to the hKit object, because its configuration is done by require_once
103
        //and will thus only work for the first instantiation...
104
        static $hkit;
105
        if (is_null($hkit))
106
        {
107
            require_once MIDCOM_ROOT . '/external/hkit.php';
108
            $hkit = new hKit();
109
        }
110
        $data = array();
111
112
        // TODO: Error handling
113
        $client = new org_openpsa_httplib();
114
        $html = $client->get($url);
115
116
        // Check for ICBM coordinate information
117
        $icbm = org_openpsa_httplib_helpers::get_meta_value($html, 'icbm');
118
        if ($icbm)
119
        {
120
            $data['icbm'] = $icbm;
121
        }
122
123
        // Check for RSS feed
124
        $rss_url = org_openpsa_httplib_helpers::get_link_values($html, 'alternate');
125
126
        if (!empty($rss_url))
127
        {
128
            $data['rss_url'] = $rss_url[0]['href'];
129
130
            // We have a feed URL, but we should check if it is GeoRSS as well
131
            $items = net_nemein_rss_fetch::raw_fetch($data['rss_url'])->get_items();
132
133
            if (count($items) > 0)
134
            {
135
                if (   $items[0]->get_latitude()
136
                    || $items[0]->get_longitude())
137
                {
138
                    // This is a GeoRSS feed
139
                    $data['georss_url'] = $data['rss_url'];
140
                }
141
            }
142
        }
143
144
        $hcards = @$hkit->getByURL('hcard', $url);
145
146
        if (   is_array($hcards)
147
            && count($hcards) > 0)
148
        {
149
            // We have found hCard data here
150
            $data['hcards'] = $hcards;
151
        }
152
153
        return $data;
154
    }
155
156
    /**
157
     * AT handler for fetching Semantic Web data for person or group
158
     *
159
     * @param array $args handler arguments
160
     * @param midcom_baseclasses_components_cron_handler $handler The cron_handler object calling this method.
161
     * @return boolean indicating success/failure
162
     */
163
    public function check_url(array $args, midcom_baseclasses_components_cron_handler $handler)
164
    {
165
        if (array_key_exists('person', $args))
166
        {
167
            // Handling for persons
168
            try
169
            {
170
                $person = new org_openpsa_contacts_person_dba($args['person']);
171
            }
172
            catch (midcom_error $e)
173
            {
174
                $handler->print_error("Person {$args['person']} not found, error " . $e->getMessage());
175
                return false;
176
            }
177
            if (!$person->homepage)
178
            {
179
                $handler->print_error("Person {$person->guid} has no homepage, skipping");
180
                return false;
181
            }
182
            return $this->_check_person_url($person);
183
        }
184
        else if (array_key_exists('group', $args))
185
        {
186
            // Handling for groups
187
            try
188
            {
189
                $group = new org_openpsa_contacts_group_dba($args['group']);
190
            }
191
            catch (midcom_error $e)
192
            {
193
                $handler->print_error("Group {$args['group']} not found, error " . $e->getMessage());
194
                return false;
195
            }
196
            if (!$group->homepage)
197
            {
198
                $handler->print_error("Group {$group->guid} has no homepage, skipping");
199
                return false;
200
            }
201
            return $this->_check_group_url($group);
202
        }
203
        $handler->print_error('Person or Group GUID not set, aborting');
204
        return false;
205
    }
206
207
    private function _check_group_url(org_openpsa_contacts_group_dba $group)
208
    {
209
        $data = org_openpsa_contacts_interface::_get_data_from_url($group->homepage);
210
211
        // Use the data we got
212
        if (array_key_exists('icbm', $data))
213
        {
214
            // We know where the group is located
215
            $icbm_parts = explode(',', $data['icbm']);
216
            if (count($icbm_parts) == 2)
217
            {
218
                $latitude = (float) $icbm_parts[0];
219
                $longitude = (float) $icbm_parts[1];
220
                if (   abs($latitude) < 90
221
                    && abs($longitude) < 180)
222
                {
223
                    $location = new org_routamc_positioning_location_dba();
224
                    $location->date = time();
225
                    $location->latitude = $latitude;
226
                    $location->longitude = $longitude;
227
                    $location->relation = org_routamc_positioning_location_dba::RELATION_LOCATED;
228
                    $location->parent = $group->guid;
229
                    $location->parentclass = 'org_openpsa_contacts_group_dba';
230
                    $location->parentcomponent = 'org.openpsa.contacts';
231
                    $location->create();
232
                }
233
            }
234
        }
235
        // TODO: We can use a lot of other data too
236
        if (array_key_exists('hcards', $data))
237
        {
238
            // Process those hCard values that are interesting for us
239
            foreach ($data['hcards'] as $hcard)
240
            {
241
                $group = $this->_update_from_hcard($group, $hcard);
242
            }
243
244
            $group->update();
245
        }
246
        return true;
247
    }
248
249
    private function _check_person_url(org_openpsa_contacts_person_dba $person)
250
    {
251
        $data = org_openpsa_contacts_interface::_get_data_from_url($person->homepage);
252
253
        // Use the data we got
254
        if (array_key_exists('georss_url', $data))
255
        {
256
            // GeoRSS subscription is a good way to keep track of person's location
257
            $person->set_parameter('org.routamc.positioning:georss', 'georss_url', $data['georss_url']);
258
        }
259
        else if (array_key_exists('icbm', $data))
260
        {
261
            // Instead of using the ICBM position data directly we can subscribe to it so we get modifications too
262
            $person->set_parameter('org.routamc.positioning:html', 'icbm_url', $person->homepage);
263
        }
264
265
        if (array_key_exists('rss_url', $data))
266
        {
267
            // Instead of using the ICBM position data directly we can subscribe to it so we get modifications too
268
            $person->set_parameter('net.nemein.rss', 'url', $data['rss_url']);
269
        }
270
271
        if (array_key_exists('hcards', $data))
272
        {
273
            // Process those hCard values that are interesting for us
274
            foreach ($data['hcards'] as $hcard)
275
            {
276
                $person = $this->_update_from_hcard($person, $hcard);
277
            }
278
279
            $person->update();
280
        }
281
        return true;
282
    }
283
284
    private function _update_from_hcard($object, $hcard)
285
    {
286
        foreach ($hcard as $key => $val)
287
        {
288
            switch ($key)
289
            {
290
                case 'email':
291
                    $object->email = $val;
292
                    break;
293
294
                case 'tel':
295
                    $object->workphone = $val;
296
                    break;
297
298
                case 'note':
299
                    $object->extra = $val;
300
                    break;
301
302
                case 'photo':
303
                    // TODO: Importing the photo would be cool
304
                    break;
305
306
                case 'adr':
307
                    if (array_key_exists('street-address', $val))
308
                    {
309
                        $object->street = $val['street-address'];
310
                    }
311
                    if (array_key_exists('postal-code', $val))
312
                    {
313
                        $object->postcode = $val['postal-code'];
314
                    }
315
                    if (array_key_exists('locality', $val))
316
                    {
317
                        $object->city = $val['locality'];
318
                    }
319
                    if (array_key_exists('country-name', $val))
320
                    {
321
                        $object->country = $val['country-name'];
322
                    }
323
                    break;
324
            }
325
        }
326
        return $object;
327
    }
328
}
329