Passed
Push — master ( c219a7...4fe5a9 )
by Andreas
44:46 queued 26:15
created

org_openpsa_calendar_handler_ical::find_event()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0327

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 12
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 17
ccs 11
cts 13
cp 0.8462
crap 3.0327
rs 9.8666
1
<?php
2
/**
3
 * @package org.openpsa.calendar
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use Sabre\VObject\Reader;
10
use Doctrine\ORM\Query\Expr\Join;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
14
/**
15
 * Calendar ical handler
16
 *
17
 * @package org.openpsa.calendar
18
 */
19
class org_openpsa_calendar_handler_ical extends midcom_baseclasses_components_handler
20
{
21
    /**
22
     * @var midcom_db_person
23
     */
24
    private $person;
25
26
    /**
27
     * @return org_openpsa_calendar_event_dba[]
28
     */
29 2
    private function get_events() : array
30
    {
31 2
        $root_event = org_openpsa_calendar_interface::find_root_event();
32
33 2
        $qb = org_openpsa_calendar_event_dba::new_query_builder();
34 2
        $qb->get_doctrine()
35 2
            ->leftJoin('org_openpsa_eventmember', 'm', Join::WITH, 'm.eid = c.id')
36 2
            ->where('m.uid = :uid')
37 2
            ->setParameter('uid', $this->person->id);
38
39 2
        $qb->add_constraint('up', '=', $root_event->id);
40
        // Display events two weeks back
41 2
        $qb->add_constraint('start', '>', strtotime('14 days ago'));
42 2
        $qb->add_order('start', 'ASC');
43 2
        return $qb->execute();
44
    }
45
46
    /**
47
     * iCal feed of uses events
48
     *
49
     * HTTP-Basic authenticated, requires valid user, normal ACL restrictions apply
50
     */
51 2
    public function _handler_user_events(Request $request, string $username)
52
    {
53 2
        midcom::get()->auth->require_valid_user('basic');
54
55 2
        $this->find_person_by_name($username);
56 2
        if ($request->getMethod() === 'PUT') {
57 1
            $this->update($request->getContent());
58
        }
59
60 2
        $encoder = new org_openpsa_calendar_vcal;
61 2
        array_map([$encoder, 'add_event'], $this->get_events());
62
63 2
        return new Response($encoder, Response::HTTP_OK, [
64 2
            'Content-Type' => 'text/calendar'
65
        ]);
66
    }
67
68 1
    private function update(string $input)
69
    {
70 1
        $vcalendar = Reader::read($input);
71 1
        if (!$vcalendar->select('VEVENT')) {
72
            return;
73
        }
74 1
        foreach ($vcalendar->select('VEVENT') as $vevent) {
75 1
            $event = $this->find_event((string) $vevent->UID);
76
77 1
            $event->title = (string) $vevent->SUMMARY;
78 1
            $event->description = (string) $vevent->DESCRIPTION;
79 1
            $event->location = (string) $vevent->LOCATION;
80 1
            $event->busy = (string) $vevent->TRANSP == 'OPAQUE';
81 1
            $start = new DateTime((string) $vevent->DTSTART);
82 1
            $event->start = (int) $start->format('U');
83 1
            $end = new DateTime((string) $vevent->DTEND);
84 1
            $event->end = (int) $end->format('U');
85
86 1
            if ($event->id) {
87
                $event->update();
88
            } else {
89 1
                $event->create();
90 1
                $member = new org_openpsa_calendar_event_member_dba;
91 1
                $member->eid = $event->id;
92 1
                $member->uid = $this->person->id;
93 1
                $member->create();
94
            }
95
        }
96 1
    }
97
98 1
    private function find_event(string $uid) : org_openpsa_calendar_event_dba
99
    {
100 1
        if (str_ends_with($uid, '-midgardGuid')) {
101
            return new org_openpsa_calendar_event_dba(substr($uid, 0, -12));
102
        }
103 1
        $qb = org_openpsa_calendar_event_dba::new_query_builder();
104 1
        $qb->add_constraint('externalGuid', '=', $uid);
105 1
        if ($result = $qb->execute()) {
106
            return $result[0];
107
        }
108
109 1
        $event = new org_openpsa_calendar_event_dba;
110 1
        $event->externalGuid = $uid;
111 1
        $root_event = org_openpsa_calendar_interface::find_root_event();
112 1
        $root_event->require_do('midgard:create');
113 1
        $event->up = $root_event->id;
114 1
        return $event;
115
    }
116
117
    /**
118
     * Finds a person by username
119
     */
120 2
    private function find_person_by_name(string $username)
121
    {
122 2
        $username = preg_replace('/\.[iv]cs$/', '', $username);
123
124 2
        if (empty($username)) {
125
            throw new midcom_error('Username missing');
126
        }
127 2
        $qb = midcom_db_person::new_query_builder();
128 2
        midcom_core_account::add_username_constraint($qb, '=', $username);
129 2
        midcom::get()->auth->request_sudo($this->_component);
130 2
        $persons = $qb->execute();
131 2
        midcom::get()->auth->drop_sudo();
132 2
        if (empty($persons)) {
133
            throw new midcom_error_notfound('Could not find person with username ' . $username);
134
        }
135 2
        $this->person = $persons[0];
136 2
    }
137
138
    /**
139
     * Publicly available iCal feed indicating user when is busy
140
     *
141
     * Most values are stripped before display
142
     */
143
    public function _handler_user_busy(string $username)
144
    {
145
        $this->find_person_by_name($username);
146
147
        $encoder = new org_openpsa_calendar_vcal;
148
        foreach ($this->get_events() as $event) {
149
            // clear all data not absolutely required for busy listing
150
            foreach ($event->get_properties() as $fieldname) {
151
                if ($fieldname == 'title') {
152
                    $event->title = $this->_l10n->get('busy');
153
                } elseif (is_array($event->$fieldname)) {
154
                    $event->$fieldname = [];
155
                } elseif (!in_array($fieldname, ['metadata', 'guid', 'start', 'end'])) {
156
                    $event->$fieldname = '';
157
                }
158
            }
159
            // Only display the requested user as participant
160
            $event->participants[$this->person->id] = true;
161
            // Always force busy in this view
162
            $event->busy = true;
163
            $encoder->add_event($event);
164
        }
165
        return new Response($encoder, Response::HTTP_OK, [
166
            'Content-Type' => 'text/calendar'
167
        ]);
168
    }
169
}
170