Passed
Push — master ( f6b156...dcf7e9 )
by Andreas
32:47 queued 15:02
created

org_openpsa_widgets_contact::read_object()   B

Complexity

Conditions 10
Paths 36

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 13.7025

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 18
c 1
b 0
f 0
nc 36
nop 1
dl 0
loc 29
ccs 12
cts 18
cp 0.6667
crap 13.7025
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Class for rendering person records
4
 *
5
 * Uses the hCard microformat for output.
6
 *
7
 * @author Henri Bergius, http://bergie.iki.fi
8
 * @copyright Nemein Oy, http://www.nemein.com
9
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
10
 * @link http://www.microformats.org/wiki/hcard hCard microformat documentation
11
 * @package org.openpsa.widgets
12
 */
13
14
use midcom\datamanager\storage\blobs;
15
16
/**
17
 * @package org.openpsa.widgets
18
 */
19
class org_openpsa_widgets_contact extends midcom_baseclasses_components_purecode
20
{
21
    /**
22
     * Do we have our contact data ?
23
     */
24
    private $_data_read_ok = false;
25
26
    /**
27
     * Contact information of the person being displayed
28
     */
29
    public $contact_details = [
30
        'guid' => '',
31
        'id' => '',
32
        'firstname' => '',
33
        'lastname' => ''
34
    ];
35
36
    /**
37
     * Optional URI to person details
38
     *
39
     * @var string
40
     */
41
    public $link;
42
43
    /**
44
     * Optional HTML to be placed into the card
45
     *
46
     * @var string
47
     */
48
    public $extra_html;
49
50
    /**
51
     * Optional HTML to be placed into the card (before any other output in the DIV)
52
     *
53
     * @var string
54
     */
55
    public $prefix_html;
56
57
    /**
58
     * Whether to show person's groups in a list
59
     *
60
     * @var boolean
61
     */
62
    public $show_groups = true;
63
64
    /**
65
     * Whether to generate links to the groups using NAP
66
     *
67
     * @var boolean
68
     */
69
    var $link_contacts = true;
70
71
    /**
72
     * Default org.openpsa.contacts URL to be used for linking to groups. Will be autoprobed if not supplied.
73
     *
74
     * @var string
75
     */
76
    private static $_contacts_url;
77
78
    private $person;
79
80
    /**
81
     * Initializes the class and stores the selected person to be shown
82
     */
83 8
    public function __construct(midcom_db_person $person = null)
84
    {
85 8
        parent::__construct();
86
87 8
        if (null === self::$_contacts_url) {
0 ignored issues
show
introduced by
The condition null === self::_contacts_url is always false.
Loading history...
88 1
            $siteconfig = org_openpsa_core_siteconfig::get_instance();
89 1
            self::$_contacts_url = $siteconfig->get_node_full_url('org.openpsa.contacts');
90
        }
91
92
        // Read properties of provided person object
93
        // TODO: Handle groups as well
94 8
        if ($person) {
95 7
            $this->person = $person;
96 7
            $this->_data_read_ok = $this->read_object($person);
97
        }
98 8
    }
99
100 1
    public static function add_head_elements()
101
    {
102 1
        static $added = false;
103 1
        if (!$added) {
104 1
            midcom::get()->head->add_stylesheet(MIDCOM_STATIC_URL . "/org.openpsa.widgets/hcard.css");
105 1
            midcom::get()->head->add_stylesheet(MIDCOM_STATIC_URL . '/stock-icons/font-awesome-4.7.0/css/font-awesome.min.css');
106 1
            $added = true;
107
        }
108 1
    }
109
110
    /**
111
     * Retrieve an object, uses in-request caching
112
     *
113
     * @param mixed $src GUID of object (ids work but are discouraged)
114
     */
115 10
    public static function get($src) : self
116
    {
117 10
        static $cache = [];
118
119 10
        if (isset($cache[$src])) {
120 4
            return $cache[$src];
121
        }
122
123
        try {
124 7
            $person = midcom_db_person::get_cached($src);
125 1
        } catch (midcom_error $e) {
126 1
            $widget = new self();
127 1
            $cache[$src] = $widget;
128 1
            return $widget;
129
        }
130
131 6
        $widget = new self($person);
132
133 6
        $cache[$person->guid] = $widget;
134 6
        $cache[$person->id] = $cache[$person->guid];
135 6
        return $cache[$person->guid];
136
    }
137
138
    /**
139
     * Read properties of a person object and populate local fields accordingly
140
     */
141 7
    private function read_object(midcom_db_person $person)
142
    {
143
        // Database identifiers
144 7
        $this->contact_details['guid'] = $person->guid;
145 7
        $this->contact_details['id'] = $person->id;
146
147 7
        if ($person->guid == "") {
148
            $this->contact_details['lastname'] = $this->_l10n->get('no person');
149 7
        } elseif ($person->firstname == '' && $person->lastname == '') {
150 7
            $this->contact_details['lastname'] = "Person #{$person->id}";
151
        } else {
152
            $this->contact_details['firstname'] = $person->firstname;
153
            $this->contact_details['lastname'] = $person->lastname;
154
        }
155
156 7
        foreach (['handphone', 'workphone', 'homephone', 'email', 'homepage'] as $property) {
157 7
            if ($person->$property) {
158
                $this->contact_details[$property] = $person->$property;
159
            }
160
        }
161
162 7
        if (   $this->_config->get('jabber_enable_presence')
163 7
            && $person->get_parameter('org.openpsa.jabber', 'jid')) {
164
            $this->contact_details['jid'] = $person->get_parameter('org.openpsa.jabber', 'jid');
165
        }
166
167 7
        if (   $this->_config->get('skype_enable_presence')
168 7
            && $person->get_parameter('org.openpsa.skype', 'name')) {
169
            $this->contact_details['skype'] = $person->get_parameter('org.openpsa.skype', 'name');
170
        }
171 7
    }
172
173
    private function _render_name(string $fallback_image) : string
174
    {
175
        $name = "<span class=\"given-name\">{$this->contact_details['firstname']}</span> <span class=\"family-name\">{$this->contact_details['lastname']}</span>";
176
177
        $url = false;
178
179
        if ($this->link) {
180
            $url = $this->link;
181
        } elseif ($this->link_contacts && !empty($this->contact_details['guid'])) {
182
            if (!self::$_contacts_url) {
183
                $this->link_contacts = false;
184
            } else {
185
                $url = self::$_contacts_url . 'person/' . $this->contact_details['guid'] . '/';
186
            }
187
        }
188
189
        $name = $this->get_image('thumbnail', $fallback_image) . $name;
190
191
        if ($url) {
192
            $name = '<a href="' . $url . '">' . $name . '</a>';
193
        }
194
195
        return $name;
196
    }
197
198 1
    public function get_image(string $type, string $fallback) : string
199
    {
200 1
        $attachments = blobs::get_attachments($this->person, 'photo');
201 1
        if (!empty($attachments[$type])) {
202
            return '<img class="photo" src="' . midcom_db_attachment::get_url($attachments[$type]) . '">';
203
        }
204 1
        if (   $this->_config->get('gravatar_enable')
205 1
            && !empty($this->contact_details['email'])) {
206
            $size = ($type == 'view') ? 500 : 32;
207
            $gravatar_url = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->contact_details['email']))) . "?s=" . $size . '&d=identicon';
