├── .gitignore ├── CODEOWNERS ├── LICENCE.md ├── README.md ├── composer.json ├── docs └── images │ ├── screenshot-webhook-index.png │ └── screenshot-webhook-log-index.png └── src ├── Bootstrap.php ├── Module.php ├── components ├── dispatcher │ ├── EventDispatcher.php │ └── EventDispatcherInterface.php ├── formatter │ └── JsonPrettyFormatter.php ├── logger │ └── Logger.php └── validators │ └── ClassConstantDefinedValidator.php ├── controllers ├── Controller.php ├── WebhookController.php └── WebhookLogController.php ├── interfaces └── WebhookInterface.php ├── migrations ├── m181011_101959_create_table_webhook.php └── m181011_101960_create_table_webhook_log.php ├── models ├── Webhook.php ├── WebhookLog.php ├── WebhookLogSearch.php ├── WebhookQuery.php └── WebhookSearch.php └── views ├── layouts └── main.php ├── webhook-log ├── index.php └── view.php └── webhook ├── _form.php ├── create.php ├── index.php ├── update.php └── view.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | composer.lock -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | @napravicukod 2 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Degordian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Webhooks 2 | 3 | Extension for creating and using web-hooks in yii2. 4 | 5 | 6 | ## Description 7 | 8 | Add webhooks and attach them to `ActiveRecord` objects' events to trigger HTTP requests to external systems 9 | (3rd party services, your own applications etc.). 10 | 11 | ### Use case example 12 | 13 | Let's assume that inside your project you have an `Example` class which extends `ActiveRecord`. 14 | 15 | If you want to trigger a webhook every time a new `Example` record is created, you will create a new `Webhook` record, 16 | and assign it to your `Example` class. 17 | 18 | You do this by setting the `event` attribute of the `Webhook` record to value of `app\models\Example::EVENT_AFTER_CREATE`. 19 | You also set the webhook `url` and `method` values. For example `http://api.service.com` and `POST`. 20 | 21 | Now, every time a new `Example` record is created inside your project, your api service receives an 22 | http request with the `Example` object attributes. 23 | 24 | ## Installation 25 | 26 | The preferred way to install this extension is through composer. 27 | 28 | Run composer installation. 29 | 30 | ```bash 31 | composer require --prefer-dist degordian/yii2-webhooks "dev-master" 32 | ``` 33 | 34 | ## Setup 35 | 36 | Run the migration. It creates the _webhook_ and _webhook_log_ tables. 37 | 38 | ```bash 39 | php yii migrate --migrationPath=@degordian/webhooks/migrations 40 | ``` 41 | 42 | The extension needs to be bootstrapped: 43 | ```php 44 | 'bootstrap' => [ 45 | // ... 46 | 'webhooks' 47 | ], 48 | ``` 49 | 50 | Add the module to the config: 51 | ```php 52 | 'modules' => [ 53 | // ... 54 | 'webhooks' => [ 55 | 'class' => 'degordian\webhooks\Module', 56 | ], 57 | ], 58 | ``` 59 | 60 | ## Usage 61 | 62 | ### Webhooks 63 | Create a new webhook by navigating to the _webhooks_ module: `index.php?r=webhooks/webhook/create` 64 | 65 | You can use the predefined events from `BaseActiveRecord` class, e.g. `EVENT_AFTER_INSERT` or you can use your own events, e.g. `app\models\Example::EVENT_EXAMPLE`. 66 | 67 | ### User generated events 68 | When triggering your custom event, make sure you __send the instantiated model__ like in the following code: 69 | ```php 70 | Event::trigger(Example::class, Example::EVENT_EXAMPLE, new Event(['sender' => $model])); 71 | ``` 72 | 73 | ### Logger 74 | Extension logs every triggered webhook with its http request and response. 75 | 76 | Logs are available at `index.php/webhooks?r=/webhook-log/index` 77 | 78 | ## Implementing your own EventDispatcher 79 | 80 | You can add your own implementation of the event dispatcher to fit your needs. It must implement `EventDispatcherInterface`. 81 | 82 | Config needs to be updated accordingly: 83 | 84 | ```php 85 | 'modules' => [ 86 | // ... 87 | 'webhooks' => [ 88 | 'class' => 'degordian\webhooks\Module', 89 | 'eventDispatcherComponentClass' => 'app\components\MyDispatcher', 90 | ], 91 | ], 92 | ``` 93 | 94 | ## Implementing your own Webhook 95 | 96 | TBD 97 | 98 | ## Screenshots 99 | 100 | ![Image of webhook index page](docs/images/screenshot-webhook-index.png) 101 | 102 | ![Image of webhook-log index page](docs/images/screenshot-webhook-log-index.png) 103 | 104 | 105 | ## Contributing 106 | 107 | Your local setup should have this repository and an existing yii2 project (preferably a clean yii2 template). 108 | 109 | Link the repo to your project by adding it to your project's `composer.json` file: 110 | 111 | ``` 112 | "repositories": [ 113 | { 114 | "type": "path", 115 | "url": "../yii2-webhooks" 116 | } 117 | ] 118 | ``` 119 | 120 | Install it to the project using composer: 121 | 122 | `composer require --prefer-dist degordian/yii2-webhooks "*"` 123 | 124 | You can edit the files from within you project, directly in your `vendor` folder, for it is much more convenient that way. 125 | 126 | ## Credits 127 | 128 | This extension is created and maintained by [Bornfight](https://www.bornfight.com). 129 | 130 | 131 | 132 | ## License 133 | 134 | TBD 135 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.1", 3 | "name": "degordian/yii2-webhooks", 4 | "description": "Yii2 extension for webhooks", 5 | "type": "yii2-extension", 6 | "keywords": ["yii2","extension","webhook"], 7 | "license": "MIT", 8 | "support": { 9 | "issues": "https://github.com/degordian/yii2-webhooks/issues", 10 | "source": "https://github.com/degordian/yii2-webhooks" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Rudolf Jurišić", 15 | "email": "rudolf.jurisic@degordian.com" 16 | } 17 | ], 18 | "minimum-stability": "dev", 19 | "autoload": { 20 | "psr-4": { 21 | "degordian\\webhooks\\": "src", 22 | "tests\\unit\\models\\": "tests/unit/models" 23 | } 24 | }, 25 | "require": { 26 | "php": ">=7.1.0", 27 | "yiisoft/yii2": "^2.0@dev", 28 | "yiisoft/yii2-httpclient": "~2.0.0" 29 | }, 30 | "require-dev": { 31 | "codeception/codeception": "2.5.x-dev" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/images/screenshot-webhook-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bornfight/yii2-webhooks/c6ac105219d7866a3476e11dd49e5967dd7225c0/docs/images/screenshot-webhook-index.png -------------------------------------------------------------------------------- /docs/images/screenshot-webhook-log-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bornfight/yii2-webhooks/c6ac105219d7866a3476e11dd49e5967dd7225c0/docs/images/screenshot-webhook-log-index.png -------------------------------------------------------------------------------- /src/Bootstrap.php: -------------------------------------------------------------------------------- 1 | setModule('webhooks', [ 12 | 'id' => 'webhooks', 13 | 'class' => 'degordian\webhooks\Module' 14 | ]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Module.php: -------------------------------------------------------------------------------- 1 | validateWebhookClass(); 29 | 30 | $webhooks = $this->findWebhooks(); 31 | 32 | if ($webhooks) { 33 | $this->validateWebhooks($webhooks); 34 | $this->validateEventDispatcherComponentClass(); 35 | 36 | \Yii::configure(\Yii::$app, [ 37 | 'components' => [ 38 | 'eventDispatcher' => [ 39 | 'class' => $this->eventDispatcherComponentClass 40 | ], 41 | 'formatter' => [ 42 | 'class' => 'degordian\webhooks\components\formatter\JsonPrettyFormatter' 43 | ] 44 | ] 45 | ]); 46 | 47 | $this->attachWebhooks($webhooks); 48 | } 49 | } 50 | 51 | private function validateWebhookClass(): void 52 | { 53 | $class = new \ReflectionClass($this->webhookClass); 54 | if (!$class->implementsInterface($this->webhookInterface)) { 55 | throw new Exception($this->webhookClass . ' must implement ' . $this->webhookInterface); 56 | } 57 | 58 | $activeRecordClassNamespace = 'yii\db\ActiveRecord'; 59 | if (!$class->isSubclassOf($activeRecordClassNamespace)) { 60 | throw new Exception($this->webhookClass . ' must extend ' . $activeRecordClassNamespace); 61 | } 62 | } 63 | 64 | private function validateEventDispatcherComponentClass(): void 65 | { 66 | $class = new \ReflectionClass($this->eventDispatcherComponentClass); 67 | if (!$class->implementsInterface($this->eventDispatcherInterface)) { 68 | throw new Exception($this->webhookClass . ' must implement ' . $this->webhookInterface); 69 | } 70 | } 71 | 72 | private function validateWebhooks($webhooks): void 73 | { 74 | $validator = new ClassConstantDefinedValidator(); 75 | foreach ($webhooks as $webhook) { 76 | if (!$validator->validate($webhook->event)) { 77 | throw new Exception('Event ' . $webhook->event . ' does not exist'); 78 | } 79 | } 80 | } 81 | 82 | private function attachWebhooks(array $webhooks): void 83 | { 84 | foreach ($webhooks as $webhook) { 85 | Event::on($webhook->getClassName(), constant($webhook->event), function ($event) use ($webhook) { 86 | $this->eventDispatcher->dispatch($event, $webhook); 87 | }); 88 | } 89 | } 90 | 91 | // private function detachWebhooks(array $webhooks): void 92 | // { 93 | // foreach ($webhooks as $webhook) { 94 | // Event::off($webhook->getClassName(), constant($webhook->event), [$this->eventDispatcher, 'dispatch']); 95 | // } 96 | // } 97 | 98 | private function findWebhooks(): array 99 | { 100 | return (new WebhookQuery($this->webhookClass)) 101 | ->all(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/components/dispatcher/EventDispatcher.php: -------------------------------------------------------------------------------- 1 | $webhook->getClassName(), 20 | 'modelEvent' => $webhook->getEventName(), 21 | 'modelAttributes' => $event->sender->attributes, 22 | ]; 23 | try { 24 | $request = $client->createRequest() 25 | ->setMethod($webhook->method) 26 | ->setHeaders([ 27 | 'User-Agent' => $this->userAgent, 28 | ]) 29 | ->setUrl($webhook->url) 30 | ->setData($data); 31 | $response = $request->send(); 32 | Logger::log($webhook, $request, $response); 33 | } catch (\Exception $e) { 34 | \Yii::error($e->getMessage()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/components/dispatcher/EventDispatcherInterface.php: -------------------------------------------------------------------------------- 1 | " . str_replace("\n", "
", json_encode(json_decode($value), JSON_PRETTY_PRINT)) . ""; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/logger/Logger.php: -------------------------------------------------------------------------------- 1 | time(), 24 | 'webhook_method' => $webhook->method, 25 | 'webhook_url' => $webhook->url, 26 | 'webhook_event' => $webhook->event, 27 | 'request_headers' => Json::encode($request->headers), 28 | 'request_payload' => Json::encode($request->data), 29 | 'response_headers' => Json::encode($response->headers), 30 | 'response_status_code' => $response->statusCode 31 | ]); 32 | 33 | $model->save(false); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/components/validators/ClassConstantDefinedValidator.php: -------------------------------------------------------------------------------- 1 | message === null) { 14 | $this->message = Yii::t('yii', '{attribute} "{value}" is not defined as a class constant'); 15 | } 16 | } 17 | 18 | public function validateValue($value) 19 | { 20 | if (!is_string($value)) { 21 | return null; 22 | } 23 | 24 | try { 25 | if (!defined($value)) { 26 | return [$this->message, []]; 27 | } 28 | } catch (\Exception $e) { 29 | return null; 30 | } 31 | 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/controllers/Controller.php: -------------------------------------------------------------------------------- 1 | layout = 'main'; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/controllers/WebhookController.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'class' => VerbFilter::class, 18 | 'actions' => [ 19 | 'delete' => ['POST'], 20 | ], 21 | ], 22 | ]; 23 | } 24 | 25 | public function actionIndex() 26 | { 27 | $searchModel = new WebhookSearch(); 28 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 29 | 30 | return $this->render('index', [ 31 | 'searchModel' => $searchModel, 32 | 'dataProvider' => $dataProvider, 33 | ]); 34 | } 35 | 36 | public function actionView($id) 37 | { 38 | return $this->render('view', [ 39 | 'model' => $this->findModel($id), 40 | ]); 41 | } 42 | 43 | public function actionCreate() 44 | { 45 | $model = new Webhook(); 46 | 47 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 48 | return $this->redirect(['view', 'id' => $model->id]); 49 | } 50 | 51 | return $this->render('create', [ 52 | 'model' => $model, 53 | ]); 54 | } 55 | 56 | public function actionUpdate($id) 57 | { 58 | $model = $this->findModel($id); 59 | 60 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 61 | return $this->redirect(['view', 'id' => $model->id]); 62 | } 63 | 64 | return $this->render('update', [ 65 | 'model' => $model, 66 | ]); 67 | } 68 | 69 | public function actionDelete($id) 70 | { 71 | $this->findModel($id)->delete(); 72 | 73 | return $this->redirect(['index']); 74 | } 75 | 76 | protected function findModel($id) 77 | { 78 | if (($model = Webhook::findOne($id)) !== null) { 79 | return $model; 80 | } 81 | 82 | throw new NotFoundHttpException('The requested page does not exist.'); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/controllers/WebhookLogController.php: -------------------------------------------------------------------------------- 1 | [ 23 | 'class' => VerbFilter::className(), 24 | 'actions' => [ 25 | 'delete' => ['POST'], 26 | ], 27 | ], 28 | ]; 29 | } 30 | 31 | /** 32 | * Lists all WebhookLog models. 33 | * @return mixed 34 | */ 35 | public function actionIndex() 36 | { 37 | $searchModel = new WebhookLogSearch(); 38 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 39 | 40 | return $this->render('index', [ 41 | 'searchModel' => $searchModel, 42 | 'dataProvider' => $dataProvider, 43 | ]); 44 | } 45 | 46 | /** 47 | * Displays a single WebhookLog model. 48 | * @param integer $id 49 | * @return mixed 50 | * @throws NotFoundHttpException if the model cannot be found 51 | */ 52 | public function actionView($id) 53 | { 54 | return $this->render('view', [ 55 | 'model' => $this->findModel($id), 56 | ]); 57 | } 58 | 59 | /** 60 | * Finds the WebhookLog model based on its primary key value. 61 | * If the model is not found, a 404 HTTP exception will be thrown. 62 | * @param integer $id 63 | * @return WebhookLog the loaded model 64 | * @throws NotFoundHttpException if the model cannot be found 65 | */ 66 | protected function findModel($id) 67 | { 68 | if (($model = WebhookLog::findOne($id)) !== null) { 69 | return $model; 70 | } 71 | 72 | throw new NotFoundHttpException('The requested page does not exist.'); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/interfaces/WebhookInterface.php: -------------------------------------------------------------------------------- 1 | createTable($this->tableName, [ 21 | 'id' => $this->primaryKey(), 22 | 'event' => $this->string(255)->notNull(), 23 | 'description' => $this->text()->null(), 24 | 'url' => $this->string(2083)->notNull(), 25 | 'method' => $this->string(6)->notNull(), 26 | 'created_at' => $this->integer(11), 27 | 'updated_at' => $this->integer(11), 28 | ]); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function safeDown() 35 | { 36 | $this->dropTable($this->tableName); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/migrations/m181011_101960_create_table_webhook_log.php: -------------------------------------------------------------------------------- 1 | createTable($this->tableName, [ 21 | 'id' => $this->bigPrimaryKey(), 22 | 'log_time' => $this->integer(11), 23 | 'webhook_event' => $this->string(), 24 | 'webhook_method' => $this->string(10), 25 | 'webhook_url' => $this->string(), 26 | 'request_headers' => $this->text(), 27 | 'request_payload' => $this->text(), 28 | 'response_headers' => $this->text(), 29 | 'response_status_code' => $this->integer(), 30 | ]); 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function safeDown() 37 | { 38 | $this->dropTable($this->tableName); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/models/Webhook.php: -------------------------------------------------------------------------------- 1 | event; 30 | } 31 | 32 | public function getUrl() 33 | { 34 | return $this->url; 35 | } 36 | 37 | public function getMethod() 38 | { 39 | return $this->method; 40 | } 41 | 42 | public function getEventName() 43 | { 44 | return explode('::', $this->event)[1]; 45 | } 46 | 47 | public function getClassName() 48 | { 49 | return explode('::', $this->event)[0]; 50 | } 51 | 52 | public function behaviors() 53 | { 54 | return [ 55 | TimestampBehavior::className(), 56 | ]; 57 | } 58 | 59 | public function rules() 60 | { 61 | return [ 62 | [['event', 'description'], 'string', 'max' => 255], 63 | [['url'], 'string', 'max' => 2083], 64 | [['method'], 'string', 'max' => 6], 65 | [['event', 'url', 'method'], 'required'], 66 | [['created_at', 'updated_at'], 'integer'], 67 | ['event', ClassConstantDefinedValidator::class, 'message' => 'Allowed format: ::'], 68 | ['url', 'url'], 69 | ['method', 'in', 'range' => ['GET', 'POST', 'PUT', 'DELETE']], 70 | ]; 71 | } 72 | 73 | public function httpMethodValidation() 74 | { 75 | } 76 | 77 | public function attributeLabels() 78 | { 79 | return [ 80 | 'id' => 'ID', 81 | 'event' => 'Event', 82 | 'description' => 'Description', 83 | 'url' => 'Url', 84 | 'method' => 'Method', 85 | 'created_at' => 'Created At', 86 | 'updated_at' => 'Updated At', 87 | ]; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/models/WebhookLog.php: -------------------------------------------------------------------------------- 1 | 255], 45 | [['webhook_method'], 'string', 'max' => 10], 46 | ]; 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function attributeLabels() 53 | { 54 | return [ 55 | 'id' => 'ID', 56 | 'log_time' => 'Log Time', 57 | 'webhook_event' => 'Webhook Event', 58 | 'webhook_method' => 'Webhook Method', 59 | 'webhook_url' => 'Webhook Url', 60 | 'request_headers' => 'Request Headers', 61 | 'request_payload' => 'Request Payload', 62 | 'response_headers' => 'Response Headers', 63 | 'response_status_code' => 'Response Status Code', 64 | ]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/models/WebhookLogSearch.php: -------------------------------------------------------------------------------- 1 | $query, 50 | 'sort' => [ 51 | 'defaultOrder' => [ 52 | 'id' => SORT_DESC 53 | ], 54 | ] 55 | ]); 56 | 57 | $this->load($params); 58 | 59 | if (!$this->validate()) { 60 | // uncomment the following line if you do not want to return any records when validation fails 61 | // $query->where('0=1'); 62 | return $dataProvider; 63 | } 64 | 65 | // grid filtering conditions 66 | $query->andFilterWhere([ 67 | 'id' => $this->id, 68 | 'log_time' => $this->log_time, 69 | 'response_status_code' => $this->response_status_code, 70 | ]); 71 | 72 | $query->andFilterWhere(['like', 'webhook_event', $this->webhook_event]) 73 | ->andFilterWhere(['like', 'webhook_method', $this->webhook_method]) 74 | ->andFilterWhere(['like', 'webhook_url', $this->webhook_url]) 75 | ->andFilterWhere(['like', 'request_headers', $this->request_headers]) 76 | ->andFilterWhere(['like', 'request_payload', $this->request_payload]) 77 | ->andFilterWhere(['like', 'response_headers', $this->response_headers]); 78 | 79 | return $dataProvider; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/models/WebhookQuery.php: -------------------------------------------------------------------------------- 1 | $query, 30 | 'sort' => [ 31 | 'defaultOrder' => [ 32 | 'id' => SORT_DESC 33 | ], 34 | ] 35 | ]); 36 | 37 | $this->load($params); 38 | 39 | if (!$this->validate()) { 40 | return $dataProvider; 41 | } 42 | 43 | // grid filtering conditions 44 | $query->andFilterWhere([ 45 | 'id' => $this->id, 46 | 'created_at' => $this->created_at, 47 | 'updated_at' => $this->updated_at, 48 | ]); 49 | 50 | $query->andFilterWhere(['like', 'event', $this->event]) 51 | ->andFilterWhere(['like', 'description', $this->description]) 52 | ->andFilterWhere(['like', 'url', $this->url]) 53 | ->andFilterWhere(['like', 'method', $this->method]); 54 | 55 | return $dataProvider; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 15 | beginPage() ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | <?= Html::encode($this->title) ?> 24 | head() ?> 25 | 26 | 27 | beginBody() ?> 28 | 29 |
30 | 'yii2-webhooks', 33 | 'brandUrl' => \yii\helpers\Url::toRoute(['webhook/index']), 34 | 'options' => [ 35 | 'class' => 'navbar-inverse navbar-fixed-top', 36 | ], 37 | ]); 38 | $menuItems = [ 39 | ['label' => 'Webhooks', 'url' => Url::toRoute(['/webhooks'])], 40 | ['label' => 'Webhook Logs', 'url' => Url::toRoute(['webhook-log/index'])], 41 | ['label' => ' ← Back to App', 'url' => Yii::$app->homeUrl], 42 | ]; 43 | 44 | echo Nav::widget([ 45 | 'options' => ['class' => 'navbar-nav navbar-right'], 46 | 'items' => $menuItems, 47 | ]); 48 | NavBar::end(); 49 | ?> 50 | 51 |
52 | [ 54 | 'label' => 'yii2-webhooks', 55 | 'url' => Url::toRoute(['/webhooks']) 56 | ], 57 | 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], 58 | ]) ?> 59 | 60 | 61 |
62 |
63 | 64 |
65 |
66 |

