1111use DateTime ;
1212use DateTimeImmutable ;
1313use DateTimeInterface ;
14+ use Exception as NativeException ;
1415use Generator ;
1516use OCA \DAV \AppInfo \Application ;
1617use OCA \DAV \CalDAV \Federation \FederatedCalendarEntity ;
1718use OCA \DAV \CalDAV \Federation \FederatedCalendarMapper ;
1819use OCA \DAV \CalDAV \Sharing \Backend ;
20+ use OCA \DAV \CalDAV \WebcalCaching \RefreshWebcalService ;
1921use OCA \DAV \Connector \Sabre \Principal ;
2022use OCA \DAV \DAV \Sharing \IShareable ;
2123use OCA \DAV \Events \CachedCalendarObjectCreatedEvent ;
4951use OCP \ICacheFactory ;
5052use OCP \IConfig ;
5153use OCP \IDBConnection ;
54+ use OCP \IL10N ;
5255use OCP \IUserManager ;
5356use OCP \Security \ISecureRandom ;
5457use Psr \Log \LoggerInterface ;
@@ -218,6 +221,7 @@ public function __construct(
218221 private IConfig $ config ,
219222 private Sharing \Backend $ calendarSharingBackend ,
220223 private FederatedCalendarMapper $ federatedCalendarMapper ,
224+ private IL10N $ l10n ,
221225 ICacheFactory $ cacheFactory ,
222226 private bool $ legacyEndpoint = false ,
223227 ) {
@@ -735,6 +739,7 @@ public function getSubscriptionById($subscriptionId) {
735739 $ fields [] = 'synctoken ' ;
736740 $ fields [] = 'principaluri ' ;
737741 $ fields [] = 'lastmodified ' ;
742+ $ fields [] = 'lasterror ' ;
738743
739744 $ query = $ this ->db ->getQueryBuilder ();
740745 $ query ->select ($ fields )
@@ -749,18 +754,7 @@ public function getSubscriptionById($subscriptionId) {
749754 return null ;
750755 }
751756
752- $ row ['principaluri ' ] = (string )$ row ['principaluri ' ];
753- $ subscription = [
754- 'id ' => $ row ['id ' ],
755- 'uri ' => $ row ['uri ' ],
756- 'principaluri ' => $ row ['principaluri ' ],
757- 'source ' => $ row ['source ' ],
758- 'lastmodified ' => $ row ['lastmodified ' ],
759- '{ ' . Plugin::NS_CALDAV . '}supported-calendar-component-set ' => new SupportedCalendarComponentSet (['VTODO ' , 'VEVENT ' ]),
760- '{http://sabredav.org/ns}sync-token ' => $ row ['synctoken ' ] ?: '0 ' ,
761- ];
762-
763- return $ this ->rowToSubscription ($ row , $ subscription );
757+ return $ this ->rowToSubscription ($ row );
764758 }
765759
766760 public function getSubscriptionByUri (string $ principal , string $ uri ): ?array {
@@ -771,6 +765,7 @@ public function getSubscriptionByUri(string $principal, string $uri): ?array {
771765 $ fields [] = 'synctoken ' ;
772766 $ fields [] = 'principaluri ' ;
773767 $ fields [] = 'lastmodified ' ;
768+ $ fields [] = 'lasterror ' ;
774769
775770 $ query = $ this ->db ->getQueryBuilder ();
776771 $ query ->select ($ fields )
@@ -786,18 +781,7 @@ public function getSubscriptionByUri(string $principal, string $uri): ?array {
786781 return null ;
787782 }
788783
789- $ row ['principaluri ' ] = (string )$ row ['principaluri ' ];
790- $ subscription = [
791- 'id ' => $ row ['id ' ],
792- 'uri ' => $ row ['uri ' ],
793- 'principaluri ' => $ row ['principaluri ' ],
794- 'source ' => $ row ['source ' ],
795- 'lastmodified ' => $ row ['lastmodified ' ],
796- '{ ' . Plugin::NS_CALDAV . '}supported-calendar-component-set ' => new SupportedCalendarComponentSet (['VTODO ' , 'VEVENT ' ]),
797- '{http://sabredav.org/ns}sync-token ' => $ row ['synctoken ' ] ?: '0 ' ,
798- ];
799-
800- return $ this ->rowToSubscription ($ row , $ subscription );
784+ return $ this ->rowToSubscription ($ row );
801785 }
802786
803787 /**
@@ -2987,6 +2971,7 @@ public function getSubscriptionsForUser($principalUri) {
29872971 $ fields [] = 'principaluri ' ;
29882972 $ fields [] = 'lastmodified ' ;
29892973 $ fields [] = 'synctoken ' ;
2974+ $ fields [] = 'lasterror ' ;
29902975
29912976 $ query = $ this ->db ->getQueryBuilder ();
29922977 $ query ->select ($ fields )
@@ -2997,18 +2982,7 @@ public function getSubscriptionsForUser($principalUri) {
29972982
29982983 $ subscriptions = [];
29992984 while ($ row = $ stmt ->fetchAssociative ()) {
3000- $ subscription = [
3001- 'id ' => $ row ['id ' ],
3002- 'uri ' => $ row ['uri ' ],
3003- 'principaluri ' => $ row ['principaluri ' ],
3004- 'source ' => $ row ['source ' ],
3005- 'lastmodified ' => $ row ['lastmodified ' ],
3006-
3007- '{ ' . Plugin::NS_CALDAV . '}supported-calendar-component-set ' => new SupportedCalendarComponentSet (['VTODO ' , 'VEVENT ' ]),
3008- '{http://sabredav.org/ns}sync-token ' => $ row ['synctoken ' ] ?: '0 ' ,
3009- ];
3010-
3011- $ subscriptions [] = $ this ->rowToSubscription ($ row , $ subscription );
2985+ $ subscriptions [] = $ this ->rowToSubscription ($ row );
30122986 }
30132987
30142988 return $ subscriptions ;
@@ -3160,6 +3134,29 @@ public function deleteSubscription($subscriptionId) {
31603134 }, $ this ->db );
31613135 }
31623136
3137+ /**
3138+ * Update the error status of a subscription
3139+ *
3140+ * @param mixed $subscriptionId
3141+ * @param null|NativeException $exception
3142+ * @param null|string $error
3143+ * @return void
3144+ */
3145+ public function trackSubscriptionError ($ subscriptionId , $ exception , $ error ): void {
3146+ $ query = $ this ->db ->getQueryBuilder ();
3147+ $ query ->update ('calendarsubscriptions ' )
3148+ ->set ('lasterror ' , $ query ->createNamedParameter ($ error ))
3149+ ->executeStatement ();
3150+
3151+ if ($ error ) {
3152+ $ this ->logger ->error ('Subscription {subscriptionId} could not be refreshed: {error} ' , [
3153+ 'exception ' => $ exception ,
3154+ 'subscriptionId ' => $ subscriptionId ,
3155+ 'error ' => $ error ,
3156+ ]);
3157+ }
3158+ }
3159+
31633160 /**
31643161 * Returns a single scheduling object for the inbox collection.
31653162 *
@@ -4000,11 +3997,47 @@ private function rowToCalendar($row, array $calendar): array {
40003997 * Amend the subscription info with database row data
40013998 *
40023999 * @param array $row
4003- * @param array $subscription
40044000 *
40054001 * @return array
40064002 */
4007- private function rowToSubscription ($ row , array $ subscription ): array {
4003+ private function rowToSubscription ($ row ): array {
4004+ $ row ['principaluri ' ] = (string )$ row ['principaluri ' ];
4005+
4006+ $ subscription = [
4007+ 'id ' => $ row ['id ' ],
4008+ 'uri ' => $ row ['uri ' ],
4009+ 'principaluri ' => $ row ['principaluri ' ],
4010+ 'source ' => $ row ['source ' ],
4011+ 'lastmodified ' => $ row ['lastmodified ' ],
4012+ '{ ' . Plugin::NS_CALDAV . '}supported-calendar-component-set ' => new SupportedCalendarComponentSet (['VTODO ' , 'VEVENT ' ]),
4013+ '{http://sabredav.org/ns}sync-token ' => $ row ['synctoken ' ] ?: '0 ' ,
4014+ ];
4015+
4016+ if ($ row ['lasterror ' ] !== null ) {
4017+ switch ($ row ['lasterror ' ]) {
4018+ case RefreshWebcalService::ERROR_PARSING :
4019+ $ lasterror = $ this ->l10n ->t ('Parsing error ' );
4020+ break ;
4021+ case RefreshWebcalService::ERROR_ACCESS :
4022+ $ lasterror = $ this ->l10n ->t ('Subscription violates local access rules ' );
4023+ break ;
4024+ case RefreshWebcalService::ERROR_URL :
4025+ $ lasterror = $ this ->l10n ->t ('Invalid URL ' );
4026+ break ;
4027+ case RefreshWebcalService::ERROR_CONTENTS :
4028+ $ lasterror = $ this ->l10n ->t ('Invalid contents ' );
4029+ break ;
4030+ case RefreshWebcalService::ERROR_NETWORK :
4031+ $ lasterror = $ this ->l10n ->t ('Network error ' );
4032+ break ;
4033+ default :
4034+ $ lasterror = $ this ->l10n ->t ('Unknown error ' );
4035+ break ;
4036+ }
4037+
4038+ $ subscription ['{ ' . \OCA \DAV \DAV \Sharing \Plugin::NS_NEXTCLOUD . '}subscription-error ' ] = $ lasterror ;
4039+ }
4040+
40084041 foreach ($ this ->subscriptionPropertyMap as $ xmlName => [$ dbName , $ type ]) {
40094042 $ value = $ row [$ dbName ];
40104043 if ($ value !== null ) {
0 commit comments