Passed
Push — master ( e0f83a...35bbad )
by Andreas
19:38
created

org_openpsa_calendar_handler_ical::update()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 35
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 5.0307

Importance

Changes 0
Metric Value
cc 5
eloc 29
nc 6
nop 1
dl 0
loc 35
ccs 25
cts 28
cp 0.8929
crap 5.0307
rs 9.1448
c 0
b 0
f 0
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
            $uid = (string) $vevent->UID;
76 1
            if (str_ends_with($uid, '-midgardGuid')) {
77
                $event = new org_openpsa_calendar_event_dba(substr($uid, 0, -12));
78
            } else {
79 1
                $event = new org_openpsa_calendar_event_dba;
80 1
                $event->externalGuid = $uid;
81 1
                $root_event = org_openpsa_calendar_interface::find_root_event();
82 1
                $root_event->require_do('midgard:create');
83 1
                $event->up = $root_event->id;
84
            }
85
86 1
            $event->title = (string) $vevent->SUMMARY;
87 1
            $event->description = (string) $vevent->DESCRIPTION;
88 1
            $event->location = (string) $vevent->LOCATION;
89 1
            $event->busy = (string) $vevent->TRANSP == 'OPAQUE';
90 1
            $start = new DateTime((string) $vevent->DTSTART);
91 1
            $event->start = (int) $start->format('U');
92 1
            $end = new DateTime((string) $vevent->DTEND);
93 1
            $event->end = (int) $end->format('U');
94
95 1
            if ($event->id) {
96
                $event->update();
97
            } else {
98 1
                $event->create();
99 1
                $member = new org_openpsa_calendar_event_member_dba;
100 1
                $member->eid = $event->id;
101 1
                $member->uid = $this->person->id;
102 1
                $member->create();
103
            }
104
        }
105 1
    }
106
107
    /**
108
     * Finds a person by username
109
     */
110 2
    private function find_person_by_name(string $username)
111
    {
112 2
        $username = preg_replace('/\.[iv]cs$/', '', $username);
113
114 2
        if (empty($username)) {
115
            throw new midcom_error('Username missing');
116
        }
117 2
        $qb = midcom_db_person::new_query_builder();
118 2
        midcom_core_account::add_username_constraint($qb, '=', $username);
119 2
        midcom::get()->auth->request_sudo($this->_component);
120 2
        $persons = $qb->execute();
121 2
        midcom::get()->auth->drop_sudo();
122 2
        if (empty($persons)) {
123
            throw new midcom_error_notfound('Could not find person with username ' . $username);
124
        }
125 2
        $this->person = $persons[0];
126 2
    }
127
128
    /**
129
     * Publicly available iCal feed indicating user when is busy
130
     *
131
     * Most values are stripped before display
132
     */
133
    public function _handler_user_busy(string $username)
134
    {
135
        $this->find_person_by_name($username);
136
137
        $encoder = new org_openpsa_calendar_vcal;
138
        foreach ($this->get_events() as $event) {
139
            // clear all data not absolutely required for busy listing
140
            foreach ($event->get_properties() as $fieldname) {
141
                if ($fieldname == 'title') {
142
                    $event->title = $this->_l10n->get('busy');
143
                } elseif (is_array($event->$fieldname)) {
144
                    $event->$fieldname = [];
145
                } elseif (!in_array($fieldname, ['metadata', 'guid', 'start', 'end'])) {
146
                    $event->$fieldname = '';
147
                }
148
            }
149
            // Only display the requested user as participant
150
            $event->participants[$this->person->id] = true;
151
            // Always force busy in this view
152
            $event->busy = true;
153
            $encoder->add_event($event);
154
        }
155
        return new Response($encoder, Response::HTTP_OK, [
156
            'Content-Type' => 'text/calendar'
157
        ]);
158
    }
159
}
160