Passed
Push — master ( c60b86...0ef755 )
by Andreas
17:33
created

org_openpsa_widgets_contact::get_image()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 6.6

Importance

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

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

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