org_openpsa_widgets_contact::_show_groups()   B
last analyzed

Complexity

Conditions 8
Paths 13

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 25.576

Importance

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

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

387
                echo '<a href="' . /** @scrutinizer ignore-type */ $contacts_url . 'group/' . $parent->guid . '/">' . $parent_name . "</a><br />\n";
Loading history...
388
            }
389
390 1
            $label = $customer->get_label();
391
392 1
            if ($cardname != 'visiting') {
393 1
                $label_property = $cardname . '_label';
394 1
                $label = $customer->$label_property;
395
            }
396
397 1
            echo $label . "\n";
398 1
            echo "</strong>\n";
399
400 1
            $property_street = 'street';
401 1
            $property_postcode = 'postcode';
402 1
            $property_city = 'city';
403
404 1
            if ($cardname != 'visiting') {
405 1
                $property_street = $cardname . 'Street';
406 1
                $property_postcode = $cardname . 'Postcode';
407 1
                $property_city = $cardname . 'City';
408
            }
409 1
            if ($customer->$property_street) {
410 1
                echo "<p>{$customer->$property_street}<br />\n";
411 1
                echo "{$customer->$property_postcode} {$customer->$property_city}</p>\n";
412
            } elseif ($customer->street) {
413
                echo "<p>{$customer->street}<br />\n";
414
                echo "{$customer->postcode} {$customer->city}</p>\n";
415
            }
416 1
            echo "</div>\n";
417
        }
418
    }
419
}
420