├── index.html
├── tmp
├── empty
├── cache
│ └── empty
└── logs
│ └── empty
├── vendor
└── empty
├── .htaccess
├── robots.txt
├── config
├── chatwork.json.default
└── slack.json.default
├── composer.json
├── .gitignore
├── lib
├── autoload.php
├── BitbucketEventNotification
│ ├── Api
│ │ ├── BaseApiClient.php
│ │ ├── ChatworkApiClient.php
│ │ └── SlackApiClient.php
│ ├── PullRequest
│ │ ├── PullRequestCreated.php
│ │ ├── PullRequestMerged.php
│ │ ├── PullRequestDeclined.php
│ │ ├── PullRequestUpdated.php
│ │ ├── PullRequestCommentCreated.php
│ │ └── PullRequest.php
│ ├── JsonParser
│ │ └── JsonParser.php
│ ├── Config
│ │ └── ConfigLoader.php
│ ├── Log
│ │ └── MLog.php
│ └── DestinationService
│ │ ├── DestinationService.php
│ │ ├── ChatworkService.php
│ │ └── SlackService.php
├── utils.php
└── SplClassLoader.php
├── README.md
├── sample-merged-hook-request.json
└── gateway.php
/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tmp/empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tmp/cache/empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tmp/logs/empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.htaccess:
--------------------------------------------------------------------------------
1 | Options -Indexes
2 |
--------------------------------------------------------------------------------
/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/config/chatwork.json.default:
--------------------------------------------------------------------------------
1 | {
2 | "token": "set your token"
3 | }
--------------------------------------------------------------------------------
/config/slack.json.default:
--------------------------------------------------------------------------------
1 | {
2 | "token": "set your token (xoxp-xxxxxxx)"
3 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "monolog/monolog": ">=1.0.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | tmp/*
4 | vendor/*
5 | composer.lock
6 | config/chatwork.json
7 | config/slack.json
8 |
--------------------------------------------------------------------------------
/lib/autoload.php:
--------------------------------------------------------------------------------
1 | register();
7 |
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/Api/BaseApiClient.php:
--------------------------------------------------------------------------------
1 | ';
9 | echo 'debug from: ' . $trace[0]['file'] . ' on line:' . $trace[0]['line'] . '
';
10 | foreach (func_get_args() as $v) {
11 | var_dump($v);
12 | }
13 | echo '';
14 | }
15 |
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/JsonParser/JsonParser.php:
--------------------------------------------------------------------------------
1 | configDir = $configDir;
21 | }
22 |
23 | /**
24 | * Load config value of config json file.
25 | *
26 | * @param $configName config json file name
27 | * @param $key key
28 | * @return mixed returns config value. false is returned if the failed for load.
29 | */
30 | public function load($configName, $key)
31 | {
32 | $configJson = file_get_contents($this->configDir . '/' . $configName . '.json');
33 | if (!$configJson) {
34 | return false;
35 | }
36 | $config = json_decode($configJson, true);
37 | if (!array_key_exists($key, $config)) {
38 | return false;
39 | }
40 | return $config[$key];
41 | }
42 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/Log/MLog.php:
--------------------------------------------------------------------------------
1 | pushHandler(new StreamHandler($loggingPath, $level));
55 | }
56 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/DestinationService/DestinationService.php:
--------------------------------------------------------------------------------
1 | serviceName = $serviceName;
30 | $this->pullRequest = $pullRequest;
31 | }
32 |
33 | /**
34 | * @return BaseAPIClient get api client of this service.
35 | */
36 | abstract function getApiClient();
37 |
38 | /**
39 | * @param array $extendedParams optional
40 | * @return mixed returns the response array if api successful.
41 | * otherwise, returns null.
42 | */
43 | abstract function postMessage($extendedParams = array());
44 |
45 | /**
46 | * Return the destination service instance by service name.
47 | *
48 | * @param string $serviceName
49 | * @param PullRequest $pullRequest
50 | * @return DestinationService
51 | */
52 | public static function create($serviceName, $pullRequest)
53 | {
54 | $serviceName = strtolower(trim($serviceName));
55 |
56 | $instance = null;
57 | switch ($serviceName) {
58 | case 'chatwork':
59 | $instance = new ChatworkService($pullRequest);
60 | break;
61 | case 'slack':
62 | $instance = new SlackService($pullRequest);
63 | break;
64 | default:
65 | break;
66 | }
67 |
68 | return $instance;
69 | }
70 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/Api/ChatworkApiClient.php:
--------------------------------------------------------------------------------
1 | $message);
31 |
32 | $ch = curl_init();
33 | curl_setopt($ch, CURLOPT_URL, self::BASE_API_URL . 'v1/rooms/' . intval($roomId) . '/messages');
34 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-ChatWorkToken: ' . $this->loadAccessToken()));
35 | curl_setopt($ch, CURLOPT_POST, 1);
36 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($option, '', '&'));
37 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
38 |
39 | $response = curl_exec($ch);
40 | $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
41 | if ($statusCode === 200) {
42 | if ($response = json_decode($response)) {
43 | MLog::getInstance()->info("Successful response data:" . json_encode($response));
44 | return $response;
45 | }
46 | }
47 |
48 | MLog::getInstance()->err("Error occurred while executing chatwork api.");
49 | MLog::getInstance()->err("Status code: {$statusCode}");
50 | MLog::getInstance()->err("Response: " . json_encode($response));
51 |
52 | return null;
53 | }
54 |
55 | /**
56 | * Get access token from config file.
57 | *
58 | * @return mixed returns config value. false is returned if the failed for load.
59 | */
60 | public function loadAccessToken()
61 | {
62 | $loader = new ConfigLoader(__DIR__ . '/../../../config');
63 | return $loader->load('chatwork', 'token');
64 | }
65 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/PullRequest/PullRequest.php:
--------------------------------------------------------------------------------
1 | setData($jsonData);
59 | }
60 |
61 | return $instance;
62 | }
63 |
64 | /**
65 | * @param array $data
66 | */
67 | public function setData($data)
68 | {
69 | $this->data = $data;
70 | }
71 |
72 | /**
73 | * @return array
74 | */
75 | public function getData()
76 | {
77 | return $this->data;
78 | }
79 |
80 | /**
81 | * Replace endpoint url to url link.
82 | *
83 | * @param string $url
84 | * @return string
85 | */
86 | public static function replaceUrlForLink($url)
87 | {
88 | return str_replace('://api.', '://', $url);
89 | }
90 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | BitbucketEventNotification
2 | ==========================
3 |
4 | Notify Chatwork or Slack, when receive pull request notifications from Bitbucket.
5 |
6 | 
7 |
8 | ## Notification Flow
9 |
10 | 1. Pull Request on Bitbucket
11 | 2. Hook post request to your server will occur.
12 | 3. This application receives the request, and post notification messages to the chat. (Chatwork or Slack)
13 |
14 | ## Supported Pull Request Notification
15 |
16 | - Created
17 | - Merged
18 | - Updated
19 | - Declined
20 | - Comment created (on the pull request page)
21 |
22 | ## Requires
23 |
24 | * PHP 5.3+ with cURL with composer
25 | * Access token of Chatwork, if you want notification to that.
26 | * Access token of Slack, if you want notification to that. (xoxp-xxxxx)
27 | * If you want to create a token to access to the page of [Slack API](https://api.slack.com/).
28 | * Bitbucket repository with administrator right.
29 |
30 | ## Installation
31 |
32 | 1. Get source code from GitHub, either using Git, or by downloading directly.
33 | 2. Copy the source files to public directory in your server.
34 | 3. Setup correct permissions
35 | * `chmod -R 777 tmp`
36 | 4. Adjust token in your config file.
37 | * for the Chatwork
38 | * `cp config/chatwork.json.default config/chatwork.json`
39 | * `vim config/chatwork.json`
40 | * for the Slack
41 | * `cp config/slack.json.default config/slack.json`
42 | * `vim config/slack.json`
43 | 5. Plugin install with composer. (You need to install composer.)
44 | * `composer install`
45 | 6. Please set the following post destination url in chat work your account setting page. (room_id is chatwork room id.)
46 | * Sample pull request post hook url (for Chatwork):
47 | * http://example.com/bitbucket_event_notification/gateway.php?destination_service=chatwork&room_id=1000000000
48 | * Sample pull request post hook url (for Slack):
49 | * http://example.com/bitbucket_event_notification/gateway.php?destination_service=slack&room_id=C1234567890
50 |
51 | ## Parameters of gateway.php (GET)
52 |
53 | |Key|Description|Example for Chatwork|Example for Slack|
54 | |:---|:---|:---|:---|
55 | |destination_service|Post destination service name.|chatwork|slack|
56 | |room_id|Post destination.|1000000000|#bitbucket, C1234567890|
57 |
58 | * If you include the # to the channel name, please URL-encoded.
59 | * Example: `#bitbucket` -> `%23bitbucket`
60 |
61 | ## Author
62 |
63 | - [創作メモ帳](http://sousaku-memo.net/)
64 | - [創作メモ帳 - Slackへのプルリクエスト通知に対応しました](http://sousaku-memo.net/php-system/1264) : Japanese document is here
65 |
--------------------------------------------------------------------------------
/sample-merged-hook-request.json:
--------------------------------------------------------------------------------
1 | {
2 | "pullrequest_merged": {
3 | "description": "",
4 | "title": "Inbox changes",
5 | "close_source_branch": true,
6 | "destination": {
7 | "commit": {
8 | "hash": "82d48819e5f7",
9 | "links": {
10 | "self": {
11 | "href": "https://api.bitbucket.org/2.0/repositories/evzijst/bitbucket2/commit/82d48819e5f7"
12 | }
13 | }
14 | },
15 | "repository": {
16 | "links": {
17 | "self": {
18 | "href": "https://api.bitbucket.org/2.0/repositories/evzijst/bitbucket2"
19 | },
20 | "avatar": {
21 | "href": "https://bitbucket.org/m/d864f6bcaa94/img/language-avatars/default_16.png"
22 | }
23 | },
24 | "full_name": "evzijst/bitbucket2",
25 | "name": "bitbucket2"
26 | },
27 | "branch": {
28 | "name": "staging"
29 | }
30 | },
31 | "reason": "",
32 | "source": {
33 | "commit": {
34 | "hash": "325625d47b0a",
35 | "links": {
36 | "self": {
37 | "href": "https://api.bitbucket.org/2.0/repositories/evzijst/bitbucket2/commit/325625d47b0a"
38 | }
39 | }
40 | },
41 | "repository": {
42 | "links": {
43 | "self": {
44 | "href": "https://api.bitbucket.org/2.0/repositories/evzijst/bitbucket2"
45 | },
46 | "avatar": {
47 | "href": "https://bitbucket.org/m/d864f6bcaa94/img/language-avatars/default_16.png"
48 | }
49 | },
50 | "full_name": "evzijst/bitbucket2",
51 | "name": "bitbucket2"
52 | },
53 | "branch": {
54 | "name": "mfrauenholtz/inbox"
55 | }
56 | },
57 | "state": "MERGED",
58 | "author": {
59 | "username": "evzijst",
60 | "display_name": "Erik van Zijst",
61 | "links": {
62 | "self": {
63 | "href": "https://api.bitbucket.org/2.0/users/evzijst"
64 | },
65 | "avatar": {
66 | "href": "https://bitbucket-staging-assetroot.s3.amazonaws.com/c/photos/2013/Oct/28/evzijst-avatar-3454044670-3_avatar.png"
67 | }
68 | }
69 | },
70 | "date": "2013-11-08T19:49:12.233187+00:00"
71 | }
72 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/Api/SlackApiClient.php:
--------------------------------------------------------------------------------
1 | $this->loadAccessToken(),
33 | 'channel' => $channel,
34 | 'text' => $message,
35 | 'username' => 'Bitbucket',
36 | 'icon_url' => 'https://slack.global.ssl.fastly.net/20653/img/services/bitbucket_48.png',
37 | 'attachments' => json_encode($attachments),
38 | );
39 |
40 | $ch = curl_init();
41 | curl_setopt($ch, CURLOPT_URL, self::BASE_API_URL . 'chat.postMessage');
42 | curl_setopt($ch, CURLOPT_POST, 1);
43 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($option, '', '&'));
44 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
45 |
46 | $response = curl_exec($ch);
47 | $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
48 | if ($statusCode === 200 && $response = json_decode($response)) {
49 | if ($response->ok === true) {
50 | MLog::getInstance()->info("Successful response data:" . json_encode($response));
51 | return $response;
52 | }
53 | }
54 |
55 | MLog::getInstance()->err("Error occurred while executing slack api.");
56 | MLog::getInstance()->err("Status code: {$statusCode}");
57 | MLog::getInstance()->err("Response: " . json_encode($response));
58 |
59 | return null;
60 | }
61 |
62 | /**
63 | * Get access token from config file.
64 | *
65 | * @return mixed returns config value. false is returned if the failed for load.
66 | */
67 | public function loadAccessToken()
68 | {
69 | $loader = new ConfigLoader(__DIR__ . '/../../../config');
70 | return $loader->load('slack', 'token');
71 | }
72 | }
--------------------------------------------------------------------------------
/gateway.php:
--------------------------------------------------------------------------------
1 | info('Access from ip address: ' . $_SERVER['REMOTE_ADDR']);
31 |
32 | header('Content-type: application/json; charset=utf-8');
33 |
34 | // Check arguments
35 | if (!isset($_GET['room_id']) || !$_GET['room_id']) {
36 | MLog::getInstance()->err('Invalid room id parameter.');
37 | header('HTTP', true, 403);
38 | echo json_encode(array('result' => false, 'message' => 'Invalid access.'));
39 | exit;
40 | }
41 |
42 | if (!isset($_GET['destination_service']) || !$_GET['destination_service']) {
43 | // default service: chatwork (keep backward compatibility)
44 | $_GET['destination_service'] = 'chatwork';
45 | }
46 |
47 | // Get json from chatwork
48 | $inputPath = USE_TEST_JSON ? APP_DIR . '/sample-merged-hook-request.json' : 'php://input';
49 | $rawJson = file_get_contents($inputPath);
50 | MLog::getInstance()->info('Request json: ' . json_encode(json_decode($rawJson)));
51 |
52 | // Parse json
53 | $parser = new JsonParser();
54 | $jsonData = $parser->parse($rawJson);
55 | $pullRequest = PullRequest::create($jsonData);
56 |
57 | MLog::getInstance()->info("Pull request type is " . get_class($pullRequest));
58 |
59 | if ($pullRequest === null) {
60 | MLog::getInstance()->err('Failed to parse json data. An unsupported json format.');
61 | if (!empty($jsonData)) {
62 | MLog::getInstance()->err('json data:' . print_r($jsonData, true));
63 | }
64 | header('HTTP', true, 403);
65 | echo json_encode(array('result' => false, 'message' => 'Failed to parse data.'));
66 | exit;
67 | }
68 |
69 | // Decide destination service
70 | $destinationService = DestinationService::create($_GET['destination_service'], $pullRequest);
71 | MLog::getInstance()->info("Destination service type is " . get_class($destinationService));
72 | if (!$destinationService) {
73 | MLog::getInstance()->err('Invalid destination service parameter.');
74 | MLog::getInstance()->err('Specified destination service value:' . $_GET['destination_service']);
75 | header('HTTP', true, 403);
76 | echo json_encode(array('result' => false, 'message' => 'Invalid access.'));
77 | exit;
78 | }
79 |
80 | // Post message
81 | $response = $destinationService->postMessage(array('room_id' => $_GET['room_id']));
82 |
83 | // Response
84 | if ($response !== null) {
85 | MLog::getInstance()->info('Return success response.');
86 | header('HTTP', true, 200);
87 | echo json_encode($response);
88 | exit;
89 | } else {
90 | MLog::getInstance()->err('Return error response.');
91 | header('HTTP', true, 403);
92 | echo json_encode(array('result' => false, 'message' => 'Failed to post message.'));
93 | exit;
94 | }
95 |
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/DestinationService/ChatworkService.php:
--------------------------------------------------------------------------------
1 | getNotifyMessage();
40 |
41 | /**
42 | * @var ChatworkApiClient $apiClient
43 | */
44 | $apiClient = $this->getApiClient();
45 | $response = $apiClient->postMessage($extendedParams['room_id'], $notifyMessage);
46 |
47 | return $response;
48 | }
49 |
50 | /**
51 | * Get notify message string for post.
52 | *
53 | * @return string|null null if failed
54 | */
55 | private function getNotifyMessage()
56 | {
57 | $data = $this->pullRequest->getData();
58 |
59 | $notify = '';
60 | if ($this->pullRequest instanceof PullRequestCreated) {
61 | $notify .= sprintf("[info]");
62 | $notify .= sprintf("[title]Pull request has been created by %s. Please review(bow)[/title]", $data['author']['display_name']);
63 | $notify .= sprintf("[CREATED] #%d %s", $data['id'], $data['title']);
64 | if (strlen($data['description']) > 0) {
65 | $notify .= sprintf("\n%s", $data['description']);
66 | }
67 | $notify .= sprintf("\nhttps://bitbucket.org/%s/pull-request/%d", $data['destination']['repository']['full_name'], $data['id']);
68 | $notify .= sprintf("[/info]");
69 | } else if ($this->pullRequest instanceof PullRequestDeclined) {
70 | $notify .= sprintf("[info]");
71 | $notify .= sprintf("[title]Pull request has been declined by %s:([/title]", $data['author']['display_name']);
72 | $notify .= sprintf("[DECLINED] %s", $data['title']);
73 | $notify .= sprintf("[/info]");
74 | } else if ($this->pullRequest instanceof PullRequestCommentCreated) {
75 | $notify .= sprintf("[info]");
76 | $notify .= sprintf("[title]Comment was posted by %s(*)[/title]", $data['user']['display_name']);
77 | $notify .= sprintf("%s", $data['content']['raw']);
78 | $notify .= sprintf("\n%s", PullRequest::replaceUrlForLink($data['links']['html']['href']));
79 | $notify .= sprintf("[/info]");
80 | } else if ($this->pullRequest instanceof PullRequestMerged) {
81 | $notify .= sprintf("[info]");
82 | $notify .= sprintf("[title]Pull request has been merged by %s. Good job8-)[/title]", $data['author']['display_name']);
83 | $notify .= sprintf("[MERGED] %s", $data['title']);
84 | $notify .= sprintf("[/info]");
85 | } else if ($this->pullRequest instanceof PullRequestUpdated) {
86 | $notify .= sprintf("[info]");
87 | $notify .= sprintf("[title]Pull request has been updated by %s. Please re-review:p[/title]", $data['author']['display_name']);
88 | $notify .= sprintf("[UPDATED] %s", $data['title']);
89 | $notify .= sprintf("[/info]");
90 | } else {
91 | $notify = null;
92 | }
93 | return $notify;
94 | }
95 | }
--------------------------------------------------------------------------------
/lib/SplClassLoader.php:
--------------------------------------------------------------------------------
1 | .
19 | */
20 |
21 | /**
22 | * SplClassLoader implementation that implements the technical interoperability
23 | * standards for PHP 5.3 namespaces and class names.
24 | *
25 | * http://groups.google.com/group/php-standards/web/psr-0-final-proposal?pli=1
26 | *
27 | * // Example which loads classes for the Doctrine Common package in the
28 | * // Doctrine\Common namespace.
29 | * $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
30 | * $classLoader->register();
31 | *
32 | * @license http://www.opensource.org/licenses/mit-license.html MIT License
33 | * @author Jonathan H. Wage
34 | * @author Roman S. Borschel
35 | * @author Matthew Weier O'Phinney
36 | * @author Kris Wallsmith
37 | * @author Fabien Potencier
38 | */
39 | class SplClassLoader
40 | {
41 | private $_fileExtension = '.php';
42 | private $_namespace;
43 | private $_includePath;
44 | private $_namespaceSeparator = '\\';
45 |
46 | /**
47 | * Creates a new SplClassLoader that loads classes of the
48 | * specified namespace.
49 | *
50 | * @param string $ns The namespace to use.
51 | */
52 | public function __construct($ns = null, $includePath = null)
53 | {
54 | $this->_namespace = $ns;
55 | $this->_includePath = $includePath;
56 | }
57 |
58 | /**
59 | * Sets the namespace separator used by classes in the namespace of this class loader.
60 | *
61 | * @param string $sep The separator to use.
62 | */
63 | public function setNamespaceSeparator($sep)
64 | {
65 | $this->_namespaceSeparator = $sep;
66 | }
67 |
68 | /**
69 | * Gets the namespace seperator used by classes in the namespace of this class loader.
70 | *
71 | * @return void
72 | */
73 | public function getNamespaceSeparator()
74 | {
75 | return $this->_namespaceSeparator;
76 | }
77 |
78 | /**
79 | * Sets the base include path for all class files in the namespace of this class loader.
80 | *
81 | * @param string $includePath
82 | */
83 | public function setIncludePath($includePath)
84 | {
85 | $this->_includePath = $includePath;
86 | }
87 |
88 | /**
89 | * Gets the base include path for all class files in the namespace of this class loader.
90 | *
91 | * @return string $includePath
92 | */
93 | public function getIncludePath()
94 | {
95 | return $this->_includePath;
96 | }
97 |
98 | /**
99 | * Sets the file extension of class files in the namespace of this class loader.
100 | *
101 | * @param string $fileExtension
102 | */
103 | public function setFileExtension($fileExtension)
104 | {
105 | $this->_fileExtension = $fileExtension;
106 | }
107 |
108 | /**
109 | * Gets the file extension of class files in the namespace of this class loader.
110 | *
111 | * @return string $fileExtension
112 | */
113 | public function getFileExtension()
114 | {
115 | return $this->_fileExtension;
116 | }
117 |
118 | /**
119 | * Installs this class loader on the SPL autoload stack.
120 | */
121 | public function register()
122 | {
123 | spl_autoload_register(array($this, 'loadClass'));
124 | }
125 |
126 | /**
127 | * Uninstalls this class loader from the SPL autoloader stack.
128 | */
129 | public function unregister()
130 | {
131 | spl_autoload_unregister(array($this, 'loadClass'));
132 | }
133 |
134 | /**
135 | * Loads the given class or interface.
136 | *
137 | * @param string $className The name of the class to load.
138 | * @return void
139 | */
140 | public function loadClass($className)
141 | {
142 | if (null === $this->_namespace || $this->_namespace . $this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace . $this->_namespaceSeparator))) {
143 | $fileName = '';
144 | $namespace = '';
145 | if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
146 | $namespace = substr($className, 0, $lastNsPos);
147 | $className = substr($className, $lastNsPos + 1);
148 | $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
149 | }
150 | $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
151 |
152 | require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
153 | }
154 | }
155 | }
--------------------------------------------------------------------------------
/lib/BitbucketEventNotification/DestinationService/SlackService.php:
--------------------------------------------------------------------------------
1 | getNotifyMessage();
33 | $attachments = $this->getAttachments();
34 |
35 | /**
36 | * @var SlackApiClient $apiClient
37 | */
38 | $apiClient = $this->getApiClient();
39 | $response = $apiClient->postMessage($extendedParams['room_id'], $notifyMessage, $attachments);
40 |
41 | return $response;
42 | }
43 |
44 | /**
45 | * @inheritdoc
46 | */
47 | public function getApiClient()
48 | {
49 | return new SlackApiClient();
50 | }
51 |
52 | /**
53 | * Get notify message string for post.
54 | *
55 | * @return string|null null if failed
56 | */
57 | private function getNotifyMessage()
58 | {
59 | $data = $this->pullRequest->getData();
60 |
61 | $notify = '';
62 | if ($this->pullRequest instanceof PullRequestCreated) {
63 | $notify .= sprintf("Pull request has been created by %s. Please review:bow:", $data['author']['display_name']);
64 | $notify .= sprintf("\nhttps://bitbucket.org/%s/pull-request/%d", $data['destination']['repository']['full_name'], $data['id']);
65 | } else if ($this->pullRequest instanceof PullRequestDeclined) {
66 | $notify .= sprintf("Pull request has been declined by %s:disappointed:", $data['author']['display_name']);
67 | } else if ($this->pullRequest instanceof PullRequestCommentCreated) {
68 | $notify .= sprintf("Comment was posted by %s:star:", $data['user']['display_name']);
69 | $notify .= sprintf("\n%s", PullRequest::replaceUrlForLink($data['links']['html']['href']));
70 | } else if ($this->pullRequest instanceof PullRequestMerged) {
71 | $notify .= sprintf("Pull request has been merged by %s. Good job:sunglasses:", $data['author']['display_name']);
72 | } else if ($this->pullRequest instanceof PullRequestUpdated) {
73 | $notify .= sprintf("Pull request has been updated by %s. Please re-review:stuck_out_tongue:", $data['author']['display_name']);
74 | } else {
75 | $notify = null;
76 | }
77 | return $notify;
78 | }
79 |
80 |
81 | /**
82 | * Get attachments data.
83 | *
84 | * @return array
85 | */
86 | private function getAttachments()
87 | {
88 | $data = $this->pullRequest->getData();
89 |
90 | $fields = array();
91 |
92 | if ($this->pullRequest instanceof PullRequestCreated) {
93 | $fields[] = array(
94 | 'title' => 'Author',
95 | 'value' => $data['author']['display_name'],
96 | 'short' => true,
97 | );
98 | $fields[] = array(
99 | 'title' => 'Title',
100 | 'value' => sprintf("#%d %s", $data['id'], $data['title']),
101 | 'short' => true,
102 | );
103 | $fields[] = array(
104 | 'title' => 'Source',
105 | 'value' => $data['source']['branch']['name'],
106 | 'short' => true,
107 | );
108 | $fields[] = array(
109 | 'title' => 'Destination',
110 | 'value' => $data['destination']['branch']['name'],
111 | 'short' => true,
112 | );
113 | if (strlen($data['description']) > 0) {
114 | $fields[] = array(
115 | 'title' => 'Description',
116 | 'value' => sprintf("\n%s", $data['description']),
117 | 'short' => false,
118 | );
119 | }
120 | } else if ($this->pullRequest instanceof PullRequestDeclined) {
121 | $fields[] = array(
122 | 'title' => 'Author',
123 | 'value' => $data['author']['display_name'],
124 | 'short' => true,
125 | );
126 | $fields[] = array(
127 | 'title' => 'Title',
128 | 'value' => sprintf("%s", $data['title']),
129 | 'short' => true,
130 | );
131 | } else if ($this->pullRequest instanceof PullRequestCommentCreated) {
132 | $fields[] = array(
133 | 'title' => 'Author',
134 | 'value' => $data['user']['display_name'],
135 | 'short' => true,
136 | );
137 | $fields[] = array(
138 | 'title' => 'Content',
139 | 'value' => sprintf("%s", $data['content']['raw']),
140 | 'short' => true,
141 | );
142 | } else if ($this->pullRequest instanceof PullRequestMerged) {
143 | $fields[] = array(
144 | 'title' => 'Author',
145 | 'value' => $data['author']['display_name'],
146 | 'short' => true,
147 | );
148 | $fields[] = array(
149 | 'title' => 'Title',
150 | 'value' => sprintf("%s", $data['title']),
151 | 'short' => true,
152 | );
153 | } else if ($this->pullRequest instanceof PullRequestUpdated) {
154 | $fields[] = array(
155 | 'title' => 'Author',
156 | 'value' => $data['author']['display_name'],
157 | 'short' => true,
158 | );
159 | $fields[] = array(
160 | 'title' => 'Title',
161 | 'value' => sprintf("%s", $data['title']),
162 | 'short' => true,
163 | );
164 | } else {
165 | $notify = null;
166 | }
167 |
168 | $attachments = array(
169 | array(
170 | 'fields' => $fields
171 | )
172 | );
173 |
174 | return $attachments;
175 | }
176 |
177 | }
--------------------------------------------------------------------------------