208
            return "<img src=\"{$gravatar_url}\" class=\"photo\" />\n";
209
        }
210 1
        return '<i class="fa fa-' . $fallback . '"></i>';
211
    }
212
213
    /**
214
     * Show selected person object inline. Outputs hCard XHTML.
215
     */
216 9
    public function show_inline() : string
217
    {
218 9
        if (!$this->_data_read_ok) {
219 9
            return '';
220
        }
221
        self::add_head_elements();
222
        $inline_string = '';
223
224
        // Start the vCard
225
        $inline_string .= "<span class=\"vcard\">";
226
227
        if (!empty($this->contact_details['guid'])) {
228
            // Identifier
229
            $inline_string .= "<span class=\"uid\" style=\"display: none;\">{$this->contact_details['guid']}</span>";
230
        }
231
232
        // The name sequence
233
        $inline_string .= "<span class=\"n\">";
234
        $inline_string .= $this->_render_name('address-card-o');
235
        $inline_string .= "</span>";
236
237
        $inline_string .= "</span>";
238
239
        return $inline_string;
240
    }
241
242
    /**
243
     * Show the selected person. Outputs hCard XHTML.
244
     */
245 2
    public function show()
246
    {
247 2
        if (!$this->_data_read_ok) {
248 2
            return false;
249
        }
250
        self::add_head_elements();
251
        // Start the vCard
252
        echo "<div class=\"vcard\" id=\"org_openpsa_widgets_contact-{$this->contact_details['guid']}\">\n";
253
        if ($this->prefix_html) {
254
            echo $this->prefix_html;
255
        }
256
257
        if (!empty($this->contact_details['guid'])) {
258
            // Identifier
259
            echo "<span class=\"uid\" style=\"display: none;\">{$this->contact_details['guid']}</span>";
260
        }
261
262
        // The Name sequence
263
        echo "<div class=\"n\">\n";
264
        echo $this->_render_name('user-o');
265
        echo "</div>\n";
266
267
        // Contact information sequence
268
        echo "<ul class=\"contact_information\">\n";
269
        if ($this->extra_html) {
270
            echo $this->extra_html;
271
        }
272
273
        $this->_show_groups();
274
275
        $this->_show_phone_number('handphone', 'mobile');
276
        $this->_show_phone_number('workphone', 'phone');
277
        $this->_show_phone_number('homephone', 'home');
278
279
        if (!empty($this->contact_details['email'])) {
280
            echo "<li><a title=\"{$this->contact_details['email']}\" href=\"mailto:{$this->contact_details['email']}\"><i class=\"fa fa-envelope-o\"></i>{$this->contact_details['email']}</a></li>\n";
281
        }
282
283
        if (!empty($this->contact_details['skype'])) {
284
            echo "<li>";
285
            echo "<a href=\"skype:{$this->contact_details['skype']}?call\"><i class=\"fa fa-skype\"></i>{$this->contact_details['skype']}</a></li>\n";
286
        }
287
288
        // Instant messaging contact information
289
        if (!empty($this->contact_details['jid'])) {
290
            echo "<li>";
291
            echo "<a href=\"xmpp:{$this->contact_details['jid']}\"";
292
            $edgar_url = $this->_config->get('jabber_edgar_url');
293
            if (!empty($edgar_url)) {
294
                echo " style=\"background-repeat: no-repeat;background-image: url('{$edgar_url}?jid={$this->contact_details['jid']}&type=image');\"";
295
            }
296
            echo "><i class=\"fa fa-comment-o\"></i>{$this->contact_details['jid']}</a></li>\n";
297
        }
298
299
        if (!empty($this->contact_details['homepage'])) {
300
            echo "<li><a title=\"{$this->contact_details['homepage']}\" href=\"{$this->contact_details['homepage']}\"><i class=\"fa fa-globe\"></i>{$this->contact_details['homepage']}</a></li>\n";
301
        }
302
303
        echo "</ul>\n";
304
        echo "</div>\n";
305
    }
