diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 7280288c02d56..b25884c4dd276 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -2339,47 +2339,82 @@ public function getShares($resourceId, $calendarType=self::CALENDAR_TYPE_CALENDA } /** - * @param boolean $value - * @param \OCA\DAV\CalDAV\Calendar $calendar - * @return string|null + * @param Calendar $calendar + * @return string */ - public function setPublishStatus($value, $calendar) { + public function addPublicLink(Calendar $calendar): string { + $calendarId = $calendar->getResourceId(); + $publicUri = $this->random->generate(16, ISecureRandom::CHAR_HUMAN_READABLE); + $this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent( + '\OCA\DAV\CalDAV\CalDavBackend::addPublicLink', + [ + 'calendarId' => $calendarId, + 'calendarData' => $this->getCalendarById($calendarId), + 'publicuri' => $publicUri, + ])); + + $query = $this->db->getQueryBuilder(); + $query->insert('dav_shares') + ->values([ + 'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()), + 'type' => $query->createNamedParameter('calendar'), + 'access' => $query->createNamedParameter(self::ACCESS_PUBLIC), + 'resourceid' => $query->createNamedParameter($calendar->getResourceId()), + 'publicuri' => $query->createNamedParameter($publicUri) + ]); + $query->execute(); + return $publicUri; + } + + /** + * @param Calendar $calendar + * @param string $publicUri + */ + public function removePublicLink(Calendar $calendar, string $publicUri) { $calendarId = $calendar->getResourceId(); + $this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent( - '\OCA\DAV\CalDAV\CalDavBackend::updateShares', + '\OCA\DAV\CalDAV\CalDavBackend::removePublicLinks', [ 'calendarId' => $calendarId, 'calendarData' => $this->getCalendarById($calendarId), - 'public' => $value, + 'publicuri' => $publicUri ])); $query = $this->db->getQueryBuilder(); - if ($value) { - $publicUri = $this->random->generate(16, ISecureRandom::CHAR_HUMAN_READABLE); - $query->insert('dav_shares') - ->values([ - 'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()), - 'type' => $query->createNamedParameter('calendar'), - 'access' => $query->createNamedParameter(self::ACCESS_PUBLIC), - 'resourceid' => $query->createNamedParameter($calendar->getResourceId()), - 'publicuri' => $query->createNamedParameter($publicUri) - ]); - $query->execute(); - return $publicUri; - } $query->delete('dav_shares') - ->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId()))) + ->where($query->expr()->eq('publicuri', $query->createNamedParameter($publicUri))) + ->andWhere($query->expr()->eq('resourceid', $query->createNamedParameter($calendarId))) ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC))); $query->execute(); - return null; } /** - * @param \OCA\DAV\CalDAV\Calendar $calendar - * @return mixed + * @param Calendar $calendar + */ + public function removeAllPublicLinks(Calendar $calendar) { + $calendarId = $calendar->getResourceId(); + + $this->dispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent( + '\OCA\DAV\CalDAV\CalDavBackend::removeAllPublicLinks', + [ + 'calendarId' => $calendarId, + 'calendarData' => $this->getCalendarById($calendarId), + ])); + + $query = $this->db->getQueryBuilder(); + $query->delete('dav_shares') + ->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendarId))) + ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC))); + $query->execute(); + } + + /** + * @param Calendar $calendar + * @return array */ - public function getPublishStatus($calendar) { + public function getPublicURIs($calendar): array { $query = $this->db->getQueryBuilder(); $result = $query->select('publicuri') ->from('dav_shares') @@ -2387,9 +2422,7 @@ public function getPublishStatus($calendar) { ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC))) ->execute(); - $row = $result->fetch(); - $result->closeCursor(); - return $row ? reset($row) : false; + return $result->fetchAll(\PDO::FETCH_ASSOC); } /** diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php index 7a46060290363..e25fffa713846 100644 --- a/apps/dav/lib/CalDAV/Calendar.php +++ b/apps/dav/lib/CalDAV/Calendar.php @@ -350,21 +350,32 @@ public function calendarQuery(array $filters) { return $uris; } + public function addPublicLink() { + $publicUri = $this->caldavBackend->addPublicLink($this); + $this->calendarInfo['publicuris'][] = $publicUri; + return $publicUri; + } + + public function removePublicLink(string $publicUri) { + $this->caldavBackend->removePublicLink($this, $publicUri); + } + + public function removeAllPublicLinks() { + $this->caldavBackend->removeAllPublicLinks($this); + } + /** - * @param boolean $value - * @return string|null + * @return bool $value */ - public function setPublishStatus($value) { - $publicUri = $this->caldavBackend->setPublishStatus($value, $this); - $this->calendarInfo['publicuri'] = $publicUri; - return $publicUri; + public function getPublishStatus(): bool { + return count($this->getPublicURIs()) > 0; } /** - * @return mixed $value + * @return mixed */ - public function getPublishStatus() { - return $this->caldavBackend->getPublishStatus($this); + public function getPublicURIs() : array { + return array_map(function ($publicURI) { return $publicURI['publicuri']; }, $this->caldavBackend->getPublicURIs($this)); } public function canWrite() { diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php index e8f6e03464172..5cfb8f7e979d9 100644 --- a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php +++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php @@ -41,6 +41,7 @@ class PublishPlugin extends ServerPlugin { const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; + const NS_NEXTCLOUD = 'http://nextcloud.com/ns/'; /** * Reference to SabreDAV server object. @@ -121,10 +122,22 @@ public function propFind(PropFind $propFind, INode $node) { $propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) { if ($node->getPublishStatus()) { // We return the publish-url only if the calendar is published. - $token = $node->getPublishStatus(); + $token = reset($node->getPublicURIs()); $publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token; - return new Publisher($publishUrl, true); + return new Publisher([$publishUrl => true]); + } + }); + + $propFind->handle('{'.self::NS_NEXTCLOUD.'}publish-urls', function () use ($node) { + if ($node->getPublishStatus()) { + // We return the publish-url only if the calendar is published. + $tokens = $node->getPublicURIs(); + $publishUrls = array_map(function ($token) { + return [$this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token => true]; + }, $tokens); + + return new Publisher($publishUrls); } }); @@ -172,65 +185,90 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) // re-populated the request body with the existing data. $request->setBody($requestBody); - $this->server->xml->parse($requestBody, $request->getUrl(), $documentType); + $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType); switch ($documentType) { case '{'.self::NS_CALENDARSERVER.'}publish-calendar' : - // We can only deal with IShareableCalendar objects - if (!$node instanceof Calendar) { - return; - } - $this->server->transactionType = 'post-publish-calendar'; + // We can only deal with IShareableCalendar objects + if (!$node instanceof Calendar) { + return; + } + $this->server->transactionType = 'post-publish-calendar'; - // Getting ACL info - $acl = $this->server->getPlugin('acl'); + // Getting ACL info + $acl = $this->server->getPlugin('acl'); - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($path, '{DAV:}write'); - } + // If there's no ACL support, we allow everything + if ($acl) { + $acl->checkPrivileges($path, '{DAV:}write'); + } - $node->setPublishStatus(true); + $node->addPublicLink(); - // iCloud sends back the 202, so we will too. - $response->setStatus(202); + // iCloud sends back the 202, so we will too. + $response->setStatus(202); - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $response->setHeader('X-Sabre-Status', 'everything-went-well'); + // Adding this because sending a response body may cause issues, + // and I wanted some type of indicator the response was handled. + $response->setHeader('X-Sabre-Status', 'everything-went-well'); - // Breaking the event chain - return false; + // Breaking the event chain + return false; case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' : - // We can only deal with IShareableCalendar objects - if (!$node instanceof Calendar) { - return; - } - $this->server->transactionType = 'post-unpublish-calendar'; + // We can only deal with IShareableCalendar objects + if (!$node instanceof Calendar) { + return; + } + $this->server->transactionType = 'post-unpublish-all-calendars'; + + // Getting ACL info + $acl = $this->server->getPlugin('acl'); + + // If there's no ACL support, we allow everything + if ($acl) { + $acl->checkPrivileges($path, '{DAV:}write'); + } + + $node->removeAllPublicLinks(); + + $response->setStatus(200); - // Getting ACL info - $acl = $this->server->getPlugin('acl'); + // Adding this because sending a response body may cause issues, + // and I wanted some type of indicator the response was handled. + $response->setHeader('X-Sabre-Status', 'everything-went-well'); - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($path, '{DAV:}write'); - } + // Breaking the event chain + return false; - $node->setPublishStatus(false); + case '{'.self::NS_NEXTCLOUD.'}unpublish-calendar' : + // We can only deal with IShareableCalendar objects + if (!$node instanceof Calendar) { + return; + } + $this->server->transactionType = 'post-unpublish-calendar'; + + // Getting ACL info + $acl = $this->server->getPlugin('acl'); + + // If there's no ACL support, we allow everything + if ($acl) { + $acl->checkPrivileges($path, '{DAV:}write'); + } - $response->setStatus(200); + $node->removePublicLink($message); - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $response->setHeader('X-Sabre-Status', 'everything-went-well'); + $response->setStatus(200); - // Breaking the event chain - return false; + // Adding this because sending a response body may cause issues, + // and I wanted some type of indicator the response was handled. + $response->setHeader('X-Sabre-Status', 'everything-went-well'); + // Breaking the event chain + return false; } } } diff --git a/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php index 9e355e018d610..be0fe58f29bff 100644 --- a/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php +++ b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php @@ -30,33 +30,26 @@ class Publisher implements XmlSerializable { /** - * @var string $publishUrl + * @var string $publishUrls */ - protected $publishUrl; + protected $publishUrls; /** - * @var boolean $isPublished + * @param array $publishUrls */ - protected $isPublished; - - /** - * @param string $publishUrl - * @param boolean $isPublished - */ - function __construct($publishUrl, $isPublished) { - $this->publishUrl = $publishUrl; - $this->isPublished = $isPublished; + function __construct(array $publishUrls) { + $this->publishUrls = $publishUrls; } /** - * @return string + * @return array */ - function getValue() { - return $this->publishUrl; + function getValue(): array { + return array_keys($this->publishUrls); } /** - * The xmlSerialize metod is called during xml writing. + * The xmlSerialize method is called during xml writing. * * Use the $writer argument to write its own xml serialization. * @@ -75,12 +68,13 @@ function getValue() { * @return void */ function xmlSerialize(Writer $writer) { - if (!$this->isPublished) { + foreach ($this->publishUrls as $publishUrl => $isPublished) + if (!$isPublished) { // for pre-publish-url - $writer->write($this->publishUrl); + $writer->write($publishUrl); } else { // for publish-url - $writer->writeElement('{DAV:}href', $this->publishUrl); + $writer->writeElement('{DAV:}href', $publishUrl); } } } diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index cc942b5662c50..9e641c03c32be 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -34,6 +34,7 @@ use OCA\DAV\CalDAV\Calendar; use OCP\IConfig; use OCP\IL10N; +use PHPUnit\Framework\MockObject\MockObject; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\PropPatch; use Sabre\DAV\Xml\Property\Href; @@ -280,7 +281,7 @@ public function testCalendarObjectsOperations() { $this->assertCount(0, $calendarObjects); } - + public function testMultipleCalendarObjectsWithSameUID() { $this->expectException(\Sabre\DAV\Exception\BadRequest::class); $this->expectExceptionMessage('Calendar object with uid already exists in this calendar collection.'); @@ -508,12 +509,12 @@ public function testPublications() { $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0]; - /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject $l10n */ + /** @var IL10N|MockObject $l10n */ $l10n = $this->createMock(IL10N::class); $config = $this->createMock(IConfig::class); $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config); - $calendar->setPublishStatus(true); + $calendar->addPublicLink(); $this->assertNotEquals(false, $calendar->getPublishStatus()); $publicCalendars = $this->backend->getPublicCalendars(); @@ -525,11 +526,24 @@ public function testPublications() { $publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI); $this->assertEquals(true, $publicCalendar['{http://owncloud.org/ns}public']); - $calendar->setPublishStatus(false); + $calendar->addPublicLink(); + $publicCalendarURIs = $this->backend->getPublicURIs($calendar); + $this->assertCount(2, $publicCalendarURIs); + $publicCalendarURI2 = $publicCalendarURIs[1]['publicuri']; + $publicCalendar2 = $this->backend->getPublicCalendar($publicCalendarURI2); + $this->assertEquals(true, $publicCalendar2['{http://owncloud.org/ns}public']); + $calendar->removePublicLink($publicCalendarURI2); + + $publicCalendarURIs = $this->backend->getPublicURIs($calendar); + $this->assertCount(1, $publicCalendarURIs); + $calendar->removeAllPublicLinks(); $this->assertEquals(false, $calendar->getPublishStatus()); $this->expectException(NotFound::class); $this->backend->getPublicCalendar($publicCalendarURI); + + $this->expectException(NotFound::class); + $this->backend->getPublicCalendar($publicCalendarURI2); } public function testSubscriptions() { @@ -607,21 +621,21 @@ public function providesSchedulingData() { DTEND;TZID=Europe/Warsaw:20170325T160000 TRANSP:OPAQUE DESCRIPTION:Magiczna treść uzyskana za pomocą magicznego proszku.\n\nę - żźćńłóÓŻŹĆŁĘ€śśśŚŚ\n \,\,))))))))\;\,\n + żźćńłóÓŻŹĆŁĘ€śśśŚŚ\n \,\,))))))))\;\,\n __))))))))))))))\,\n \\|/ -\\(((((''''((((((((.\n -*-==/// - ///(('' . `))))))\,\n /|\\ ))| o \;-. '((((( - \,(\,\n ( `| / ) \;))))' + ///(('' . `))))))\,\n /|\\ ))| o \;-. '((((( + \,(\,\n ( `| / ) \;))))' \,_))^\;(~\n | | | \,))((((_ _____- -----~~~-. %\,\;(\;(>'\;'~\n o_)\; \; )))(((` ~--- ~ `:: \\ %%~~)(v\;(`('~\n \; ''''```` - `: `:::|\\\,__\,%% )\;`'\; ~\n | _ - ) / `:|`----' `-'\n ______/\\/~ | + `: `:::|\\\,__\,%% )\;`'\; ~\n | _ + ) / `:|`----' `-'\n ______/\\/~ | / /\n /~\;\;.____/\;\;' / ___--\ - ,-( `\;\;\;/\n / // _\;______\;'------~~~~~ /\;\;/\\ /\n - // | | / \; \\\;\;\,\\\n (<_ | \; - /'\,/-----' _>\n \\_| ||_ - //~\;~~~~~~~~~\n `\\_| (\,~~ -Tua Xiong\n - \\~\\\n + ,-( `\;\;\;/\n / // _\;______\;'------~~~~~ /\;\;/\\ /\n + // | | / \; \\\;\;\,\\\n (<_ | \; + /'\,/-----' _>\n \\_| ||_ + //~\;~~~~~~~~~\n `\\_| (\,~~ -Tua Xiong\n + \\~\\\n ~~\n\n SEQUENCE:1 X-MOZ-GENERATION:1 diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php index f63c047a2d2b6..95bf8ab56bf34 100644 --- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php +++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php @@ -7,7 +7,7 @@ * @author Lukas Reschke * @author Morris Jobke * @author Roeland Jago Douma - * @author Thomas Citharel + * @author Thomas Citharel * @author Thomas Müller * @author Vinicius Cubas Brand * @@ -41,6 +41,9 @@ use OCP\ILogger; use OCP\IUserManager; use OCP\Security\ISecureRandom; +use PHPUnit\Framework\MockObject\MockObject; +use Sabre\DAV\Exception; +use Sabre\DAV\Exception\NotFound; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; @@ -60,11 +63,11 @@ class PublicCalendarRootTest extends TestCase { private $publicCalendarRoot; /** @var IL10N */ private $l10n; - /** @var Principal|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Principal| MockObject */ private $principal; - /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + /** @var IUserManager| MockObject */ protected $userManager; - /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ + /** @var IGroupManager| MockObject */ protected $groupManager; /** @var IConfig */ protected $config; @@ -157,13 +160,15 @@ public function testGetChildren() { /** * @return Calendar + * @throws Exception + * @throws NotFound */ protected function createPublicCalendar() { $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []); $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0]; $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config); - $publicUri = $calendar->setPublishStatus(true); + $publicUri = $calendar->addPublicLink(); $calendarInfo = $this->backend->getPublicCalendar($publicUri); $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config); diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php index 99feb5ebfa000..4f4adfd874ef2 100644 --- a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php +++ b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php @@ -33,15 +33,16 @@ class PublisherTest extends TestCase { const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; + const NS_NEXTCLOUD = 'http://nextcloud.com/ns/'; public function testSerializePublished() { - $publish = new Publisher('urltopublish', true); + $publish = new Publisher(['urltopublish' => true]); $xml = $this->write([ '{' . self::NS_CALENDARSERVER . '}publish-url' => $publish, ]); - $this->assertEquals('urltopublish', $publish->getValue()); + $this->assertEquals(['urltopublish'], $publish->getValue()); $this->assertXmlStringEqualsXmlString( ' @@ -50,14 +51,31 @@ public function testSerializePublished() { ', $xml); } + public function testSerializeMultiplePublished() { + $publish = new Publisher(['urltopublish' => true, 'secondurltopublish' => true]); + + $xml = $this->write([ + '{' . self::NS_NEXTCLOUD . '}publish-urls' => $publish, + ]); + + $this->assertEquals(['urltopublish', 'secondurltopublish'], $publish->getValue()); + + $this->assertXmlStringEqualsXmlString( + ' + + urltopublish + secondurltopublish + ', $xml); + } + public function testSerializeNotPublished() { - $publish = new Publisher('urltopublish', false); + $publish = new Publisher(['urltopublish' => false]); $xml = $this->write([ '{' . self::NS_CALENDARSERVER . '}pre-publish-url' => $publish, ]); - $this->assertEquals('urltopublish', $publish->getValue()); + $this->assertEquals(['urltopublish'], $publish->getValue()); $this->assertXmlStringEqualsXmlString( ' diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php index cf62b6eb05dbe..7aef34ca3698a 100644 --- a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php +++ b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php @@ -30,6 +30,7 @@ use OCP\IConfig; use OCP\IRequest; use OCP\IURLGenerator; +use PHPUnit\Framework\MockObject\MockObject; use Sabre\DAV\Server; use Sabre\DAV\SimpleCollection; use Sabre\HTTP\Request; @@ -42,11 +43,11 @@ class PluginTest extends TestCase { private $plugin; /** @var Server */ private $server; - /** @var Calendar | \PHPUnit_Framework_MockObject_MockObject */ + /** @var Calendar | MockObject */ private $book; - /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */ + /** @var IConfig | MockObject */ private $config; - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */ + /** @var IURLGenerator | MockObject */ private $urlGenerator; protected function setUp(): void { @@ -79,7 +80,7 @@ protected function setUp(): void { public function testPublishing() { - $this->book->expects($this->once())->method('setPublishStatus')->with(true); + $this->book->expects($this->once())->method('addPublicLink')->with(); // setup request $request = new Request(); @@ -92,7 +93,7 @@ public function testPublishing() { public function testUnPublishing() { - $this->book->expects($this->once())->method('setPublishStatus')->with(false); + $this->book->expects($this->once())->method('removeAllPublicLinks')->with(); // setup request $request = new Request(); @@ -102,4 +103,17 @@ public function testUnPublishing() { $response = new Response(); $this->plugin->httpPost($request, $response); } + + public function testUnPublishingALink() { + + $this->book->expects($this->once())->method('removePublicLink')->with('urltounpublish'); + + // setup request + $request = new Request(); + $request->addHeader('Content-Type', 'application/xml'); + $request->setUrl('cal1'); + $request->setBody('urltounpublish'); + $response = new Response(); + $this->plugin->httpPost($request, $response); + } }