diff --git a/lib/CalDAV/Schedule/Plugin.php b/lib/CalDAV/Schedule/Plugin.php index 8577ae9f70..3092b3628f 100644 --- a/lib/CalDAV/Schedule/Plugin.php +++ b/lib/CalDAV/Schedule/Plugin.php @@ -597,8 +597,9 @@ public function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilege } /** - * This method looks at an old iCalendar object, a new iCalendar object and - * starts sending scheduling messages based on the changes. + * This method looks at an old iCalendar object, a new iCalendar object and: + * - starts sending scheduling messages based on the changes. + * - ensures the description fields are coherent * * A list of addresses needs to be specified, so the system knows who made * the update, because the behavior may be different based on if it's an @@ -612,6 +613,8 @@ public function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilege */ protected function processICalendarChange($oldObject, VCalendar $newObject, array $addresses, array $ignore = [], &$modified = false) { + $this->ensureDescriptionConsistency($oldObject, $newObject, $modified); + $broker = $this->createITipBroker(); $messages = $broker->parseEvent($newObject, $addresses, $oldObject); @@ -1003,4 +1006,41 @@ protected function createITipBroker(): Broker { return new Broker(); } + + /** + * Ensure the alternate version of the description is removed if only the main one is changed + */ + private function ensureDescriptionConsistency($oldObj, VCalendar $vCal, &$modified) { + if (!$oldObj) { + return; // No previous version to compare + } + + $xAltDescPropName = "X-ALT-DESC"; + + // Get presence of description fields + $hasOldDescription = isset($oldObj->VTODO) && isset($oldObj->VTODO->DESCRIPTION); + $hasNewDescription = isset($vCal->VTODO) && isset($vCal->VTODO->DESCRIPTION); + $hasOldXAltDesc = isset($oldObj->VTODO) && isset($oldObj->VTODO->{$xAltDescPropName}); + $hasNewXAltDesc = isset($vCal->VTODO) && isset($vCal->VTODO->{$xAltDescPropName}); + $hasAllDesc = $hasOldDescription && $hasNewDescription && $hasOldXAltDesc && $hasNewXAltDesc; + + // If all description fields are present, then verify consistency + if ($hasAllDesc) { + // Get descriptions + $oldDescription = (string) $oldObj->VTODO->DESCRIPTION; + $newDescription = (string) $vCal->VTODO->DESCRIPTION; + $oldXAltDesc = (string) $oldObj->VTODO->{$xAltDescPropName}; + $newXAltDesc = (string) $vCal->VTODO->{$xAltDescPropName}; + + // Compare descriptions + $isSameDescription = $oldDescription === $newDescription; + $isSameXAltDesc = $oldXAltDesc === $newXAltDesc; + + // If the description changed, but not the alternate one, then delete the latest + if (!$isSameDescription && $isSameXAltDesc) { + unset($vCal->VTODO->{$xAltDescPropName}); + $modified = true; + } + } + } } diff --git a/tests/docker/Dockerfile b/tests/docker/Dockerfile new file mode 100644 index 0000000000..f26fd74cbe --- /dev/null +++ b/tests/docker/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:24.04 + +# Install PHP +RUN apt update -y +RUN apt install ca-certificates -y +ADD php.sources /etc/apt/sources.list.d/ +RUN apt update -y +RUN apt install -y php7.4 php7.4-xml php7.4-mbstring php7.4-curl php7.4-sqlite3 +RUN apt install -y curl zip git + +# Install composer +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +RUN php composer-setup.php --version=2.8.3 +RUN mv composer.phar /usr/local/bin/composer +RUN rm composer-setup.php + +# Setup tests +RUN mkdir /src/ +ADD run-tests.sh . +RUN chmod +x run-tests.sh + +ENTRYPOINT ["/run-tests.sh"] diff --git a/tests/docker/README.md b/tests/docker/README.md new file mode 100644 index 0000000000..929531c365 --- /dev/null +++ b/tests/docker/README.md @@ -0,0 +1,9 @@ +USAGE +===== + +- Install Docker +- Download the folder **/tests/docker** from the repository +- Goto that folder using a terminal +- Run `docker compose up` +- Run `docker run -ti sabre-dav-unit-tests` + diff --git a/tests/docker/docker-compose.yml b/tests/docker/docker-compose.yml new file mode 100644 index 0000000000..ee897fa530 --- /dev/null +++ b/tests/docker/docker-compose.yml @@ -0,0 +1,8 @@ +services: + sabre-dav-unit-tests: + entrypoint: bash -c "echo Execute docker run -ti sabre-dav-unit-tests to start" + container_name: sabre-dav-unit-tests + build: + context: ./ + dockerfile: ./Dockerfile + image: sabre-dav-unit-tests:latest \ No newline at end of file diff --git a/tests/docker/php.sources b/tests/docker/php.sources new file mode 100644 index 0000000000..0913c78b91 --- /dev/null +++ b/tests/docker/php.sources @@ -0,0 +1,34 @@ +Types: deb +URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu/ +Suites: noble +Components: main +Signed-By: + -----BEGIN PGP PUBLIC KEY BLOCK----- + . + mQINBGYo0vEBEAC0Semxy5I2b8exRUxJfTKkHR4f5uyS0dTd9vYgMI5T3gsa7ypH + HtE+GiZC+T9m/F9h66+XJMxhuNsKRs7T2In5NSeso9H/ytlSTayUaBtCFfRp6y6b + 6ozuRBfqYJGxhjAnIzvNF/Wpp2BvfQm3OrQ7uJJrt5IvzLDC4jPxl/Xs3sTT+Hbk + bkKKprZ3xmy2enuwBaNWR/CUtAz3hbkzL1kGbhX9m3QidFJagVVdDw3aNEwo8ush + djWfF+BajNvpDFYJKBGQbCeagB753Baa5yIN62x+THLnLiKTMDS1e7U0ZDiV9671 + noTbtN5TeZeyfsEmeZ8X60x11JIP3yYHYZT70/DyTYX3WC9yQFyIgVOfRlGklMKI + k3TLMmtq8w5Hz1vovwzV7PzaQnmY+uNP2ZbAP4fJ3iFAj0L+u0i1nOFgTy0Lq058 + O/FjRrQxuceDDCF+9ThspXMw3Puvz8giuBDCdEda84uC7XWMdqgz/maLfFQjAmyP + Ixi1EMxMlHYyZajpR1cdCfrAIQlnQjHSWmyeCFgXPPfRA71aCcJ7oSrDjogW6Ahd + HRkQRKf1FF9BFzycgSQotfR+7CKfPQh1kghufM9W/spARzA709nGZjXJzgEJLQd3 + CDB6dIIxT/0YI36h3Qgfmiiw4twO24MMEqEEPIELz2WJKeWGkdQdcekpxQARAQAB + tB9MYXVuY2hwYWQgUFBBIGZvciBPbmTFmWVqIFN1csO9iQJOBBMBCgA4FiEEuNx+ + U5RmVu+85MHdcdrqq0rUyrYFAmYo0vECGwMFCwkIBwIGFQoJCAsCBBYCAwECHgEC + F4AACgkQcdrqq0rUyrYOPQ/+IArA4s1J3op/w7cXek0ieFHWHFDrxPYS+78/LF/J + LoYZw0nIU5Ovr+LzehFMIQU6esgPXwbeCVgwLwat57augAkAYWT0UzH5dE6RKAGr + C2vsHWVfPhQn6UndfzwXc0mTLGQni25aQaZ6k60Dbm/vblejrTQrtAUWoMO3Z1cr + NDGJ3Z9DCxtr2o9gRYUI6HwLHJtobTIeI5xsr5x+GvXiIAVCPa3ZEuRL6jMQfqfS + C43mpuiS1kGgsnQLs2DbN7EFCfiJoNX1QzZu25zg+IS9PXbCJnheZWnH0rwUSb/N + hZPcSefGlNlhr824OfT30v79hQnw59XbsfV270O9jPbD4kttN+OiszbU66zsuiOh + BO46XCckQPqDkBMw56GPFuVrQgGb1thXvn67URJgPyJhwauBWKPNAJ9Ojuo+yVq/ + hdR1VNWThXQbZgaGSWrbjt6FdYtQb9VX88uu5gFDmr180HogHNUDUcqNLLdnjfFs + 4DyJlusQ5I/a7cQ7nlkNgxAmHszwO/mGLBuGljDUYkwZDW9nqP1Q5Q2jMtrhgXvR + 2SOtufvecUbB7+eoRSaOnu7CNMATG6LocFEMzhKUde1uZTfWSqnYEcdqoFJMi46y + qaNxhiNLsQ5OBMbgSp2zCbQxRBdITMVvBR5YjCetUIGEs6T1yQ5wh5Xpoi34ShHn + v38= + =kFlZ + -----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/tests/docker/run-tests.sh b/tests/docker/run-tests.sh new file mode 100644 index 0000000000..d1fb0b320e --- /dev/null +++ b/tests/docker/run-tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +repoUrl= +while [ -z "$repoUrl" ] +do + read -p "Please enter public repository URL:" repoUrl + + if [ -z "$repoUrl" ]; then echo "Repository URL is mandatory"; fi +done + +read -p "Enter the branch name [default: master]" branchName +branchName=${branchName:-master} + +echo "Are you sure you want to test with?" +echo "URL: $repoUrl" +echo "Branch: $branchName" +read -p "[y/N]" confirm + +if [ "$confirm" != "Y" ] && [ "$confirm" != "y" ]; then + echo "Cancelling test run" + exit +fi + +echo "Starting setup" + +git clone -b "$branchName" --single-branch --depth 1 "$repoUrl" /src/ + +( + cd /src/ + composer install + + mkdir -p vendor/sabre/http/tests/www + php -S localhost:8000 -t vendor/sabre/http/tests/www & + + composer phpunit +)