306
307
    private function _show_phone_number(string $field, string $type)
308
    {
309
        if (!empty($this->contact_details[$field])) {
310
            echo "<li><a title=\"Dial {$this->contact_details[$field]}\" href=\"tel:{$this->contact_details[$field]}\"><i class=\"fa fa-{$type}\"></i>{$this->contact_details[$field]}</a></li>\n";
311
        }
312
    }
313
314
    private function _show_groups()
315
    {
316
        if (   !$this->show_groups
317
            || empty($this->contact_details['id'])) {
318
            return;
319
        }
320
        $link_contacts = $this->link_contacts && self::$_contacts_url;
321
322
        $mc = org_openpsa_contacts_member_dba::new_collector('uid', $this->contact_details['id']);
323
        $mc->add_constraint('gid.orgOpenpsaObtype', '>=', org_openpsa_contacts_group_dba::ORGANIZATION);
324
325
        foreach ($mc->get_rows(['gid', 'extra']) as $data) {
326
            try {
327
                $group = org_openpsa_contacts_group_dba::get_cached($data['gid']);
328
            } catch (midcom_error $e) {
329
                $e->log();
330
                continue;
331
            }
332
333
            echo "<li>";
334
335
            if ($data['extra']) {
336
                echo "<span class=\"title\">" . htmlspecialchars($data['extra']) . "</span>, ";
337
            }
338
339
            $group_label = htmlspecialchars($group->get_label());
0 ignored issues
show
Bug introduced by
The method get_label() does not exist on midcom_core_dbaobject. It seems like you code against a sub-type of midcom_core_dbaobject such as org_openpsa_calendar_event_dba or org_openpsa_invoices_invoice_dba or net_nemein_tag_tag_dba or org_openpsa_invoices_invoice_item_dba or midcom_db_parameter or org_openpsa_calendar_event_member_dba or org_openpsa_sales_salesproject_offer_dba or midcom_db_topic or net_nemein_tag_link_dba or org_openpsa_invoices_billing_data_dba or org_openpsa_directmarketing_campaign_member_dba or org_openpsa_contacts_group_dba or midcom_db_person or midcom_db_member or org_openpsa_projects_project or org_openpsa_calendar_event_resource_dba or midcom_db_group or org_openpsa_projects_task_dba or org_openpsa_documents_document_dba. ( Ignorable by Annotation )

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

339
            $group_label = htmlspecialchars($group->/** @scrutinizer ignore-call */ get_label());
Loading history...
340
            if ($link_contacts) {
341
                $group_label = "<a href=\"" . self::$_contacts_url . "group/{$group->guid}/\"><i class=\"fa fa-users\"></i>" . $group_label . '</a>';
342
            }
343
344
            echo "<span class=\"organization-name\">{$group_label}</span>";
345
            echo "</li>\n";
346
        }
347
    }