© name) ?>

67 | 68 |

69 |
70 |
71 | 72 | endBody() ?> 73 | 74 | 75 | endPage() ?> 76 | -------------------------------------------------------------------------------- /src/views/webhook-log/index.php: -------------------------------------------------------------------------------- 1 | title = 'Webhook Logs'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 | 15 |

title) ?>

16 | 17 | $dataProvider, 19 | 'filterModel' => $searchModel, 20 | 'columns' => [ 21 | 'id', 22 | 'log_time:datetime', 23 | [ 24 | 'attribute' => 'response_status_code', 25 | 'content' => function($model) { 26 | if($model->response_status_code === 200) { 27 | return ''.$model->response_status_code.''; 28 | } 29 | return ''.$model->response_status_code.''; 30 | } 31 | ], 32 | 'webhook_event', 33 | 'webhook_method', 34 | 'webhook_url:url', 35 | [ 36 | 'class' => 'yii\grid\ActionColumn', 37 | 'buttons' => [ 38 | 'view' => function ($url, $model) { 39 | return Html::a('', $url, [ 40 | 'title' => Yii::t('app', 'lead-view'), 41 | ]); 42 | }, 43 | 44 | 'update' => function ($url, $model) { 45 | return ''; 46 | }, 47 | 'delete' => function ($url, $model) { 48 | return ''; 49 | }, 50 | ] 51 | 52 | ], 53 | ], 54 | ]); ?> 55 |
56 | -------------------------------------------------------------------------------- /src/views/webhook-log/view.php: -------------------------------------------------------------------------------- 1 | title = $model->id; 11 | $this->params['breadcrumbs'][] = ['label' => 'Webhook Logs', 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |
15 | 16 |

title) ?>

