mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-12 04:23:19 +00:00
Add third party application webhook event
This commit is contained in:
@@ -37,6 +37,8 @@ use Alchemy\Phrasea\Model\Entities\UsrList;
|
|||||||
use Alchemy\Phrasea\Model\Entities\UsrListEntry;
|
use Alchemy\Phrasea\Model\Entities\UsrListEntry;
|
||||||
use Alchemy\Phrasea\Model\Entities\StoryWZ;
|
use Alchemy\Phrasea\Model\Entities\StoryWZ;
|
||||||
use Alchemy\Phrasea\Core\Provider\ORMServiceProvider;
|
use Alchemy\Phrasea\Core\Provider\ORMServiceProvider;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
use Doctrine\ORM\Tools\SchemaTool;
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
@@ -109,6 +111,8 @@ class RegenerateSqliteDb extends Command
|
|||||||
$this->insertTwoTokens($this->container['EM'], $DI);
|
$this->insertTwoTokens($this->container['EM'], $DI);
|
||||||
$this->insertOneInvalidToken($this->container['EM'], $DI);
|
$this->insertOneInvalidToken($this->container['EM'], $DI);
|
||||||
$this->insertOneValidationToken($this->container['EM'], $DI);
|
$this->insertOneValidationToken($this->container['EM'], $DI);
|
||||||
|
$this->insertWebhookEvent($this->container['EM'], $DI);
|
||||||
|
$this->insertWebhookEventDelivery($this->container['EM'], $DI);
|
||||||
|
|
||||||
$this->container['EM']->flush();
|
$this->container['EM']->flush();
|
||||||
|
|
||||||
@@ -121,6 +125,7 @@ class RegenerateSqliteDb extends Command
|
|||||||
$fixtures['token']['token_2'] = $DI['token_2']->getValue();
|
$fixtures['token']['token_2'] = $DI['token_2']->getValue();
|
||||||
$fixtures['token']['token_invalid'] = $DI['token_invalid']->getValue();
|
$fixtures['token']['token_invalid'] = $DI['token_invalid']->getValue();
|
||||||
$fixtures['token']['token_validation'] = $DI['token_validation']->getValue();
|
$fixtures['token']['token_validation'] = $DI['token_validation']->getValue();
|
||||||
|
|
||||||
$fixtures['user']['test_phpunit'] = $DI['user']->getId();
|
$fixtures['user']['test_phpunit'] = $DI['user']->getId();
|
||||||
$fixtures['user']['test_phpunit_not_admin'] = $DI['user_notAdmin']->getId();
|
$fixtures['user']['test_phpunit_not_admin'] = $DI['user_notAdmin']->getId();
|
||||||
$fixtures['user']['test_phpunit_alt1'] = $DI['user_alt1']->getId();
|
$fixtures['user']['test_phpunit_alt1'] = $DI['user_alt1']->getId();
|
||||||
@@ -133,6 +138,7 @@ class RegenerateSqliteDb extends Command
|
|||||||
$fixtures['oauth']['acc-user-not-admin'] = $DI['api-app-acc-user-not-admin']->getId();
|
$fixtures['oauth']['acc-user-not-admin'] = $DI['api-app-acc-user-not-admin']->getId();
|
||||||
|
|
||||||
$fixtures['databox']['records'] = $DI['databox']->get_sbas_id();
|
$fixtures['databox']['records'] = $DI['databox']->get_sbas_id();
|
||||||
|
|
||||||
$fixtures['collection']['coll'] = $DI['coll']->get_base_id();
|
$fixtures['collection']['coll'] = $DI['coll']->get_base_id();
|
||||||
$fixtures['collection']['coll_no_access'] = $DI['coll_no_access']->get_base_id();
|
$fixtures['collection']['coll_no_access'] = $DI['coll_no_access']->get_base_id();
|
||||||
$fixtures['collection']['coll_no_status'] = $DI['coll_no_status']->get_base_id();
|
$fixtures['collection']['coll_no_status'] = $DI['coll_no_status']->get_base_id();
|
||||||
@@ -170,6 +176,8 @@ class RegenerateSqliteDb extends Command
|
|||||||
$fixtures['feed']['private']['feed'] = $DI['feed_private']->getId();
|
$fixtures['feed']['private']['feed'] = $DI['feed_private']->getId();
|
||||||
$fixtures['feed']['private']['entry'] = $DI['feed_private_entry']->getId();
|
$fixtures['feed']['private']['entry'] = $DI['feed_private_entry']->getId();
|
||||||
$fixtures['feed']['private']['token'] = $DI['feed_private_token']->getId();
|
$fixtures['feed']['private']['token'] = $DI['feed_private_token']->getId();
|
||||||
|
|
||||||
|
$fixtures['webhook']['event'] = $DI['event_webhook_1']->getId();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$output->writeln("<error>".$e->getMessage()."</error>");
|
$output->writeln("<error>".$e->getMessage()."</error>");
|
||||||
if ($renamed) {
|
if ($renamed) {
|
||||||
@@ -329,6 +337,45 @@ class RegenerateSqliteDb extends Command
|
|||||||
return $this->container['manipulator.user']->createUser($login, uniqid('pass'), $email, $admin);
|
return $this->container['manipulator.user']->createUser($login, uniqid('pass'), $email, $admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function insertWebhookEvent(EntityManager $em, \Pimple $DI)
|
||||||
|
{
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setName(WebhookEvent::NEW_FEED_ENTRY);
|
||||||
|
$event->setType(WebhookEvent::FEED_ENTRY_TYPE);
|
||||||
|
$event->setData(array(
|
||||||
|
'feed_id' => $DI['feed_public_entry']->getFeed()->getId(),
|
||||||
|
'entry_id' => $DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$em->persist($event);
|
||||||
|
|
||||||
|
$DI['event_webhook_1'] = $event;
|
||||||
|
|
||||||
|
$event2 = new WebhookEvent();
|
||||||
|
$event2->setName(WebhookEvent::NEW_FEED_ENTRY);
|
||||||
|
$event2->setType(WebhookEvent::FEED_ENTRY_TYPE);
|
||||||
|
$event2->setData(array(
|
||||||
|
'feed_id' => $DI['feed_public_entry']->getFeed()->getId(),
|
||||||
|
'entry_id' => $DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$event2->setProcessed(true);
|
||||||
|
$em->persist($event2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function insertWebhookEventDelivery(EntityManager $em, \Pimple $DI)
|
||||||
|
{
|
||||||
|
$delivery = new WebhookEventDelivery();
|
||||||
|
$delivery->setThirdPartyApplication($DI['api-app-user']);
|
||||||
|
$delivery->setWebhookEvent($DI['event_webhook_1']);
|
||||||
|
$delivery->setDelivered(true);
|
||||||
|
$em->persist($delivery);
|
||||||
|
|
||||||
|
$delivery2 = new WebhookEventDelivery();
|
||||||
|
$delivery2->setThirdPartyApplication($DI['api-app-user-not-admin']);
|
||||||
|
$delivery2->setWebhookEvent($DI['event_webhook_1']);
|
||||||
|
$delivery2->setDeliverTries(1);
|
||||||
|
$em->persist($delivery2);
|
||||||
|
}
|
||||||
|
|
||||||
private function generateCollection(\Pimple $DI)
|
private function generateCollection(\Pimple $DI)
|
||||||
{
|
{
|
||||||
$coll = $collection_no_acces = $collection_no_acces_by_status = $db = null;
|
$coll = $collection_no_acces = $collection_no_acces_by_status = $db = null;
|
||||||
|
@@ -23,6 +23,8 @@ use Alchemy\Phrasea\Model\Manipulator\RegistrationManipulator;
|
|||||||
use Alchemy\Phrasea\Model\Manipulator\TaskManipulator;
|
use Alchemy\Phrasea\Model\Manipulator\TaskManipulator;
|
||||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\WebhookEventDeliveryManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\WebhookEventManipulator;
|
||||||
use Alchemy\Phrasea\Model\Manager\UserManager;
|
use Alchemy\Phrasea\Model\Manager\UserManager;
|
||||||
use Silex\Application as SilexApplication;
|
use Silex\Application as SilexApplication;
|
||||||
use Silex\ServiceProviderInterface;
|
use Silex\ServiceProviderInterface;
|
||||||
@@ -82,6 +84,14 @@ class ManipulatorServiceProvider implements ServiceProviderInterface
|
|||||||
$app['manipulator.api-log'] = $app->share(function ($app) {
|
$app['manipulator.api-log'] = $app->share(function ($app) {
|
||||||
return new ApiLogManipulator($app['EM'], $app['repo.api-logs']);
|
return new ApiLogManipulator($app['EM'], $app['repo.api-logs']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$app['manipulator.webhook-event'] = $app->share(function ($app) {
|
||||||
|
return new WebhookEventManipulator($app['EM'], $app['repo.webhook-event']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$app['manipulator.webhook-delivery'] = $app->share(function ($app) {
|
||||||
|
return new WebhookEventDeliveryManipulator($app['EM'], $app['repo.webhook-delivery']);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot(SilexApplication $app)
|
public function boot(SilexApplication $app)
|
||||||
|
@@ -115,6 +115,12 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
|
|||||||
$app['repo.api-oauth-refresh-tokens'] = $app->share(function (PhraseaApplication $app) {
|
$app['repo.api-oauth-refresh-tokens'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return $app['EM']->getRepository('Phraseanet:ApiOauthRefreshToken');
|
return $app['EM']->getRepository('Phraseanet:ApiOauthRefreshToken');
|
||||||
});
|
});
|
||||||
|
$app['repo.webhook-event'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return $app['EM']->getRepository('Phraseanet:WebhookEvent');
|
||||||
|
});
|
||||||
|
$app['repo.webhook-delivery'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return $app['EM']->getRepository('Phraseanet:WebhookEventDelivery');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot(Application $app)
|
public function boot(Application $app)
|
||||||
|
@@ -18,12 +18,14 @@ use Alchemy\Phrasea\TaskManager\Job\FtpPullJob;
|
|||||||
use Alchemy\Phrasea\TaskManager\Job\PhraseanetIndexerJob;
|
use Alchemy\Phrasea\TaskManager\Job\PhraseanetIndexerJob;
|
||||||
use Alchemy\Phrasea\TaskManager\Job\RecordMoverJob;
|
use Alchemy\Phrasea\TaskManager\Job\RecordMoverJob;
|
||||||
use Alchemy\Phrasea\TaskManager\Job\SubdefsJob;
|
use Alchemy\Phrasea\TaskManager\Job\SubdefsJob;
|
||||||
|
use Alchemy\Phrasea\TaskManager\Job\WebhookJob;
|
||||||
use Alchemy\Phrasea\TaskManager\Job\WriteMetadataJob;
|
use Alchemy\Phrasea\TaskManager\Job\WriteMetadataJob;
|
||||||
use Alchemy\Phrasea\TaskManager\Job\Factory as JobFactory;
|
use Alchemy\Phrasea\TaskManager\Job\Factory as JobFactory;
|
||||||
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
||||||
use Alchemy\Phrasea\TaskManager\TaskManagerStatus;
|
use Alchemy\Phrasea\TaskManager\TaskManagerStatus;
|
||||||
use Alchemy\Phrasea\TaskManager\Log\LogFileFactory;
|
use Alchemy\Phrasea\TaskManager\Log\LogFileFactory;
|
||||||
use Alchemy\Phrasea\TaskManager\Notifier;
|
use Alchemy\Phrasea\TaskManager\Notifier;
|
||||||
|
use Alchemy\Phrasea\Webhook\EventProcessorFactory;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Silex\ServiceProviderInterface;
|
use Silex\ServiceProviderInterface;
|
||||||
|
|
||||||
@@ -76,6 +78,7 @@ class TasksServiceProvider implements ServiceProviderInterface
|
|||||||
new RecordMoverJob($app['dispatcher'], $logger, $app['translator']),
|
new RecordMoverJob($app['dispatcher'], $logger, $app['translator']),
|
||||||
new SubdefsJob($app['dispatcher'], $logger, $app['translator']),
|
new SubdefsJob($app['dispatcher'], $logger, $app['translator']),
|
||||||
new WriteMetadataJob($app['dispatcher'], $logger, $app['translator']),
|
new WriteMetadataJob($app['dispatcher'], $logger, $app['translator']),
|
||||||
|
new WebhookJob($app['dispatcher'], $logger, $app['translator']),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -127,7 +127,7 @@ class ApiApplication
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="webhook_url", type="string", length=128)
|
* @ORM\Column(name="webhook_url", type="string", length=128, nullable=true)
|
||||||
*/
|
*/
|
||||||
private $webhookUrl;
|
private $webhookUrl;
|
||||||
|
|
||||||
|
180
lib/Alchemy/Phrasea/Model/Entities/WebhookEvent.php
Normal file
180
lib/Alchemy/Phrasea/Model/Entities/WebhookEvent.php
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Entities;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Gedmo\Mapping\Annotation as Gedmo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Table(name="WebhookEvents", indexes={@ORM\Index(name="name", columns={"name"})})
|
||||||
|
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\WebhookEventRepository")
|
||||||
|
*/
|
||||||
|
class WebhookEvent
|
||||||
|
{
|
||||||
|
const NEW_FEED_ENTRY = 'new_feed_entry';
|
||||||
|
const FEED_ENTRY_TYPE = 'feed_entry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=64, nullable=false)
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=64, nullable=false)
|
||||||
|
*/
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="json_array", nullable=false)
|
||||||
|
*/
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="boolean", nullable=false)
|
||||||
|
*/
|
||||||
|
private $processed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Gedmo\Timestampable(on="create")
|
||||||
|
* @ORM\Column(type="datetime")
|
||||||
|
*/
|
||||||
|
private $created;
|
||||||
|
|
||||||
|
public static function types()
|
||||||
|
{
|
||||||
|
return array(self::FEED_ENTRY_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function events()
|
||||||
|
{
|
||||||
|
return array(self::NEW_FEED_ENTRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTime $created
|
||||||
|
*
|
||||||
|
* @return WebhookEvent
|
||||||
|
*/
|
||||||
|
public function setCreated(\DateTime $created)
|
||||||
|
{
|
||||||
|
$this->created = $created;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return WebhookEvent
|
||||||
|
*/
|
||||||
|
public function setData(array $data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return WebhookEvent
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
if (!in_array($name, self::events())) {
|
||||||
|
throw new \InvalidArgumentException("Invalid event name");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $processed
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setProcessed($processed)
|
||||||
|
{
|
||||||
|
$this->processed = (Boolean) $processed;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isProcessed()
|
||||||
|
{
|
||||||
|
return $this->processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $type
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
if (!in_array($type, self::types())) {
|
||||||
|
throw new \InvalidArgumentException("Invalid event name");
|
||||||
|
}
|
||||||
|
$this->type = $type;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
166
lib/Alchemy/Phrasea/Model/Entities/WebhookEventDelivery.php
Normal file
166
lib/Alchemy/Phrasea/Model/Entities/WebhookEventDelivery.php
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Entities;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Gedmo\Mapping\Annotation as Gedmo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Table(name="WebhookEventDeliveries",
|
||||||
|
* uniqueConstraints={
|
||||||
|
* @ORM\UniqueConstraint(name="unique_app_delivery",columns={"application_id", "event_id"})
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\WebhookEventDeliveryRepository")
|
||||||
|
*/
|
||||||
|
class WebhookEventDelivery
|
||||||
|
{
|
||||||
|
const MAX_DELIVERY_TRIES = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity="ApiApplication")
|
||||||
|
* @ORM\JoinColumn(name="application_id", referencedColumnName="id", nullable=false)
|
||||||
|
*
|
||||||
|
* @return ApiApplication
|
||||||
|
**/
|
||||||
|
private $application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity="WebhookEvent")
|
||||||
|
* @ORM\JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
|
||||||
|
*
|
||||||
|
* @return WebhookEvent
|
||||||
|
**/
|
||||||
|
private $event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="boolean", nullable=false)
|
||||||
|
*/
|
||||||
|
private $delivered = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer", nullable=false)
|
||||||
|
*/
|
||||||
|
private $deliveryTries = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Gedmo\Timestampable(on="create")
|
||||||
|
* @ORM\Column(type="datetime")
|
||||||
|
*/
|
||||||
|
private $created;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTime $created
|
||||||
|
*
|
||||||
|
* @return WebhookEvent
|
||||||
|
*/
|
||||||
|
public function setCreated(\DateTime $created)
|
||||||
|
{
|
||||||
|
$this->created = $created;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $delivered
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDelivered($delivered)
|
||||||
|
{
|
||||||
|
$this->delivered = (Boolean) $delivered;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public function isDelivered()
|
||||||
|
{
|
||||||
|
return $this->delivered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getDeliveryTries()
|
||||||
|
{
|
||||||
|
return $this->deliveryTries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param integer $try
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDeliverTries($try)
|
||||||
|
{
|
||||||
|
$this->deliveryTries = (int) $try;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ApiApplication
|
||||||
|
*/
|
||||||
|
public function getThirdPartyApplication()
|
||||||
|
{
|
||||||
|
return $this->application;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ApiApplication $application
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setThirdPartyApplication(ApiApplication $application)
|
||||||
|
{
|
||||||
|
$this->application = $application;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebhookEvent $event
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setWebhookEvent(WebhookEvent $event)
|
||||||
|
{
|
||||||
|
$this->event = $event;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return WebhookEvent
|
||||||
|
*/
|
||||||
|
public function getWebhookEvent()
|
||||||
|
{
|
||||||
|
return $this->event;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Manipulator;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application;
|
||||||
|
use Alchemy\Phrasea\Authentication\ACLProvider;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiAccount;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiLog;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\User;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class WebhookEventDeliveryManipulator implements ManipulatorInterface
|
||||||
|
{
|
||||||
|
private $om;
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
public function __construct(ObjectManager $om, EntityRepository $repo)
|
||||||
|
{
|
||||||
|
$this->om = $om;
|
||||||
|
$this->repository = $repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(ApiApplication $application, WebhookEvent $event)
|
||||||
|
{
|
||||||
|
$delivery = new WebhookEventDelivery();
|
||||||
|
$delivery->setThirdPartyApplication($application);
|
||||||
|
$delivery->setWebhookEvent($event);
|
||||||
|
|
||||||
|
$this->update($delivery);
|
||||||
|
|
||||||
|
return $delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(WebhookEventDelivery $delivery)
|
||||||
|
{
|
||||||
|
$this->om->remove($delivery);
|
||||||
|
$this->om->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(WebhookEventDelivery $delivery)
|
||||||
|
{
|
||||||
|
$this->om->persist($delivery);
|
||||||
|
$this->om->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deliverySuccess(WebhookEventDelivery $delivery)
|
||||||
|
{
|
||||||
|
$delivery->setDelivered(true);
|
||||||
|
$delivery->setDeliverTries($delivery->getDeliveryTries() + 1);
|
||||||
|
$this->update($delivery);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deliveryFailure(WebhookEventDelivery $delivery)
|
||||||
|
{
|
||||||
|
$delivery->setDelivered(false);
|
||||||
|
$delivery->setDeliverTries($delivery->getDeliveryTries() + 1);
|
||||||
|
$this->update($delivery);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Manipulator;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application;
|
||||||
|
use Alchemy\Phrasea\Authentication\ACLProvider;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiAccount;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiLog;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\User;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class WebhookEventManipulator implements ManipulatorInterface
|
||||||
|
{
|
||||||
|
private $om;
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
public function __construct(ObjectManager $om, EntityRepository $repo)
|
||||||
|
{
|
||||||
|
$this->om = $om;
|
||||||
|
$this->repository = $repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create($eventName, $type, array $data)
|
||||||
|
{
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setName($eventName);
|
||||||
|
$event->setType($type);
|
||||||
|
$event->setData($data);
|
||||||
|
|
||||||
|
$this->update($event);
|
||||||
|
|
||||||
|
return $event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(WebhookEvent $event)
|
||||||
|
{
|
||||||
|
$this->om->remove($event);
|
||||||
|
$this->om->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(WebhookEvent $event)
|
||||||
|
{
|
||||||
|
$this->om->persist($event);
|
||||||
|
$this->om->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processed(WebhookEvent $event)
|
||||||
|
{
|
||||||
|
$event->setProcessed(true);
|
||||||
|
$this->update($event);
|
||||||
|
}
|
||||||
|
}
|
@@ -50,4 +50,12 @@ class ApiApplicationRepository extends EntityRepository
|
|||||||
|
|
||||||
return $qb->getQuery()->getResult();
|
return $qb->getQuery()->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findWithDefinedWebhookCallback()
|
||||||
|
{
|
||||||
|
$qb = $this->createQueryBuilder('app');
|
||||||
|
$qb->where($qb->expr()->isNotNull('app.webhookUrl'));
|
||||||
|
|
||||||
|
return $qb->getQuery()->getResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Repositories;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebhookEventDeliveryRepository
|
||||||
|
*
|
||||||
|
* This class was generated by the Doctrine ORM. Add your own custom
|
||||||
|
* repository methods below.
|
||||||
|
*/
|
||||||
|
class WebhookEventDeliveryRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
public function findUndeliveredEvents()
|
||||||
|
{
|
||||||
|
$qb = $this->createQueryBuilder('e');
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->where($qb->expr()->eq('e.delivered', $qb->expr()->literal(false)))
|
||||||
|
->andWhere($qb->expr()->lt('e.deliveryTries', ':nb_tries'));
|
||||||
|
|
||||||
|
$qb->setParameter(':nb_tries', WebhookEventDelivery::MAX_DELIVERY_TRIES);
|
||||||
|
|
||||||
|
return $qb->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Repositories;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebhookEventRepository
|
||||||
|
*
|
||||||
|
* This class was generated by the Doctrine ORM. Add your own custom
|
||||||
|
* repository methods below.
|
||||||
|
*/
|
||||||
|
class WebhookEventRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
public function findUnprocessedEvents()
|
||||||
|
{
|
||||||
|
$qb = $this->createQueryBuilder('e');
|
||||||
|
|
||||||
|
$qb->where($qb->expr()->eq('e.processed', $qb->expr()->literal(false)));
|
||||||
|
|
||||||
|
return $qb->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
}
|
168
lib/Alchemy/Phrasea/TaskManager/Job/WebhookJob.php
Normal file
168
lib/Alchemy/Phrasea/TaskManager/Job/WebhookJob.php
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\TaskManager\Job;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Core\Version;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||||
|
use Alchemy\Phrasea\TaskManager\Editor\DefaultEditor;
|
||||||
|
use Alchemy\Phrasea\Webhook\EventProcessorFactory;
|
||||||
|
use Guzzle\Http\Client as GuzzleClient;
|
||||||
|
use Guzzle\Batch\BatchBuilder;
|
||||||
|
use Silex\Application;
|
||||||
|
use Guzzle\Common\Event;
|
||||||
|
use Guzzle\Plugin\Backoff\BackoffPlugin;
|
||||||
|
use Guzzle\Plugin\Backoff\TruncatedBackoffStrategy;
|
||||||
|
use Guzzle\Plugin\Backoff\CallbackBackoffStrategy;
|
||||||
|
use Guzzle\Plugin\Backoff\CurlBackoffStrategy;
|
||||||
|
use Guzzle\Plugin\Backoff\ExponentialBackoffStrategy;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
|
use Guzzle\Http\Exception\MultiTransferException;
|
||||||
|
|
||||||
|
class WebhookJob extends AbstractJob
|
||||||
|
{
|
||||||
|
private $httpClient;
|
||||||
|
|
||||||
|
public function __construct(EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null, TranslatorInterface $translator, GuzzleClient $httpClient = null)
|
||||||
|
{
|
||||||
|
parent::__construct($dispatcher, $logger, $translator);
|
||||||
|
|
||||||
|
$this->httpClient = $httpClient ?: new GuzzleClient();
|
||||||
|
$this->httpClient->setUserAgent(sprintf('Phraseanet/%s (%s)', Version::getNumber(), Version::getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->translator->trans("API Webhook");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getJobId()
|
||||||
|
{
|
||||||
|
return 'Webhook';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return $this->translator->trans("Notify third party application when an event occurs in Phraseanet");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getEditor()
|
||||||
|
{
|
||||||
|
return new DefaultEditor($this->translator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function doJob(JobData $data)
|
||||||
|
{
|
||||||
|
$app = $data->getApplication();
|
||||||
|
$thirdPartyApplications = $app['repo.api-applications']->findWithDefinedWebhookCallback();
|
||||||
|
$that = $this;
|
||||||
|
|
||||||
|
$this->httpClient->getEventDispatcher()->addListener('request.error', function (Event $event) {
|
||||||
|
// override guzzle default behavior of throwing exceptions
|
||||||
|
// when 4xx & 5xx responses are encountered
|
||||||
|
$event->stopPropagation();
|
||||||
|
}, -254);
|
||||||
|
|
||||||
|
$this->httpClient->addSubscriber(new BackoffPlugin(
|
||||||
|
// set max retries
|
||||||
|
new TruncatedBackoffStrategy(WebhookEventDelivery::MAX_DELIVERY_TRIES,
|
||||||
|
// set callback which logs success or failure
|
||||||
|
new CallbackBackoffStrategy(function($retries, $request, $response, $e) use ($app, $that) {
|
||||||
|
$retry = true;
|
||||||
|
if ($response && (null !== $deliverId = parse_url($request->getUrl(), PHP_URL_FRAGMENT))) {
|
||||||
|
$delivery = $app['repo.webhook-delivery']->find($deliverId);
|
||||||
|
if ($response->isSuccessful()) {
|
||||||
|
$app['manipulator.webhook-delivery']->deliverySuccess($delivery);
|
||||||
|
|
||||||
|
$that->log('info', sprintf('Deliver success event "%d:%s" for app "%s"', $delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(), $delivery->getThirdPartyApplication()->getName()));
|
||||||
|
$retry = false;
|
||||||
|
} else {
|
||||||
|
$app['manipulator.webhook-delivery']->deliveryFailure($delivery);
|
||||||
|
|
||||||
|
$that->log('error', sprintf('Deliver failure event "%d:%s" for app "%s"', $delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(), $delivery->getThirdPartyApplication()->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $retry;
|
||||||
|
}},
|
||||||
|
true,
|
||||||
|
new CurlBackoffStrategy()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
foreach ($app['repo.webhook-event']->findUnprocessedEvents() as $event) {
|
||||||
|
// set event as processed
|
||||||
|
$app['manipulator.webhook-event']->processed($event);
|
||||||
|
|
||||||
|
$this->log('info', sprintf('Processing event "%s" with id %d', $event->getName(), $event->getId()));
|
||||||
|
|
||||||
|
// send requests
|
||||||
|
$this->deliverEvent($app, $thirdPartyApplications, $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deliverEvent(Application $app, array $thirdPartyApplications, WebhookEvent $event)
|
||||||
|
{
|
||||||
|
if (count($thirdPartyApplications) === 0) {
|
||||||
|
$this->log('info', sprintf('No applications defined to listen for webhook events'));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format event data
|
||||||
|
$eventFactory = new EventProcessorFactory($app);
|
||||||
|
$eventProcessor = $eventFactory->get($event);
|
||||||
|
$data = $eventProcessor->process();
|
||||||
|
|
||||||
|
// batch requests
|
||||||
|
$batch = BatchBuilder::factory()
|
||||||
|
->transferRequests(10)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
foreach ($thirdPartyApplications as $thirdPartyApplication) {
|
||||||
|
$delivery = $app['manipulator.webhook-delivery']->create($thirdPartyApplication, $event);
|
||||||
|
|
||||||
|
// append delivery id as url anchor
|
||||||
|
$uniqueUrl = $this->getUrl($thirdPartyApplication, $delivery);
|
||||||
|
|
||||||
|
// create http request with data as request body
|
||||||
|
$batch->add($this->httpClient->createRequest('POST', $uniqueUrl, array(
|
||||||
|
'Content-Type' => 'application/vnd.phraseanet.event+json'
|
||||||
|
), json_encode($data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$batch->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUrl(ApiApplication $application, WebhookEventDelivery $delivery)
|
||||||
|
{
|
||||||
|
return sprintf('%s#%s', $application->getWebhookUrl(), $delivery->getId());
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
use Alchemy\Phrasea\Notification\Receiver;
|
use Alchemy\Phrasea\Notification\Receiver;
|
||||||
use Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication;
|
use Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
|
||||||
class eventsmanager_notify_feed extends eventsmanager_notifyAbstract
|
class eventsmanager_notify_feed extends eventsmanager_notifyAbstract
|
||||||
{
|
{
|
||||||
@@ -59,9 +60,11 @@ class eventsmanager_notify_feed extends eventsmanager_notifyAbstract
|
|||||||
|
|
||||||
$data = $dom_xml->saveXml();
|
$data = $dom_xml->saveXml();
|
||||||
|
|
||||||
API_Webhook::create($this->app['phraseanet.appbox'], API_Webhook::NEW_FEED_ENTRY, array_merge(
|
$this->app['manipulator.webhook-event']->create(
|
||||||
array('feed_id' => $entry->getFeed()->getId()), $params
|
WebhookEvent::NEW_FEED_ENTRY,
|
||||||
));
|
WebhookEvent::FEED_ENTRY_TYPE,
|
||||||
|
array_merge(array('feed_id' => $entry->getFeed()->getId()), $params)
|
||||||
|
);
|
||||||
|
|
||||||
$Query = new \User_Query($this->app);
|
$Query = new \User_Query($this->app);
|
||||||
|
|
||||||
|
@@ -1,144 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Phraseanet
|
|
||||||
*
|
|
||||||
* (c) 2005-2014 Alchemy
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Guzzle\Http\Client as GuzzleClient;
|
|
||||||
|
|
||||||
class task_period_apiwebhooks extends task_appboxAbstract
|
|
||||||
{
|
|
||||||
public static function getName()
|
|
||||||
{
|
|
||||||
return _('Api Webhook');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function help()
|
|
||||||
{
|
|
||||||
return _('Notify Phraseanet Oauth2 client applications using webhooks.');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function retrieveContent(appbox $appbox)
|
|
||||||
{
|
|
||||||
$stmt = $appbox->get_connection()->prepare('SELECT id, `type`, `data` FROM api_webhooks');
|
|
||||||
$stmt->execute();
|
|
||||||
$rs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
|
||||||
$stmt->closeCursor();
|
|
||||||
|
|
||||||
return $rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function processOneContent(appbox $appbox, array $row)
|
|
||||||
{
|
|
||||||
$data = null;
|
|
||||||
switch ($row['type']) {
|
|
||||||
case \API_Webhook::NEW_FEED_ENTRY:
|
|
||||||
$data = $this->processNewFeedEntry($row);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$urls = $this->getApplicationHookUrls($appbox);
|
|
||||||
$this->sendData($urls, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function postProcessOneContent(appbox $appbox, array $row)
|
|
||||||
{
|
|
||||||
$w = new API_Webhook($appbox, $row['id']);
|
|
||||||
$w->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getApplicationHookUrls(appbox $appbox)
|
|
||||||
{
|
|
||||||
$stmt = $appbox->get_connection()->prepare('
|
|
||||||
SELECT webhook_url
|
|
||||||
FROM api_applications
|
|
||||||
WHERE webhook_url IS NOT NULL
|
|
||||||
');
|
|
||||||
$stmt->execute();
|
|
||||||
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
|
||||||
$stmt->closeCursor();
|
|
||||||
|
|
||||||
return array_map(function ($row) {
|
|
||||||
return $row['webhook_url'];
|
|
||||||
}, $rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function sendData(array $urls, array $data)
|
|
||||||
{
|
|
||||||
if (count($urls) === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$client = new GuzzleClient();
|
|
||||||
$body = json_encode($data);
|
|
||||||
$requests = array();
|
|
||||||
foreach ($urls as $url) {
|
|
||||||
$requests[] = $client->createRequest('POST', $url, array(
|
|
||||||
'Content-Type' => 'application/vnd.phraseanet.event+json'
|
|
||||||
), $body);
|
|
||||||
}
|
|
||||||
$client->send($requests);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function processNewFeedEntry(array $row)
|
|
||||||
{
|
|
||||||
$data = json_decode($row['data']);
|
|
||||||
if (!isset($data->{"feed_id"}) || !isset($data->{"entry_id"})) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$feed = new Feed_Adapter($this->dependencyContainer, $data->{"feed_id"});
|
|
||||||
$entry = new \Feed_Entry_Adapter($this->dependencyContainer, $feed, $data->{"entry_id"});
|
|
||||||
$query = new \User_Query($this->dependencyContainer);
|
|
||||||
|
|
||||||
$query->include_phantoms(true)
|
|
||||||
->include_invite(false)
|
|
||||||
->include_templates(false)
|
|
||||||
->email_not_null(true);
|
|
||||||
|
|
||||||
if ($entry->get_feed()->get_collection()) {
|
|
||||||
$query->on_base_ids(array($entry->get_feed()->get_collection()->get_base_id()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = 0;
|
|
||||||
$perLoop = 100;
|
|
||||||
$users = array();
|
|
||||||
|
|
||||||
do {
|
|
||||||
$results = $query->limit($start, $perLoop)->execute()->get_results();
|
|
||||||
foreach ($results as $user) {
|
|
||||||
$users[] = array(
|
|
||||||
'email' => $user->get_email(),
|
|
||||||
'firstname' => $user->get_firstname() ?: null,
|
|
||||||
'lastname' => $user->get_lastname() ?: null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$start += $perLoop;
|
|
||||||
} while (count($results) > 0);
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'event' => $row['type'],
|
|
||||||
'users_were_notified' => !!$data->{"notify_email"},
|
|
||||||
'feed' => array(
|
|
||||||
'id' => $feed->get_id(),
|
|
||||||
'title' => $feed->get_title(),
|
|
||||||
'description' => $feed->get_subtitle() ?: null,
|
|
||||||
),
|
|
||||||
'entry' => array(
|
|
||||||
'id' => $entry->get_id(),
|
|
||||||
'author' => array(
|
|
||||||
'name' => $entry->get_author_name(),
|
|
||||||
'email' => $entry->get_author_email()
|
|
||||||
),
|
|
||||||
'title' => $entry->get_title(),
|
|
||||||
'description' => $entry->get_subtitle() ?: null,
|
|
||||||
),
|
|
||||||
'users' => $users
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -76,53 +76,6 @@
|
|||||||
</indexes>
|
</indexes>
|
||||||
<engine>InnoDB</engine>
|
<engine>InnoDB</engine>
|
||||||
</table>
|
</table>
|
||||||
<table name="api_webhooks">
|
|
||||||
<fields>
|
|
||||||
<field>
|
|
||||||
<name>id</name>
|
|
||||||
<type>int(11) unsigned</type>
|
|
||||||
<null></null>
|
|
||||||
<extra>auto_increment</extra>
|
|
||||||
<default></default>
|
|
||||||
<comment></comment>
|
|
||||||
</field>
|
|
||||||
<field>
|
|
||||||
<name>type</name>
|
|
||||||
<type>varchar(64)</type>
|
|
||||||
<null></null>
|
|
||||||
<extra></extra>
|
|
||||||
<default></default>
|
|
||||||
<comment></comment>
|
|
||||||
</field>
|
|
||||||
<field>
|
|
||||||
<name>data</name>
|
|
||||||
<type>longtext</type>
|
|
||||||
<null></null>
|
|
||||||
<extra></extra>
|
|
||||||
<default></default>
|
|
||||||
<comment></comment>
|
|
||||||
</field>
|
|
||||||
<field>
|
|
||||||
<name>created</name>
|
|
||||||
<type>datetime</type>
|
|
||||||
<null></null>
|
|
||||||
<extra></extra>
|
|
||||||
<default></default>
|
|
||||||
<comment></comment>
|
|
||||||
</field>
|
|
||||||
</fields>
|
|
||||||
<indexes>
|
|
||||||
<index>
|
|
||||||
<name>PRIMARY</name>
|
|
||||||
<type>PRIMARY</type>
|
|
||||||
<fields>
|
|
||||||
<field>id</field>
|
|
||||||
</fields>
|
|
||||||
</index>
|
|
||||||
</indexes>
|
|
||||||
<engine>InnoDB</engine>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<table name="bridge_accounts">
|
<table name="bridge_accounts">
|
||||||
<fields>
|
<fields>
|
||||||
<field>
|
<field>
|
||||||
|
@@ -57,6 +57,16 @@ class ManipulatorServiceProviderTest extends ServiceProviderTestCase
|
|||||||
'manipulator.api-oauth-refresh-token',
|
'manipulator.api-oauth-refresh-token',
|
||||||
'Alchemy\Phrasea\Model\Manipulator\ApiOauthRefreshTokenManipulator'
|
'Alchemy\Phrasea\Model\Manipulator\ApiOauthRefreshTokenManipulator'
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'Alchemy\Phrasea\Core\Provider\ManipulatorServiceProvider',
|
||||||
|
'manipulator.webhook-event',
|
||||||
|
'Alchemy\Phrasea\Model\Manipulator\WebhookEventManipulator'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Alchemy\Phrasea\Core\Provider\ManipulatorServiceProvider',
|
||||||
|
'manipulator.webhook-delivery',
|
||||||
|
'Alchemy\Phrasea\Model\Manipulator\WebhookEventDelivery'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,6 +39,8 @@ class RepositoriesServiceProviderTest extends ServiceProviderTestCase
|
|||||||
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-tokens', 'Alchemy\Phrasea\Model\Repositories\ApiOauthTokenRepository'],
|
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-tokens', 'Alchemy\Phrasea\Model\Repositories\ApiOauthTokenRepository'],
|
||||||
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-codes', 'Alchemy\Phrasea\Model\Repositories\ApiOauthCodeRepository'],
|
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-codes', 'Alchemy\Phrasea\Model\Repositories\ApiOauthCodeRepository'],
|
||||||
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-refresh-tokens', 'Alchemy\Phrasea\Model\Repositories\ApiOauthRefreshTokenRepository'],
|
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.api-oauth-refresh-tokens', 'Alchemy\Phrasea\Model\Repositories\ApiOauthRefreshTokenRepository'],
|
||||||
|
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.webhook-event', 'Alchemy\Phrasea\Model\Repositories\WebhookEventRepository'],
|
||||||
|
['Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider', 'repo.webhook-delivery', 'Alchemy\Phrasea\Model\Repositories\WebhookEventDeliveryRepository'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Model\Manipulator;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V1;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\WebhookEventDeliveryManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\ApiApplicationManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||||
|
|
||||||
|
class WebhookEventDeliveryManipulatorTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
public function testCreate()
|
||||||
|
{
|
||||||
|
$manipApp = new ApiApplicationManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.api-applications'], self::$DI['app']['random.medium']);
|
||||||
|
$application = $manipApp->create(
|
||||||
|
uniqid('app'),
|
||||||
|
ApiApplication::WEB_TYPE,
|
||||||
|
'Desktop application description',
|
||||||
|
'http://web-app-url.net',
|
||||||
|
self::$DI['user'],
|
||||||
|
'http://web-app-url.net/callback'
|
||||||
|
);
|
||||||
|
|
||||||
|
$manipulator = new WebhookEventDeliveryManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-delivery']);
|
||||||
|
$nbHooks = count(self::$DI['app']['repo.webhook-delivery']->findAll());
|
||||||
|
$manipulator->create($application, self::$DI['webhook-event']);
|
||||||
|
$this->assertGreaterThan($nbHooks, count(self::$DI['app']['repo.webhook-delivery']->findAll()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDelete()
|
||||||
|
{
|
||||||
|
$manipApp = new ApiApplicationManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.api-applications'], self::$DI['app']['random.medium']);
|
||||||
|
$application = $manipApp->create(
|
||||||
|
uniqid('app'),
|
||||||
|
ApiApplication::WEB_TYPE,
|
||||||
|
'Desktop application description',
|
||||||
|
'http://web-app-url.net',
|
||||||
|
self::$DI['user'],
|
||||||
|
'http://web-app-url.net/callback'
|
||||||
|
);
|
||||||
|
$manipulator = new WebhookEventDeliveryManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-delivery']);
|
||||||
|
$eventDelivery = $manipulator->create($application, self::$DI['webhook-event']);
|
||||||
|
$countBefore = count(self::$DI['app']['repo.webhook-delivery']->findAll());
|
||||||
|
$manipulator->delete($eventDelivery);
|
||||||
|
$this->assertGreaterThan(count(self::$DI['app']['repo.webhook-delivery']->findAll()), $countBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdate()
|
||||||
|
{
|
||||||
|
$manipApp = new ApiApplicationManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.api-applications'], self::$DI['app']['random.medium']);
|
||||||
|
$application = $manipApp->create(
|
||||||
|
uniqid('app'),
|
||||||
|
ApiApplication::WEB_TYPE,
|
||||||
|
'Desktop application description',
|
||||||
|
'http://web-app-url.net',
|
||||||
|
self::$DI['user'],
|
||||||
|
'http://web-app-url.net/callback'
|
||||||
|
);
|
||||||
|
$manipulator = new WebhookEventDeliveryManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-delivery']);
|
||||||
|
$eventDelivery = $manipulator->create($application, self::$DI['webhook-event']);
|
||||||
|
$this->assertEquals(0, $eventDelivery->getDeliveryTries());
|
||||||
|
$eventDelivery->setDeliverTries(1);
|
||||||
|
$manipulator->update($eventDelivery);
|
||||||
|
$eventDelivery = self::$DI['app']['repo.webhook-delivery']->find($eventDelivery->getId());
|
||||||
|
$this->assertEquals(1, $eventDelivery->getDeliveryTries());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeliverySuccess()
|
||||||
|
{
|
||||||
|
$manipApp = new ApiApplicationManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.api-applications'], self::$DI['app']['random.medium']);
|
||||||
|
$application = $manipApp->create(
|
||||||
|
uniqid('app'),
|
||||||
|
ApiApplication::WEB_TYPE,
|
||||||
|
'Desktop application description',
|
||||||
|
'http://web-app-url.net',
|
||||||
|
self::$DI['user'],
|
||||||
|
'http://web-app-url.net/callback'
|
||||||
|
);
|
||||||
|
$manipulator = new WebhookEventDeliveryManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-delivery']);
|
||||||
|
$eventDelivery = $manipulator->create($application, self::$DI['webhook-event']);
|
||||||
|
$tries = $eventDelivery->getDeliveryTries();
|
||||||
|
$manipulator->deliverySuccess($eventDelivery);
|
||||||
|
$this->assertTrue($eventDelivery->isDelivered());
|
||||||
|
$this->assertGreaterThan($tries, $eventDelivery->getDeliveryTries());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeliveryFailure()
|
||||||
|
{
|
||||||
|
$manipApp = new ApiApplicationManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.api-applications'], self::$DI['app']['random.medium']);
|
||||||
|
$application = $manipApp->create(
|
||||||
|
uniqid('app'),
|
||||||
|
ApiApplication::WEB_TYPE,
|
||||||
|
'Desktop application description',
|
||||||
|
'http://web-app-url.net',
|
||||||
|
self::$DI['user'],
|
||||||
|
'http://web-app-url.net/callback'
|
||||||
|
);
|
||||||
|
$manipulator = new WebhookEventDeliveryManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-delivery']);
|
||||||
|
$eventDelivery = $manipulator->create($application, self::$DI['webhook-event']);
|
||||||
|
$tries = $eventDelivery->getDeliveryTries();
|
||||||
|
$manipulator->deliveryFailure($eventDelivery);
|
||||||
|
$this->assertfalse($eventDelivery->isDelivered());
|
||||||
|
$this->assertGreaterThan($tries, $eventDelivery->getDeliveryTries());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Model\Manipulator;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\WebhookEventManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
|
||||||
|
class WebhookEventManipulatorTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
public function testCreate()
|
||||||
|
{
|
||||||
|
$manipulator = new WebhookEventManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.manipulator.webhook-delivery']);
|
||||||
|
$nbEvents = count(self::$DI['app']['repo.webhook-event']->findAll());
|
||||||
|
$event = $manipulator->create(WebhookEvent::NEW_FEED_ENTRY, WebhookEvent::FEED_ENTRY_TYPE, array(
|
||||||
|
'feed_id' => self::$DI['feed_public_entry']->getFeed()->getId(), 'entry_id' => self::$DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$this->assertGreaterThan($nbEvents, count(self::$DI['app']['repo.webhook-event']->findAll()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDelete()
|
||||||
|
{
|
||||||
|
$manipulator = new WebhookEventManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-event']);
|
||||||
|
$event = $manipulator->create(WebhookEvent::NEW_FEED_ENTRY, WebhookEvent::FEED_ENTRY_TYPE, array(
|
||||||
|
'feed_id' => self::$DI['feed_public_entry']->getFeed()->getId(), 'entry_id' => self::$DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$eventMem = clone $event;
|
||||||
|
$countBefore = count(self::$DI['app']['repo.webhook-event']->findAll());
|
||||||
|
self::$DI['app']['manipulator.webhook-delivery']->create($event);
|
||||||
|
$manipulator->delete($event);
|
||||||
|
$this->assertGreaterThan(count(self::$DI['app']['repo.webhook-event']->findAll()), $countBefore);
|
||||||
|
$tokens = self::$DI['app']['repo.api-oauth-tokens']->findOauthTokens($eventMem);
|
||||||
|
$this->assertEquals(0, count($tokens));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdate()
|
||||||
|
{
|
||||||
|
$manipulator = new WebhookEventManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-event']);
|
||||||
|
$event = $manipulator->create(WebhookEvent::NEW_FEED_ENTRY, WebhookEvent::FEED_ENTRY_TYPE, array(
|
||||||
|
'feed_id' => self::$DI['feed_public_entry']->getFeed()->getId(), 'entry_id' => self::$DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$event->setProcessed(true);
|
||||||
|
$manipulator->update($event);
|
||||||
|
$event = self::$DI['app']['repo.webhook-event']->find($event->getId());
|
||||||
|
$this->assertTrue($event->isProcessed());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessed()
|
||||||
|
{
|
||||||
|
$manipulator = new WebhookEventManipulator(self::$DI['app']['EM'], self::$DI['app']['repo.webhook-event']);
|
||||||
|
$event = $manipulator->create(WebhookEvent::NEW_FEED_ENTRY, WebhookEvent::FEED_ENTRY_TYPE, array(
|
||||||
|
'feed_id' => self::$DI['feed_public_entry']->getFeed()->getId(), 'entry_id' => self::$DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$manipulator->processed($event);
|
||||||
|
$this->assertTrue($event->isProcessed());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Model\Repositories;
|
||||||
|
|
||||||
|
class WebhookEventDeliveryRepositoryTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
public function testFindUndeliveredEvents()
|
||||||
|
{
|
||||||
|
$events = self::$DI['app']['EM']->getRepository('Phraseanet:WebhookEventDelivery')->findUndeliveredEvents();
|
||||||
|
$this->assertCount(1, $events);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Model\Repositories;
|
||||||
|
|
||||||
|
class WebhookEventRepositoryTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
public function testFindUnprocessedEvents()
|
||||||
|
{
|
||||||
|
$events = self::$DI['app']['EM']->getRepository('Phraseanet:WebhookEvent')->findUnprocessedEvents();
|
||||||
|
$this->assertCount(1, $events);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\TaskManager\Job;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\TaskManager\Job\WebhookJob;
|
||||||
|
|
||||||
|
class WebhookJobTestJobTest extends JobTestCase
|
||||||
|
{
|
||||||
|
protected function getJob()
|
||||||
|
{
|
||||||
|
return new WebhookJob(null, null, $this->createTranslatorMock());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Webhook;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Webhook\EventProcessorFactory;
|
||||||
|
|
||||||
|
class EventProcessorFactoryTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider eventProvider
|
||||||
|
*/
|
||||||
|
public function testGet($type, $expected)
|
||||||
|
{
|
||||||
|
$factory = new EventProcessorFactory(self::$DI['app']);
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setType($type);
|
||||||
|
$this->assertInstanceOf($expected, $factory->get($event));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \RuntimeException
|
||||||
|
*/
|
||||||
|
public function testUnknownProcessor()
|
||||||
|
{
|
||||||
|
$factory = new EventProcessorFactory(self::$DI['app']);
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$factory->get($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function eventProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(WebhookEvent::FEED_ENTRY_TYPE, 'Alchemy\Phrasea\Webhook\Processor\FeedEntryProcessor'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Webhook;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Webhook\Processor\FeedEntryProcessor;
|
||||||
|
|
||||||
|
class FeedEntryProcessorTest extends \PhraseanetTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testProcessWithNoFeedId()
|
||||||
|
{
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setData(array(
|
||||||
|
'feed_id' => 0,
|
||||||
|
'entry_id' => 0
|
||||||
|
));
|
||||||
|
$event->setName(WebhookEvent::NEW_FEED_ENTRY);
|
||||||
|
$event->setType(WebhookEvent::FEED_ENTRY_TYPE);
|
||||||
|
$processor = new FeedEntryProcessor($event, self::$DI['app']);
|
||||||
|
$this->assertEquals($processor->process(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithMissingDataProperty()
|
||||||
|
{
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setData(array(
|
||||||
|
'feed_id' => 0,
|
||||||
|
));
|
||||||
|
$event->setName(WebhookEvent::NEW_FEED_ENTRY);
|
||||||
|
$event->setType(WebhookEvent::FEED_ENTRY_TYPE);
|
||||||
|
$processor = new FeedEntryProcessor($event, self::$DI['app']);
|
||||||
|
$this->assertEquals($processor->process(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testProcess()
|
||||||
|
{
|
||||||
|
$event = new WebhookEvent();
|
||||||
|
$event->setData(array(
|
||||||
|
'feed_id' => self::$DI['feed_public_entry']->getFeed()->getId(),
|
||||||
|
'entry_id' => self::$DI['feed_public_entry']->getId()
|
||||||
|
));
|
||||||
|
$event->setName(WebhookEvent::NEW_FEED_ENTRY);
|
||||||
|
$event->setType(WebhookEvent::FEED_ENTRY_TYPE);
|
||||||
|
$processor = new FeedEntryProcessor($event, self::$DI['app']);
|
||||||
|
$this->assertEquals($processor->process(), null);
|
||||||
|
}
|
||||||
|
}
|
@@ -202,6 +202,10 @@ abstract class PhraseanetTestCase extends WebTestCase
|
|||||||
return $DI['app']['repo.api-applications']->find(self::$fixtureIds['oauth']['user']);
|
return $DI['app']['repo.api-applications']->find(self::$fixtureIds['oauth']['user']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self::$DI['webhook-event'] = self::$DI->share(function ($DI) {
|
||||||
|
return $DI['app']['repo.webhook-event']->find(self::$fixtureIds['webhook']['event']);
|
||||||
|
});
|
||||||
|
|
||||||
self::$DI['oauth2-app-user-not-admin'] = self::$DI->share(function ($DI) {
|
self::$DI['oauth2-app-user-not-admin'] = self::$DI->share(function ($DI) {
|
||||||
return $DI['app']['repo.api-applications']->find(self::$fixtureIds['oauth']['user-not-admin']);
|
return $DI['app']['repo.api-applications']->find(self::$fixtureIds['oauth']['user-not-admin']);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user