348
349
    /**
350
     * Renderer for organization address cards
351
     */
352 1
    public static function show_address_card($customer, array $cards)
353
    {
354 1
        $cards_to_show = [];
355 1
        $multiple_addresses = false;
356 1
        $inherited_cards_only = true;
357 1
        $default_shown = false;
358 1
        $siteconfig = org_openpsa_core_siteconfig::get_instance();
359 1
        $contacts_url = $siteconfig->get_node_full_url('org.openpsa.contacts');
360
361 1
        foreach ($cards as $cardname) {
362 1
            if ($cardname == 'visiting') {
363 1
                if ($customer->street) {
364
                    $default_shown = true;
365
                    $cards_to_show[] = $cardname;
366
                }
367 1
                continue;
368
            }
369
370 1
            $property = $cardname . 'Street';
371
372 1
            if (empty($cards_to_show)) {
373 1
                if ($customer->$property) {
374
                    $inherited_cards_only = false;
375
                    $cards_to_show[] = $cardname;
376 1
                } elseif (!$default_shown && $customer->street) {
377
                    $default_shown = true;
378 1
                    $cards_to_show[] = $cardname;
379
                }
380
            } elseif (    $customer->$property
381
                      || ($customer->street && !$inherited_cards_only && !$default_shown)) {
382
                $inherited_cards_only = false;
383
                $multiple_addresses = true;
384
                $cards_to_show[] = $cardname;
385
            }
386
        }
387
388 1
        if (empty($cards_to_show)) {
389 1
            return;
390
        }
391
392
        $root_group = org_openpsa_contacts_interface::find_root_group();
393
        $parent = $customer->get_parent();
394
        $parent_name = false;
395
        if ($parent->id != $root_group->id) {
396
            $parent_name = $parent->get_label();
397
        }
398
399
        foreach ($cards_to_show as $cardname) {
400
            echo '<div class="vcard">';
401
            if (   $multiple_addresses
402
                || (   $cardname != 'visiting'
403
                    && !$inherited_cards_only)) {
404
                echo '<div style="text-align:center"><em>' . midcom::get()->i18n->get_string($cardname . ' address', 'org.openpsa.contacts') . "</em></div>\n";
405
            }
406
            echo "<strong>\n";
407
            if ($parent_name) {
408
                echo '<a href="' . $contacts_url . 'group/' . $parent->guid . '/">' . $parent_name . "</a><br />\n";
0 ignored issues
show
Bug introduced by
Are you sure $contacts_url of type false|mixed|null can be used in concatenation? ( Ignorable by Annotation )

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

408
                echo '<a href="' . /** @scrutinizer ignore-type */ $contacts_url . 'group/' . $parent->guid . '/">' . $parent_name . "</a><br />\n";
Loading history...
409
            }
410
411
            $label = $customer->get_label();
412
413
            if ($cardname != 'visiting') {
414
                $label_property = $cardname . '_label';
415
                $label = $customer->$label_property;
416
            }
417
418
            echo $label . "\n";
419
            echo "</strong>\n";
420
421
            $property_street = 'street';
422
            $property_postcode = 'postcode';
423
            $property_city = 'city';
424
425
            if ($cardname != 'visiting') {
426
                $property_street = $cardname . 'Street';
427
                $property_postcode = $cardname . 'Postcode';
428
                $property_city = $cardname . 'City';
429
            }
430
            if ($customer->$property_street) {
431
                echo "<p>{$customer->$property_street}<br />\n";
432
                echo "{$customer->$property_postcode} {$customer->$property_city}</p>\n";
433
            } elseif ($customer->street) {
434
                echo "<p>{$customer->street}<br />\n";
435
                echo "{$customer->postcode} {$customer->city}</p>\n";
436
            }
437
            echo "</div>\n";
438
        }
439
    }
440
}
441