17 | 18 | $model, 20 | 'attributes' => [ 21 | 'id', 22 | 'log_time:datetime', 23 | 'webhook_event', 24 | 'webhook_method', 25 | 'webhook_url:url', 26 | 'request_headers:prettyjson', 27 | 'request_payload:prettyjson', 28 | 'response_headers:prettyjson', 29 | 'response_status_code', 30 | ], 31 | ]) ?> 32 | 33 |
34 | -------------------------------------------------------------------------------- /src/views/webhook/_form.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 | 14 | 15 | field($model, 'event')->textInput(['maxlength' => true]) ?> 16 | 17 | field($model, 'description')->textInput() ?> 18 | 19 | field($model, 'url')->textInput(['maxlength' => true]) ?> 20 | 21 | field($model, 'method')->textInput(['maxlength' => true]) ?> 22 | 23 |
24 | 'btn btn-success']) ?> 25 |
26 | 27 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /src/views/webhook/create.php: -------------------------------------------------------------------------------- 1 | title = 'Create Webhook'; 9 | $this->params['breadcrumbs'][] = ['label' => 'Webhooks', 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 |
13 | 14 |

title) ?>

15 | 16 | render('_form', [ 17 | 'model' => $model, 18 | ]) ?> 19 | 20 |
21 | -------------------------------------------------------------------------------- /src/views/webhook/index.php: -------------------------------------------------------------------------------- 1 | title = 'Webhooks'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 | 15 |

