Passed
Push — master ( 900101...1b7a8f )
by Andreas
17:53
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 13
CRAP Score 12.1438

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

329
            $group_label = htmlspecialchars($group->/** @scrutinizer ignore-call */ get_label());
Loading history...
330
            if ($link_contacts) {
331
                $group_label = "<a href=\"" . self::$_contacts_url . "group/{$group->guid}/\"><i class=\"fa fa-users\"></i>" . $group_label . '</a>';
332
            }
333
334
            echo "<span class=\"organization-name\">{$group_label}</span>";
335
            echo "</li>\n";
336
        }
337 2
    }
338
339
    /**
340
     * Renderer for organization address cards
341
     */
342 1
    public static function show_address_card($customer, array $cards)
343
    {
344 1
        $cards_to_show = [];
345 1
        $multiple_addresses = false;
346 1
        $inherited_cards_only = true;
347 1
        $default_shown = false;
348 1
        $siteconfig = org_openpsa_core_siteconfig::get_instance();
349 1
        $contacts_url = $siteconfig->get_node_full_url('org.openpsa.contacts');
350
351 1
        foreach ($cards as $cardname) {
352 1
            if ($cardname == 'visiting') {
353 1
                if ($customer->street) {
354
                    $default_shown = true;
355
                    $cards_to_show[] = $cardname;
356
                }
357 1
                continue;
358
            }
359
360 1
            $property = $cardname . 'Street';
361
362 1
            if (empty($cards_to_show)) {
363 1
                if ($customer->$property) {
364 1
                    $inherited_cards_only = false;
365 1
                    $cards_to_show[] = $cardname;
366
                } elseif (!$default_shown && $customer->street) {
367
                    $default_shown = true;
368 1
                    $cards_to_show[] = $cardname;
369
                }
370
            } elseif (    $customer->$property
371
                      || ($customer->street && !$inherited_cards_only && !$default_shown)) {
372
                $inherited_cards_only = false;
373
                $multiple_addresses = true;
374
                $cards_to_show[] = $cardname;
375
            }
376
        }
377
378 1
        if (empty($cards_to_show)) {
379
            return;
380
        }
381
382 1
        $parent_name = false;
383 1
        if ($parent = $customer->get_parent()) {
384
            $root_group = org_openpsa_contacts_interface::find_root_group();
385
            if ($parent->id != $root_group->id) {
386
                $parent_name = $parent->get_label();
387
            }
388
        }
389
390 1
        foreach ($cards_to_show as $cardname) {
391 1
            echo '<div class="vcard">';
392 1
            if (   $multiple_addresses
393 1
                || (   $cardname != 'visiting'
394 1
                    && !$inherited_cards_only)) {
395 1
                echo '<div style="text-align:center"><em>' . midcom::get()->i18n->get_string($cardname . ' address', 'org.openpsa.contacts') . "</em></div>\n";
396
            }
397 1
            echo "<strong>\n";
398 1
            if ($parent_name) {
399
                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

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