title) ?>

16 | 17 |

18 | 'btn btn-success']) ?> 19 |

20 | 21 | $dataProvider, 23 | 'filterModel' => $searchModel, 24 | 'columns' => [ 25 | 'id', 26 | 'event', 27 | 'url:url', 28 | 'method', 29 | 30 | ['class' => 'yii\grid\ActionColumn'], 31 | ], 32 | ]); ?> 33 |
34 | -------------------------------------------------------------------------------- /src/views/webhook/update.php: -------------------------------------------------------------------------------- 1 | title = 'Update Webhook: ' . $model->id; 9 | $this->params['breadcrumbs'][] = ['label' => 'Webhooks', 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][] = 'Update'; 12 | ?> 13 |
14 | 15 |

title) ?>

16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /src/views/webhook/view.php: -------------------------------------------------------------------------------- 1 | title = $model->id; 10 | $this->params['breadcrumbs'][] = ['label' => 'Webhooks', 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 | 15 |

title) ?>

16 | 17 |

18 | $model->id], ['class' => 'btn btn-primary']) ?> 19 | $model->id], [ 20 | 'class' => 'btn btn-danger', 21 | 'data' => [ 22 | 'confirm' => 'Are you sure you want to delete this item?', 23 | 'method' => 'post', 24 | ], 25 | ]) ?> 26 |

27 | 28 | $model, 30 | 'attributes' => [ 31 | 'id', 32 | 'event', 33 | 'description:ntext', 34 | 'url:url', 35 | 'method', 36 | 'created_at', 37 | 'updated_at', 38 | ], 39 | ]) ?> 40 | 41 |
42 | --------------------------------------------------------------------------------