├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── FbBotApp.php
├── LICENSE.txt
├── Menu
├── LocalizedMenu.php
└── MenuItem.php
├── Messages
├── AccountLink.php
├── Address.php
├── Adjustment.php
├── Attachment.php
├── AudioMessage.php
├── FileMessage.php
├── ImageMessage.php
├── Message.php
├── MessageButton.php
├── MessageDefaultAction.php
├── MessageElement.php
├── MessageMediaElement.php
├── MessageReceiptElement.php
├── QuickReply.php
├── QuickReplyButton.php
├── SenderAction.php
├── StructuredMessage.php
├── Summary.php
└── VideoMessage.php
├── README.md
├── UserProfile.php
├── composer.json
├── composer.lock
├── phpunit.xml.dist
└── tests
├── Mocks
├── Menu
│ ├── LocalizedMenu
│ │ ├── default.json
│ │ └── default_no_items.json
│ └── MenuItem
│ │ ├── nested.json
│ │ ├── postback.json
│ │ └── web.json
├── Messages
│ ├── AccountLink
│ │ ├── link.json
│ │ └── unlink.json
│ └── SenderAction
│ │ ├── mark_seen.json
│ │ ├── typing_off.json
│ │ └── typing_on.json
└── Response
│ └── User
│ └── user.json
└── TestCase
├── AbstractTestCase.php
├── Menu
├── LocalizedMenuTest.php
└── MenuItemTest.php
├── Messages
├── AccountLinkTest.php
└── SenderActionTest.php
└── UserProfile
└── UserProfileTest.php
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Would you like assistance or advice?
2 |
3 | Issue description
4 |
5 | Steps to reproduce
6 |
7 | Traceback or other info
8 |
9 | * fb-messenger-php version: x.x.x / master@commit
10 | * PHP version: x.x.x
11 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Fixes #[include a number of issue this PR is fixing].
2 |
3 | Summary of changes proposed in this Pull Request:
4 | -
5 | -
6 | -
7 |
8 | PR checklist:
9 | - [ ] Updated relevant documentation
10 | - [ ] Updated CHANGELOG.md
11 | - [ ] Added tests for my change
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### OSX template
3 | .DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | # Icon must end with two \r
8 | Icon
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear in the root of a volume
14 | .DocumentRevisions-V100
15 | .fseventsd
16 | .Spotlight-V100
17 | .TemporaryItems
18 | .Trashes
19 | .VolumeIcon.icns
20 |
21 | # Directories potentially created on remote AFP share
22 | .AppleDB
23 | .AppleDesktop
24 | Network Trash Folder
25 | Temporary Items
26 | .apdisk
27 | ### JetBrains template
28 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
29 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
30 |
31 | # User-specific stuff:
32 | .idea/workspace.xml
33 | .idea/tasks.xml
34 | .idea/dictionaries
35 | .idea/vcs.xml
36 | .idea/jsLibraryMappings.xml
37 |
38 | # Sensitive or high-churn files:
39 | .idea/dataSources.ids
40 | .idea/dataSources.xml
41 | .idea/dataSources.local.xml
42 | .idea/sqlDataSources.xml
43 | .idea/dynamic.xml
44 | .idea/uiDesigner.xml
45 |
46 | # Gradle:
47 | .idea/gradle.xml
48 | .idea/libraries
49 |
50 | # Mongo Explorer plugin:
51 | .idea/mongoSettings.xml
52 |
53 | ## File-based project format:
54 | *.iws
55 |
56 | ## Plugin-specific files:
57 |
58 | # IntelliJ
59 | /out/
60 |
61 | # mpeltonen/sbt-idea plugin
62 | .idea_modules/
63 |
64 | # JIRA plugin
65 | atlassian-ide-plugin.xml
66 |
67 | # Crashlytics plugin (for Android Studio and IntelliJ)
68 | com_crashlytics_export_strings.xml
69 | crashlytics.properties
70 | crashlytics-build.properties
71 | fabric.properties
72 |
73 | # composer
74 | /vendor/
75 | composer.phar
76 |
77 | # Project
78 | phpunit.phar
79 | .phpunit.result.cache
80 | phpunit.xml
81 | /build/
82 | .env
83 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | sudo: false
4 |
5 | php:
6 | - 7.1
7 | - 7.2
8 | - 7.3
9 |
10 | branches:
11 | only:
12 | - master
13 | - fb-travis-ci
14 |
15 | before_script:
16 | - travis_retry composer self-update
17 | - travis_retry composer install --no-interaction --prefer-source
18 |
19 | script:
20 | - vendor/bin/phpunit
21 |
22 | after_success:
23 | - bash <(curl -s https://codecov.io/bash)
24 |
25 | cache:
26 | directories:
27 | - $HOME/.composer/cache
28 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v1.2.3 (in development)
2 |
3 | ### New features & improvements:
4 | - Update required php version to 7.1.3 (https://www.php.net/supported-versions.php)
5 | - Add descriptions
6 | - Add tests
7 |
8 | ### Bug fixes:
9 | - Add missing ";"
10 |
11 | ## v1.2.2 (release date: 13th April 2019)
12 |
13 | ### New features & improvements:
14 | - Add appsecret_proof support
15 |
16 | ### Bug fixes:
17 | - Hotfixes in class FbBotApp
18 |
19 | ## v1.2.1 (release date: 04th April 2019)
20 |
21 | ### Bug fixes:
22 | - Add missing ";" to $apiVersion declaration in class FbBotApp
23 |
24 |
25 | ## v1.2 (release date: 02th April 2019)
26 |
27 | ### New features & improvements:
28 | - Add user_phone_number & user_email to QuickReplyButton.php
29 | - Add api version selection in the constructor of the class FbBotApp
30 |
31 |
32 | ## v1.1.1 (release date: 15th November 2018)
33 |
34 | ### Bug fixes:
35 | - removing last_ad_referral & is_payment_enabled from profile fields
36 |
37 | ## v1.1 (release date: 9th November 2018)
38 |
39 | ### Bug fixes:
40 | - Change NON_PROMOTIONAL_SUBSCRIPTION from type to tag
41 |
42 |
43 | ## v1.0 (release date: 12th May 2016)
44 |
45 | ### New features & improvements:
46 | - First stable version
47 |
--------------------------------------------------------------------------------
/FbBotApp.php:
--------------------------------------------------------------------------------
1 | token = $token;
71 |
72 | if (is_null($version)) {
73 | $version = $this->apiVersion;
74 | }
75 |
76 | if (!is_null($app_secret)) {
77 | $this->appsecret_proof = hash_hmac('sha256', $this->token, $app_secret);
78 | }
79 |
80 | $this->apiUrl = $this->baseApiUrl . $version . "/";
81 | }
82 |
83 | /**
84 | * Send Message
85 | *
86 | * @param Message $message
87 | * @return array
88 | */
89 | public function send($message)
90 | {
91 | return $this->call('me/messages', $message->getData());
92 | }
93 |
94 | public function batch($messages)
95 | {
96 | //Max 50 Requests per batch send
97 | $max_batch_count = 50;
98 | $count = 0;
99 | $data = [];
100 | $response = [];
101 |
102 | foreach ($messages as $message) {
103 |
104 | $message_data = $message->getData();
105 |
106 | $data['batch'][] = [
107 | "method" => "POST",
108 | "relative_url" => "me/messages",
109 | "body" => http_build_query($message_data)
110 | ];
111 |
112 | $count++;
113 |
114 |
115 | if ( $count === $max_batch_count ) {
116 | $data['batch'] = json_encode($data['batch']);
117 | $response = array_merge($response, $this->call('/', $data));
118 | $data['batch'] = [];
119 | $count = 0;
120 | }
121 |
122 | }
123 |
124 | //send out last batch
125 | if ( !empty($data['batch']) ) {
126 | $data['batch'] = json_encode($data['batch']);
127 | $response = array_merge($response, $this->call('me/messages', $data));
128 | }
129 |
130 | return $response;
131 | }
132 |
133 | public function batchIds($fb_ids, $message)
134 | {
135 | //Less resource intensive version
136 |
137 | //Max 50 Requests per batch send
138 | $max_batch_count = 50;
139 | $count = 0;
140 | $data = [];
141 | $response = [];
142 | $message_data = $message->getData();
143 |
144 | foreach ($fb_ids as $fb_id) {
145 |
146 | $message_data['recipient']['id'] = $fb_id;
147 |
148 | $data['batch'][] = [
149 | "method" => "POST",
150 | "relative_url" => "me/messages",
151 | "body" => http_build_query($message_data)
152 | ];
153 |
154 | $count++;
155 |
156 | if ( $count === $max_batch_count ) {
157 | $data['batch'] = json_encode($data['batch']);
158 | $response = array_merge($response, $this->call('/', $data));
159 | $data['batch'] = [];
160 | $count = 0;
161 | }
162 | }
163 |
164 | //send out last batch
165 | if ( !empty($data['batch']) ) {
166 | $data['batch'] = json_encode($data['batch']);
167 | $response = array_merge($response, $this->call('me/messages', $data));
168 | }
169 |
170 | return $response;
171 | }
172 |
173 | /**
174 | * Debugging Tool - Can accept an object, array, string, number
175 | *
176 | * @param Message $message
177 | * @return array
178 | */
179 | public function debug($fb_id, $message)
180 | {
181 |
182 | $responses = [];
183 |
184 | $maxlength = 2000;
185 |
186 | $length = strlen(json_encode( $message, JSON_UNESCAPED_SLASHES ) );
187 |
188 | $pages = ceil($length/$maxlength);
189 |
190 | for ($x=0; $x<$pages; $x++) {
191 |
192 | $responses[] = $this->send( new Message($fb_id,substr( json_encode( $message, JSON_UNESCAPED_SLASHES ), $x*$maxlength, $maxlength), false, "ISSUE_RESOLUTION", "REGULAR", "MESSAGE_TAG" ) );
193 |
194 | }
195 |
196 | return $responses;
197 |
198 | }
199 |
200 | /**
201 | * Upload File (image, audio, video, file)
202 | *
203 | * @see Attachment Reuse on https://developers.facebook.com/docs/messenger-platform/send-api-reference
204 | * @param Messages\Attachment $attachment
205 | * @return array contains attachment_id (if successfully uploaded).
206 | */
207 | public function upload($attachment)
208 | {
209 | $data = $attachment->getData();
210 | $data['attachment']['payload']['is_reusable'] = true;
211 | return $this->call('me/message_attachments',[
212 | 'message' => $data
213 | ], self::TYPE_POST);
214 | }
215 |
216 | /**
217 | * Get User Profile Info
218 | *
219 | * @param int $id
220 | * @param string $fields
221 | * @return UserProfile
222 | */
223 | public function userProfile($id, $fields = 'first_name,last_name,profile_pic,locale,timezone,gender')
224 | {
225 | return new UserProfile($this->call($id, [
226 | 'fields' => $fields
227 | ], self::TYPE_GET));
228 | }
229 |
230 | /**
231 | * Set Get Started Button
232 | *
233 | * @see https://developers.facebook.com/docs/messenger-platform/thread-settings/get-started-button
234 | * @param string $payload
235 | * @return array
236 | */
237 | public function setGetStartedButton($payload)
238 | {
239 | return $this->call('me/messenger_profile', [
240 | 'get_started' => ['payload' => $payload]
241 | ], self::TYPE_POST);
242 | }
243 |
244 | /**
245 | * Delete Get Started Button
246 | *
247 | * @see https://developers.facebook.com/docs/messenger-platform/thread-settings/get-started-button
248 | * @return array
249 | */
250 | public function deleteGetStartedButton()
251 | {
252 | return $this->call('me/messenger_profile', [
253 | 'fields' => ['get_started'],
254 | ], self::TYPE_DELETE);
255 | }
256 |
257 |
258 | /**
259 | * Set Greeting Message
260 | *
261 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/greeting-text
262 | * @param array $localizedGreetings
263 | * @return array
264 | */
265 | public function setGreetingText($localizedGreetings){
266 | return $this->call('me/messenger_profile', [
267 | 'greeting' => $localizedGreetings
268 | ], self::TYPE_POST);
269 | }
270 |
271 |
272 | /**
273 | * Delete Greeting Text
274 | *
275 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/greeting-text
276 | * @return array
277 | */
278 | public function deleteGreetingText()
279 | {
280 | return $this->call('me/messenger_profile', [
281 | 'fields' => ['greeting'],
282 | ], self::TYPE_DELETE);
283 | }
284 |
285 | /**
286 | * Get Greeting Text
287 | *
288 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/greeting-text
289 | * @return array
290 | */
291 | public function getGreetingText(){
292 | return $this->call('me/messenger_profile', [
293 | 'fields' => 'greeting',
294 | ], self::TYPE_GET);
295 | }
296 |
297 | /**
298 | * Set Target Audience
299 | *
300 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/target-audience
301 | * @param string $audience_type ("all", "custom", "none")
302 | * @param string $list_type ("whitelist", "blacklist")
303 | * @param array $countries_array
304 | * @return array
305 | */
306 | public function setTargetAudience($audience_type, $list_type=null, $countries_array=null){
307 |
308 | if ($audience_type === "custom") {
309 | return $this->call('me/messenger_profile', [
310 | 'target_audience' => [
311 | 'audience_type' => $audience_type,
312 | 'countries' => [
313 | $list_type => $countries_array
314 | ]
315 | ]
316 | ], self::TYPE_POST);
317 | } else {
318 | return $this->call('me/messenger_profile', [
319 | 'target_audience' => [
320 | 'audience_type' => $audience_type
321 | ]
322 | ], self::TYPE_POST);
323 | }
324 | }
325 |
326 | /**
327 | * Delete Target Audience
328 | *
329 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/target-audience
330 | * @return array
331 | */
332 | public function deleteTargetAudience()
333 | {
334 | return $this->call('me/messenger_profile', [
335 | 'fields' => ['target_audience'],
336 | ], self::TYPE_DELETE);
337 | }
338 |
339 | /**
340 | * Get Target Audience
341 | *
342 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/target-audience
343 | * @return array
344 | */
345 | public function getTargetAudience(){
346 | return $this->call('me/messenger_profile', [
347 | 'fields' => 'target_audience',
348 | ], self::TYPE_GET);
349 | }
350 |
351 | /**
352 | * Set Domain Whitelisting
353 | *
354 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/domain-whitelisting
355 | * @param array|string $domains
356 | * @return array
357 | */
358 | public function setDomainWhitelist($domains){
359 |
360 | if(!is_array($domains))
361 | $domains = array($domains);
362 |
363 | return $this->call('me/messenger_profile', [
364 | 'whitelisted_domains' => $domains
365 | ], self::TYPE_POST);
366 | }
367 |
368 | /**
369 | * Delete Domain Whitelisting
370 | *
371 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/domain-whitelisting
372 | * @return array
373 | */
374 | public function deleteDomainWhitelist()
375 | {
376 | return $this->call('me/messenger_profile', [
377 | 'fields' => ['whitelisted_domains'],
378 | ], self::TYPE_DELETE);
379 | }
380 |
381 | /**
382 | * Get Domain Whitelisting
383 | *
384 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/domain-whitelisting
385 | * @return array
386 | */
387 | public function getDomainWhitelist(){
388 | return $this->call('me/messenger_profile', [
389 | 'fields' => 'whitelisted_domains',
390 | ], self::TYPE_GET);
391 | }
392 |
393 | /**
394 | * Set Chat Extension Home URL
395 | *
396 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/home-url/
397 | * @param string $url
398 | * @param string $webview_height_ratio
399 | * @param string $webview_share_button
400 | * @param boolean $in_test
401 | * @return array
402 | */
403 | public function setHomeUrl($url, $webview_height_ratio = 'tall', $webview_share_button = 'hide', $in_test = false){
404 | return $this->call('me/messenger_profile', [
405 | 'home_url' => [
406 | 'url' => $url,
407 | 'webview_height_ratio' => $webview_height_ratio,
408 | 'webview_share_button' => $webview_share_button,
409 | 'in_test' => $in_test
410 | ]
411 | ], self::TYPE_POST);
412 | }
413 |
414 | /**
415 | * Delete Chat Extension Home Url
416 | *
417 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/home-url/
418 | * @return array
419 | */
420 | public function deleteHomeUrl()
421 | {
422 | return $this->call('me/messenger_profile', [
423 | 'fields' => ['home_url'],
424 | ], self::TYPE_DELETE);
425 | }
426 |
427 | /**
428 | * Get Chat Extension Home Url
429 | *
430 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/home-url/
431 | * @return array
432 | */
433 | public function getHomeUrl(){
434 | return $this->call('me/messenger_profile', [
435 | 'fields' => 'home_url',
436 | ], self::TYPE_GET);
437 | }
438 |
439 | /**
440 | * Set Nested Menu
441 | *
442 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/persistent-menu
443 | * @params $localizedMenu
444 | * @return array
445 | */
446 | public function setPersistentMenu($localizedMenu)
447 | {
448 | $elements = [];
449 |
450 | foreach ($localizedMenu as $menu) {
451 | $elements[] = $menu->getData();
452 | }
453 |
454 | return $this->call('me/messenger_profile', [
455 | 'persistent_menu' => $elements
456 | ], self::TYPE_POST);
457 | }
458 |
459 | /**
460 | * Get Nested Menu
461 | *
462 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/persistent-menu
463 | * @return array
464 | */
465 | public function getPersistentMenu()
466 | {
467 | return $this->call('me/messenger_profile', [
468 | 'fields' => 'persistent_menu',
469 | ], self::TYPE_GET);
470 | }
471 |
472 | /**
473 | * Remove Persistent Menu
474 | *
475 | * @see https://developers.facebook.com/docs/messenger-platform/messenger-profile/persistent-menu
476 | * @return array
477 | */
478 | public function deletePersistentMenu()
479 | {
480 | return $this->call('me/messenger_profile', [
481 | 'fields' => ['persistent_menu'],
482 | ], self::TYPE_DELETE);
483 | }
484 |
485 |
486 | /**
487 | * Set NLP Settings
488 | *
489 | * @see https://developers.facebook.com/docs/messenger-platform/built-in-nlp
490 | * @return array
491 | */
492 | public function setNLP($nlp_enabled = true, $model = 'ENGLISH', $custom_token = null, $verbose = false, $n_best = 1){
493 | return $this->call('me/nlp_configs', [
494 | 'nlp_enabled' => $nlp_enabled,
495 | 'model' => $model,
496 | 'custom_token' => $custom_token,
497 | 'verbose' => $verbose,
498 | 'n_best' => $n_best
499 | ], self::TYPE_POST);
500 | }
501 |
502 |
503 | /**
504 | * Messaging Insights API
505 | * Metrics = page_messages_active_threads_unique, page_messages_blocked_conversations_unique, page_messages_reported_conversations_unique
506 | * page_messages_reported_conversations_by_report_type_unique, page_messages_feedback_by_action_unique,
507 | *
508 | * @see https://developers.facebook.com/docs/messenger-platform/analytics#insights
509 | * @return array
510 | */
511 | public function getInsights($metric = 'page_messages_active_threads_unique'){
512 | return $this->call('me/insights', [
513 | 'metric' => $metric
514 | ], self::TYPE_GET);
515 | }
516 |
517 | /**
518 | * Request to API
519 | *
520 | * @access public
521 | * @param string $url
522 | * @param array $data
523 | * @param string $type Type of request (GET|POST|DELETE)
524 | * @return array
525 | */
526 | public function call($url, $data, $type = self::TYPE_POST)
527 | {
528 | $data['access_token'] = $this->token;
529 |
530 | if (!is_null($this->appsecret_proof)){
531 | $data['appsecret_proof'] = $this->appsecret_proof;
532 | }
533 |
534 | $headers = [
535 | 'Content-Type: application/json',
536 | ];
537 |
538 | if ($type == self::TYPE_GET) {
539 | $url .= '?'.http_build_query($data);
540 | }
541 |
542 | $process = curl_init($this->apiUrl.$url);
543 | curl_setopt($process, CURLOPT_HTTPHEADER, $headers);
544 | curl_setopt($process, CURLOPT_HEADER, false);
545 | curl_setopt($process, CURLOPT_TIMEOUT, 30);
546 |
547 | if($type == self::TYPE_POST || $type == self::TYPE_DELETE) {
548 | curl_setopt($process, CURLOPT_POST, 1);
549 | curl_setopt($process, CURLOPT_POSTFIELDS, json_encode($data));
550 | }
551 |
552 | if ($type == self::TYPE_DELETE) {
553 | curl_setopt($process, CURLOPT_CUSTOMREQUEST, "DELETE");
554 | }
555 |
556 | curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
557 | $return = curl_exec($process);
558 |
559 | /**
560 | * Check for cURL Errors and, if found display the error code
561 | *
562 | * @see http://php.net/manual/en/function.curl-error.php
563 | */
564 | $curl_error = curl_error($process);
565 | if ($curl_error) {
566 | $this->curl_error = $curl_error;
567 | }
568 |
569 | curl_close($process);
570 |
571 | return json_decode($return, true);
572 | }
573 |
574 | /**
575 | * Get the last cURL error if encountered
576 | *
577 | * @return null|string
578 | */
579 | public function getCurlError()
580 | {
581 | return $this->curl_error;
582 | }
583 | }
584 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/Menu/LocalizedMenu.php:
--------------------------------------------------------------------------------
1 | locale = $locale;
27 | $this->composer_input_disabled = $composer_input_disabled;
28 | $this->menuItems = $menuItems;
29 | }
30 |
31 | public function getData(){
32 | $result = [
33 | 'locale' => $this->locale,
34 | 'composer_input_disabled' => $this->composer_input_disabled
35 | ];
36 |
37 | if(isset($this->menuItems)){
38 | foreach ($this->menuItems as $menuItem){
39 | $result['call_to_actions'][] = $menuItem->getData();
40 | }
41 | }
42 | return $result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Menu/MenuItem.php:
--------------------------------------------------------------------------------
1 | type = $type;
85 | $this->title = $title;
86 | $this->data = $data;
87 |
88 | $this->webview_height_ratio = $webview_height_ratio;
89 | $this->messenger_extensions = $messenger_extensions;
90 | $this->fallback_url = $fallback_url;
91 | $this->webview_share_button = $webview_share_button;
92 |
93 | }
94 |
95 | /**
96 | * Get Button data
97 | *
98 | * @return array
99 | */
100 | public function getData()
101 | {
102 | $result['type'] = $this->type;
103 | $result['title'] = $this->title;
104 |
105 | switch($this->type)
106 | {
107 | case self::TYPE_POSTBACK:
108 | $result['payload'] = $this->data;
109 | break;
110 |
111 | case self::TYPE_WEB:
112 | $result['url'] = $this->data;
113 |
114 | if ($this->webview_height_ratio) {
115 | $result['webview_height_ratio'] = $this->webview_height_ratio;
116 | }
117 |
118 | if ($this->messenger_extensions){
119 | $result['messenger_extensions'] = $this->messenger_extensions;
120 | $result['fallback_url'] = $this->fallback_url;
121 | }
122 |
123 | if($this->webview_share_button){
124 | $result['webview_share_button'] = $this->webview_share_button;
125 | }
126 | break;
127 |
128 | case self::TYPE_NESTED:
129 | foreach ($this->data as $item) {
130 | $result['call_to_actions'][] = $item->getData();
131 | }
132 | break;
133 | }
134 | return $result;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/Messages/AccountLink.php:
--------------------------------------------------------------------------------
1 | title = $title;
56 | $this->subtitle = $subtitle;
57 | $this->url = $url;
58 | $this->image_url = $image_url;
59 | $this->logout = $logout;
60 | }
61 |
62 | /**
63 | * Get AccountLink data
64 | *
65 | * @return array
66 | */
67 | public function getData()
68 | {
69 | if($this->logout)
70 | {
71 | $buttons = new MessageButton(MessageButton::TYPE_ACCOUNT_UNLINK, '');
72 | }
73 | else
74 | {
75 | $buttons = new MessageButton(MessageButton::TYPE_ACCOUNT_LINK, '', $this->url);
76 | }
77 |
78 | $result = [
79 | 'title' => $this->title,
80 | 'subtitle' => $this->subtitle,
81 | 'image_url' => $this->image_url,
82 | 'buttons' => [$buttons->getData()]
83 | ];
84 |
85 | return $result;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Messages/Address.php:
--------------------------------------------------------------------------------
1 | data = $data;
25 | }
26 |
27 | /**
28 | * Get Data
29 | *
30 | * @return array
31 | */
32 | public function getData()
33 | {
34 | return $this->data;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Messages/Adjustment.php:
--------------------------------------------------------------------------------
1 | data = $data;
25 | }
26 |
27 | /**
28 | * Get Data
29 | *
30 | * @return array
31 | */
32 | public function getData()
33 | {
34 | return $this->data;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Messages/Attachment.php:
--------------------------------------------------------------------------------
1 | type = $type;
44 | $this->payload = $payload;
45 | $this->quick_replies = $quick_replies;
46 | }
47 |
48 | /**
49 | * @return string
50 | */
51 | public function getType()
52 | {
53 | return $this->type;
54 | }
55 |
56 | /**
57 | * @param string $type
58 | */
59 | public function setType($type)
60 | {
61 | $this->type = $type;
62 | }
63 |
64 | /**
65 | * @return array
66 | */
67 | public function getPayload()
68 | {
69 | return $this->payload;
70 | }
71 |
72 | /**
73 | * @param array $payload
74 | */
75 | public function setPayload($payload)
76 | {
77 | $this->payload = $payload;
78 | }
79 |
80 | /**
81 | * @return string
82 | */
83 | public function getFileData()
84 | {
85 | return $this->fileData;
86 | }
87 |
88 | /**
89 | * @param string $fileData
90 | */
91 | public function setFileData($fileData)
92 | {
93 | $this->fileData = $fileData;
94 | }
95 |
96 | /**
97 | * @return array
98 | */
99 | public function getData()
100 | {
101 | $data = [
102 | 'attachment' => [
103 | 'type' => $this->type,
104 | 'payload' => $this->payload
105 | ]
106 | ];
107 |
108 | foreach ($this->quick_replies as $qr) {
109 | $data['quick_replies'][] = $qr->getData();
110 | }
111 |
112 | if (!empty($this->fileData)) {
113 | $data['filedata'] = $this->fileData;
114 | }
115 | return $data;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/Messages/AudioMessage.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
35 | $this->text = $file;
36 | $this->quick_replies = $quick_replies;
37 | $this->notification_type = $notification_type;
38 | $this->messaging_type = $messaging_type;
39 | }
40 |
41 | /**
42 | * Get message data
43 | *
44 | * @return array
45 | */
46 | public function getData()
47 | {
48 | $res = [
49 | 'recipient' => [
50 | 'id' => $this->recipient
51 | ],
52 | 'notification_type'=> $this->notification_type,
53 | 'messaging_type' => $this->messaging_type
54 | ];
55 |
56 | $attachment = new Attachment(Attachment::TYPE_AUDIO, [], $this->quick_replies);
57 |
58 | if (strcmp(intval($this->text), $this->text) === 0) {
59 | $attachment->setPayload(array('attachment_id' => $this->text));
60 | } elseif (strpos($this->text, 'http://') === 0 || strpos($this->text, 'https://') === 0) {
61 | $attachment->setPayload(array('url' => $this->text));
62 | } else {
63 | $attachment->setFileData($this->getCurlValue($this->text, mime_content_type($this->text), basename($this->text)));
64 | }
65 |
66 | $res['message'] = $attachment->getData();
67 |
68 | return $res;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Messages/FileMessage.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
35 | $this->text = $file;
36 | $this->quick_replies = $quick_replies;
37 | $this->notification_type = $notification_type;
38 | $this->messaging_type = $messaging_type;
39 | }
40 |
41 | /**
42 | * Get message data
43 | *
44 | * @return array
45 | */
46 | public function getData()
47 | {
48 | $res = [
49 | 'recipient' => [
50 | 'id' => $this->recipient
51 | ],
52 | 'notification_type'=> $this->notification_type,
53 | 'messaging_type' => $this->messaging_type
54 | ];
55 |
56 | $attachment = new Attachment(Attachment::TYPE_FILE, [], $this->quick_replies);
57 |
58 | if (strcmp(intval($this->text), $this->text) === 0) {
59 | $attachment->setPayload(array('attachment_id' => $this->text));
60 | } elseif (strpos($this->text, 'http://') === 0 || strpos($this->text, 'https://') === 0) {
61 | $attachment->setPayload(array('url' => $this->text));
62 | } else {
63 | $attachment->setFileData($this->getCurlValue($this->text, mime_content_type($this->text), basename($this->text)));
64 | }
65 |
66 | $res['message'] = $attachment->getData();
67 |
68 | return $res;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Messages/ImageMessage.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
41 | $this->text = $file;
42 | $this->quick_replies = $quick_replies;
43 | $this->notification_type = $notification_type;
44 | $this->messaging_type = $messaging_type;
45 | }
46 |
47 | /**
48 | * Get message data
49 | *
50 | * @return array
51 | */
52 | public function getData()
53 | {
54 | $res = [
55 | 'recipient' => [
56 | 'id' => $this->recipient
57 | ],
58 | 'notification_type'=> $this->notification_type,
59 | 'messaging_type' => $this->messaging_type
60 | ];
61 |
62 | $attachment = new Attachment(Attachment::TYPE_IMAGE, [], $this->quick_replies);
63 |
64 | if (strcmp(intval($this->text), $this->text) === 0) {
65 | $attachment->setPayload(array('attachment_id' => $this->text));
66 | $res['message'] = $attachment->getData();
67 | } elseif (strpos($this->text, 'http://') === 0 || strpos($this->text, 'https://') === 0) {
68 | $attachment->setPayload(array('url' => $this->text));
69 | $res['message'] = $attachment->getData();
70 | } else {
71 | $attachment->setPayload(array('url' => basename($this->text)));
72 | $attachment->setFileData($this->getCurlValue($this->text, mime_content_type($this->text), basename($this->text)));
73 | $res['message'] = $attachment->getData();
74 | $res['filedata'] = $res['message']['filedata'];
75 | unset($res['message']['filedata']);
76 | }
77 |
78 | return $res;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Messages/Message.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
96 | $this->text = $text;
97 | $this->user_ref = $user_ref;
98 | $this->tag = $tag;
99 | $this->notification_type = $notification_type;
100 | $this->messaging_type = $messaging_type;
101 | $this->messaging_type = $messaging_type;
102 | }
103 |
104 | public function setTag($tag) {
105 | $this->tag = $tag;
106 | }
107 | /**
108 | * Get message data
109 | *
110 | * @return array
111 | */
112 | public function getData()
113 | {
114 | return [
115 | 'recipient' => $this->user_ref ? ['user_ref' => $this->recipient] : ['id' => $this->recipient],
116 | 'message' => [
117 | 'text' => $this->text
118 | ],
119 | 'tag'=> $this->tag,
120 | 'notification_type'=> $this->notification_type,
121 | 'messaging_type' => $this->messaging_type
122 | ];
123 | }
124 |
125 | /**
126 | * @param string $filename
127 | * @param string $contentType
128 | * @param string $postname
129 | * @return \CURLFile|string
130 | */
131 | protected function getCurlValue($filename, $contentType, $postname)
132 | {
133 | // PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
134 | // See: https://wiki.php.net/rfc/curl-file-upload
135 | if (function_exists('curl_file_create')) {
136 | return curl_file_create($filename, $contentType, $postname);
137 | }
138 |
139 | // Use the old style if using an older version of PHP
140 | $value = "@{$this->filename};filename=" . $postname;
141 | if ($contentType) {
142 | $value .= ';type=' . $contentType;
143 | }
144 |
145 | return $value;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Messages/MessageButton.php:
--------------------------------------------------------------------------------
1 | type = $type;
112 | $this->title = $title;
113 |
114 | $this->webview_height_ratio = $webview_height_ratio;
115 | $this->messenger_extensions = $messenger_extensions;
116 | $this->fallback_url = $fallback_url;
117 | $this->share_contents = $share_contents;
118 | $this->webview_share_button = $webview_share_button;
119 |
120 | if (!$url) {
121 | $url = $title;
122 | }
123 |
124 | $this->url = $url;
125 | }
126 |
127 | /**
128 | * Get Button data
129 | *
130 | * @return array
131 | */
132 | public function getData()
133 | {
134 | $result = [
135 | 'type' => $this->type
136 | ];
137 |
138 | switch($this->type)
139 | {
140 | case self::TYPE_POSTBACK:
141 | $result['title'] = $this->title;
142 | $result['payload'] = $this->url;
143 | break;
144 |
145 | case self::TYPE_CALL:
146 | $result['title'] = $this->title;
147 | $result['payload'] = $this->url;
148 | break;
149 |
150 | case self::TYPE_WEB:
151 | $result['title'] = $this->title;
152 | $result['url'] = $this->url;
153 |
154 | if ($this->webview_height_ratio) {
155 | $result['webview_height_ratio'] = $this->webview_height_ratio;
156 | }
157 |
158 | if ($this->messenger_extensions){
159 | $result['messenger_extensions'] = $this->messenger_extensions;
160 | $result['fallback_url'] = $this->fallback_url;
161 | }
162 |
163 | if($this->webview_share_button){
164 | $result['webview_share_button'] = $this->webview_share_button;
165 | }
166 | break;
167 |
168 | case self::TYPE_SHARE:
169 | //only share_contents needed
170 | if ($this->share_contents)
171 | $result['share_contents'] = $this->share_contents->getData();
172 | break;
173 |
174 | case self::TYPE_ACCOUNT_LINK:
175 | $result['url'] = $this->url;
176 | break;
177 |
178 | case self::TYPE_ACCOUNT_UNLINK:
179 | //only type needed
180 | break;
181 | }
182 |
183 | return $result;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/Messages/MessageDefaultAction.php:
--------------------------------------------------------------------------------
1 | type = self::TYPE_WEB;
60 |
61 | $this->webview_height_ratio = $webview_height_ratio;
62 | $this->messenger_extensions = $messenger_extensions;
63 | $this->fallback_url = $fallback_url;
64 | $this->url = $url;
65 | }
66 |
67 | /**
68 | * Get Button data
69 | *
70 | * @return array
71 | */
72 | public function getData()
73 | {
74 | $result = [
75 | 'type' => $this->type
76 | ];
77 |
78 | switch($this->type)
79 | {
80 |
81 | case self::TYPE_WEB:
82 | $result['url'] = $this->url;
83 |
84 | if ($this->webview_height_ratio) {
85 | $result['webview_height_ratio'] = $this->webview_height_ratio;
86 | }
87 |
88 | if ($this->messenger_extensions){
89 | $result['messenger_extensions'] = $this->messenger_extensions;
90 | $result['fallback_url'] = $this->fallback_url;
91 | }
92 | break;
93 |
94 | }
95 |
96 | return $result;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Messages/MessageElement.php:
--------------------------------------------------------------------------------
1 | title = $title;
66 | $this->subtitle = $subtitle;
67 | $this->url = $url;
68 | $this->image_url = $image_url;
69 | $this->buttons = $buttons;
70 | if (!empty($default_action)) {
71 | $this->default_action = $default_action;
72 | }
73 | }
74 |
75 | /**
76 | * Get Element data
77 | *
78 | * @return array
79 | */
80 | public function getData()
81 | {
82 | $result = [
83 | 'title' => $this->title,
84 | 'subtitle' => $this->subtitle,
85 | 'item_url' => $this->url,
86 | 'image_url' => $this->image_url,
87 | ];
88 |
89 | if (!empty($this->default_action)) {
90 | $result['default_action'] = $this->default_action;
91 | }
92 |
93 | if (!empty($this->buttons)) {
94 | $result['buttons'] = [];
95 |
96 | foreach ($this->buttons as $btn) {
97 | $result['buttons'][] = $btn->getData();
98 | }
99 | }
100 |
101 | return $result;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Messages/MessageMediaElement.php:
--------------------------------------------------------------------------------
1 | type = $type;
60 | $this->url = $url;
61 | $this->attachment_id = $attachment_id;
62 | $this->buttons = $buttons;
63 | }
64 |
65 | /**
66 | * Get Element data
67 | *
68 | * @return array
69 | */
70 | public function getData()
71 | {
72 | $result = [
73 | 'type' => $this->type,
74 | ];
75 |
76 | if (!empty($this->url)) {
77 | $result['url'] = $this->url;
78 | }
79 |
80 | if (!empty($this->attachment_id)) {
81 | $result['attachment_id'] = $this->attachment_id;
82 | }
83 |
84 | if (!empty($this->buttons)) {
85 | $result['buttons'] = [];
86 |
87 | foreach ($this->buttons as $btn) {
88 | $result['buttons'][] = $btn->getData();
89 | }
90 | }
91 |
92 | return $result;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Messages/MessageReceiptElement.php:
--------------------------------------------------------------------------------
1 | title = $title;
41 | $this->subtitle = $subtitle;
42 | $this->image_url = $image_url;
43 | $this->quantity = $quantity;
44 | $this->price = $price;
45 | $this->currency = $currency;
46 | }
47 |
48 | /**
49 | * @return array
50 | */
51 | public function getData()
52 | {
53 | return [
54 | 'title' => $this->title,
55 | 'subtitle' => $this->subtitle,
56 | 'image_url' => $this->image_url,
57 | 'quantity' => $this->quantity,
58 | 'price' => $this->price,
59 | 'currency' => $this->currency
60 | ];
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Messages/QuickReply.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
26 | $this->text = $text;
27 | $this->quick_replies = $quick_replies;
28 | $this->tag = $tag;
29 | $this->notification_type = $notification_type;
30 | $this->messaging_type = $messaging_type;
31 | }
32 |
33 | public function getData() {
34 | $result = [
35 | 'recipient' => [
36 | 'id' => $this->recipient
37 | ],
38 | 'message' => [
39 | 'text' => $this->text
40 | ],
41 | 'tag'=> $this->tag,
42 | 'notification_type'=> $this->notification_type,
43 | 'messaging_type' => $this->messaging_type
44 | ];
45 |
46 | foreach ($this->quick_replies as $qr) {
47 | if($qr instanceof QuickReplyButton){
48 | $result['message']['quick_replies'][] = $qr->getData();
49 | } else {
50 | $result['message']['quick_replies'][] = $qr;
51 | }
52 | }
53 |
54 | return $result;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Messages/QuickReplyButton.php:
--------------------------------------------------------------------------------
1 | type = $type;
69 | $this->title = $title;
70 | $this->payload = $payload;
71 | $this->image_url = $image_url;
72 |
73 | }
74 |
75 | /**
76 | * Get Button data
77 | *
78 | * @return array
79 | */
80 | public function getData()
81 | {
82 | $result = [
83 | 'content_type' => $this->type
84 | ];
85 |
86 | switch($this->type)
87 | {
88 | case self::TYPE_LOCATION:
89 | $result['image_url'] = $this->image_url;
90 | break;
91 |
92 | case self::TYPE_TEXT:
93 | $result['payload'] = $this->payload;
94 | $result['title'] = $this->title;
95 | $result['image_url'] = $this->image_url;
96 | break;
97 |
98 | case self::TYPE_USER_PHONE_NUMBER:
99 | $result['payload'] = $this->payload;
100 | break;
101 |
102 | case self::TYPE_USER_EMAIL:
103 | $result['payload'] = $this->payload;
104 | break;
105 | }
106 |
107 | return $result;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Messages/SenderAction.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
40 | $this->action = $action;
41 |
42 | }
43 |
44 | /**
45 | * Get message data
46 | *
47 | * @return array
48 | */
49 | public function getData()
50 | {
51 | return [
52 | 'recipient' => [
53 | 'id' => $this->recipient
54 | ],
55 | 'sender_action' => $this->action
56 | ];
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Messages/StructuredMessage.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
147 | $this->type = $type;
148 | $this->quick_replies = $quick_replies;
149 | $this->tag = $tag;
150 | $this->notification_type = $notification_type;
151 | $this->messaging_type = $messaging_type;
152 |
153 | switch ($type)
154 | {
155 | case self::TYPE_BUTTON:
156 | $this->title = $data['text'];
157 | $this->buttons = $data['buttons'];
158 | break;
159 |
160 | case self::TYPE_GENERIC:
161 | $this->elements = $data['elements'];
162 | //aspect ratio used to render images specified by image_url in element objects
163 | //default is horizontal
164 | if(isset($data['image_aspect_ratio'])) {
165 | $this->image_aspect_ratio = $data['image_aspect_ratio'];
166 | }
167 | break;
168 |
169 | case self::TYPE_MEDIA:
170 | $this->elements = $data['elements'];
171 | break;
172 |
173 | case self::TYPE_LIST:
174 | $this->elements = $data['elements'];
175 | //allowed is a sinle button for the whole list
176 | if(isset($data['buttons'])){
177 | $this->buttons = $data['buttons'];
178 | }
179 | //the top_element_style indicate if the first item is featured or not.
180 | //default is large
181 | if(isset($data['top_element_style'])){
182 | $this->top_element_style = $data['top_element_style'];
183 | }
184 | //if the top_element_style is large the first element image_url MUST be set.
185 | if($this->top_element_style == 'large' && (!isset($data['elements'][0]->getData()['image_url']) || $data['elements'][0]->getData()['image_url'] == '')){
186 | $message = 'Facbook require the image_url to be set for the first element if the top_element_style is large. set the image_url or change the top_element_style to compact.';
187 | throw new \Exception($message);
188 | }
189 | break;
190 |
191 | case self::TYPE_RECEIPT:
192 | $this->recipient_name = $data['recipient_name'];
193 | $this->order_number = $data['order_number'];
194 | $this->currency = $data['currency'];
195 | $this->payment_method = $data['payment_method'];
196 | $this->order_url = $data['order_url'];
197 | $this->timestamp = $data['timestamp'];
198 | $this->elements = $data['elements'];
199 | $this->address = $data['address'];
200 | $this->summary = $data['summary'];
201 | $this->adjustments = $data['adjustments'];
202 | break;
203 | }
204 | }
205 |
206 | /**
207 | * Get Data
208 | *
209 | * @return array
210 | */
211 | public function getData()
212 | {
213 |
214 | $result = [
215 | 'attachment' => [
216 | 'type' => 'template',
217 | 'payload' => [
218 | 'template_type' => $this->type
219 | ]
220 | ]
221 | ];
222 |
223 | if (is_array($this->quick_replies)) {
224 | foreach ($this->quick_replies as $qr) {
225 | if ($qr instanceof QuickReplyButton) {
226 | $result['quick_replies'][] = $qr->getData();
227 | }
228 | }
229 | }
230 |
231 | switch ($this->type)
232 | {
233 | case self::TYPE_BUTTON:
234 | $result['attachment']['payload']['text'] = $this->title;
235 | $result['attachment']['payload']['buttons'] = [];
236 |
237 | foreach ($this->buttons as $btn) {
238 | $result['attachment']['payload']['buttons'][] = $btn->getData();
239 | }
240 |
241 | break;
242 |
243 | case self::TYPE_GENERIC:
244 | $result['attachment']['payload']['elements'] = [];
245 | $result['attachment']['payload']['image_aspect_ratio'] = $this->image_aspect_ratio;
246 |
247 | foreach ($this->elements as $btn) {
248 | $result['attachment']['payload']['elements'][] = $btn->getData();
249 | }
250 | break;
251 |
252 | case self::TYPE_LIST:
253 | $result['attachment']['payload']['elements'] = [];
254 | $result['attachment']['payload']['top_element_style'] = $this->top_element_style;
255 | //list items button
256 | foreach ($this->elements as $btn) {
257 | $result['attachment']['payload']['elements'][] = $btn->getData();
258 | }
259 | //the whole list button
260 | foreach ($this->buttons as $btn) {
261 | $result['attachment']['payload']['buttons'][] = $btn->getData();
262 | }
263 | break;
264 |
265 | case self::TYPE_RECEIPT:
266 | $result['attachment']['payload']['recipient_name'] = $this->recipient_name;
267 | $result['attachment']['payload']['order_number'] = $this->order_number;
268 | $result['attachment']['payload']['currency'] = $this->currency;
269 | $result['attachment']['payload']['payment_method'] = $this->payment_method;
270 | $result['attachment']['payload']['order_url'] = $this->order_url;
271 | $result['attachment']['payload']['timestamp'] = $this->timestamp;
272 | $result['attachment']['payload']['elements'] = [];
273 |
274 | foreach ($this->elements as $btn) {
275 | $result['attachment']['payload']['elements'][] = $btn->getData();
276 | }
277 |
278 | $result['attachment']['payload']['address'] = $this->address->getData();
279 | $result['attachment']['payload']['summary'] = $this->summary->getData();
280 | $result['attachment']['payload']['adjustments'] = [];
281 |
282 | foreach ($this->adjustments as $btn) {
283 | $result['attachment']['payload']['adjustments'][] = $btn->getData();
284 | }
285 | break;
286 | }
287 |
288 |
289 | if ($this->recipient) {
290 | return [
291 | 'recipient' => [
292 | 'id' => $this->recipient
293 | ],
294 | 'message' => $result,
295 | 'tag' => $this->tag,
296 | 'notification_type'=> $this->notification_type,
297 | 'messaging_type' => $this->messaging_type
298 | ];
299 | } else {
300 | //share_contents only
301 | return [
302 | 'attachment' => $result['attachment']
303 | ];
304 | }
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/Messages/Summary.php:
--------------------------------------------------------------------------------
1 | data = $data;
25 | }
26 |
27 | /**
28 | * Get Data
29 | *
30 | * @return array
31 | */
32 | public function getData()
33 | {
34 | return $this->data;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Messages/VideoMessage.php:
--------------------------------------------------------------------------------
1 | recipient = $recipient;
35 | $this->text = $file;
36 | $this->quick_replies = $quick_replies;
37 | $this->notification_type = $notification_type;
38 | $this->messaging_type = $messaging_type;
39 | }
40 |
41 | /**
42 | * Get message data
43 | *
44 | * @return array
45 | */
46 | public function getData()
47 | {
48 | $res = [
49 | 'recipient' => [
50 | 'id' => $this->recipient
51 | ],
52 | 'notification_type'=> $this->notification_type,
53 | 'messaging_type' => $this->messaging_type
54 | ];
55 |
56 | $attachment = new Attachment(Attachment::TYPE_VIDEO, [], $this->quick_replies);
57 |
58 | if (strcmp(intval($this->text), $this->text) === 0) {
59 | $attachment->setPayload(array('attachment_id' => $this->text));
60 | } elseif (strpos($this->text, 'http://') === 0 || strpos($this->text, 'https://') === 0) {
61 | $attachment->setPayload(array('url' => $this->text));
62 | } else {
63 | $attachment->setFileData($this->getCurlValue($this->text, mime_content_type($this->text), basename($this->text)));
64 | }
65 |
66 | $res['message'] = $attachment->getData();
67 |
68 | return $res;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.com/pimax/fb-messenger-php)
2 | [](https://codecov.io/gh/pimax/fb-messenger-php)
3 |
4 | FB Messenger Bot PHP API
5 | ========================
6 |
7 | This is a PHP implementation for Facebook Messenger Bot API.
8 |
9 | REQUIREMENTS
10 | ------------
11 | The minimum requirement is that your Web server supports PHP 5.4.
12 |
13 | INSTALLATION
14 | ------------
15 |
16 | Version 1.2.2 is the last with PHP ">=5.4.0" support.
17 | **As of version 2.0, PHP 7.1.3 is required.**
18 |
19 | ```
20 | composer require "pimax/fb-messenger-php" "dev-master"
21 | composer require "pimax/fb-messenger-php" ""
22 | ```
23 |
24 | BASIC USAGE
25 | ------------
26 | See this repo - [https://github.com/pimax/fb-messenger-php-example](https://github.com/pimax/fb-messenger-php-example)
27 |
--------------------------------------------------------------------------------
/UserProfile.php:
--------------------------------------------------------------------------------
1 | data = $data;
12 | }
13 |
14 | public function getFirstName()
15 | {
16 | return isset($this->data['first_name']) ? $this->data['first_name'] : null;
17 | }
18 |
19 | public function getLastName()
20 | {
21 | return isset($this->data['last_name']) ? $this->data['last_name'] : null;
22 | }
23 |
24 | public function getPicture()
25 | {
26 | return isset($this->data['profile_pic']) ? $this->data['profile_pic'] : null;
27 | }
28 |
29 | public function getLocale()
30 | {
31 | return isset($this->data['locale']) ? $this->data['locale'] : null;
32 | }
33 |
34 | public function getTimezone()
35 | {
36 | return isset($this->data['timezone']) ? $this->data['timezone'] : null;
37 | }
38 |
39 | public function getGender()
40 | {
41 | return isset($this->data['gender']) ? $this->data['gender'] : null;
42 | }
43 |
44 | /**
45 | * Get Data
46 | *
47 | * @return array
48 | */
49 | public function getData()
50 | {
51 | return $this->data;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pimax/fb-messenger-php",
3 | "description": "Facebook Messenger Bot PHP API",
4 | "homepage": "https://github.com/pimax/fb-messenger-php",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Maksim Piniugin",
9 | "email": "m.pinyugin@gmail.com",
10 | "homepage": "https://maxpinyugin.com",
11 | "role": "Developer"
12 | }
13 | ],
14 | "require": {
15 | "php": "^7.1.3 || ^8.0 || ^8.1 || ^8.2"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "^7.3"
19 | },
20 | "autoload": {
21 | "psr-4": { "pimax\\": "" }
22 | },
23 | "scripts": {
24 | "test": "phpunit"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "fd8b0485d6bebcbff8757aa5f00d2135",
8 | "packages": [],
9 | "packages-dev": [
10 | {
11 | "name": "doctrine/instantiator",
12 | "version": "1.2.0",
13 | "source": {
14 | "type": "git",
15 | "url": "https://github.com/doctrine/instantiator.git",
16 | "reference": "a2c590166b2133a4633738648b6b064edae0814a"
17 | },
18 | "dist": {
19 | "type": "zip",
20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a",
21 | "reference": "a2c590166b2133a4633738648b6b064edae0814a",
22 | "shasum": ""
23 | },
24 | "require": {
25 | "php": "^7.1"
26 | },
27 | "require-dev": {
28 | "doctrine/coding-standard": "^6.0",
29 | "ext-pdo": "*",
30 | "ext-phar": "*",
31 | "phpbench/phpbench": "^0.13",
32 | "phpstan/phpstan-phpunit": "^0.11",
33 | "phpstan/phpstan-shim": "^0.11",
34 | "phpunit/phpunit": "^7.0"
35 | },
36 | "type": "library",
37 | "extra": {
38 | "branch-alias": {
39 | "dev-master": "1.2.x-dev"
40 | }
41 | },
42 | "autoload": {
43 | "psr-4": {
44 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
45 | }
46 | },
47 | "notification-url": "https://packagist.org/downloads/",
48 | "license": [
49 | "MIT"
50 | ],
51 | "authors": [
52 | {
53 | "name": "Marco Pivetta",
54 | "email": "ocramius@gmail.com",
55 | "homepage": "http://ocramius.github.com/"
56 | }
57 | ],
58 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
59 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
60 | "keywords": [
61 | "constructor",
62 | "instantiate"
63 | ],
64 | "time": "2019-03-17T17:37:11+00:00"
65 | },
66 | {
67 | "name": "myclabs/deep-copy",
68 | "version": "1.9.1",
69 | "source": {
70 | "type": "git",
71 | "url": "https://github.com/myclabs/DeepCopy.git",
72 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72"
73 | },
74 | "dist": {
75 | "type": "zip",
76 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
77 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
78 | "shasum": ""
79 | },
80 | "require": {
81 | "php": "^7.1"
82 | },
83 | "replace": {
84 | "myclabs/deep-copy": "self.version"
85 | },
86 | "require-dev": {
87 | "doctrine/collections": "^1.0",
88 | "doctrine/common": "^2.6",
89 | "phpunit/phpunit": "^7.1"
90 | },
91 | "type": "library",
92 | "autoload": {
93 | "psr-4": {
94 | "DeepCopy\\": "src/DeepCopy/"
95 | },
96 | "files": [
97 | "src/DeepCopy/deep_copy.php"
98 | ]
99 | },
100 | "notification-url": "https://packagist.org/downloads/",
101 | "license": [
102 | "MIT"
103 | ],
104 | "description": "Create deep copies (clones) of your objects",
105 | "keywords": [
106 | "clone",
107 | "copy",
108 | "duplicate",
109 | "object",
110 | "object graph"
111 | ],
112 | "time": "2019-04-07T13:18:21+00:00"
113 | },
114 | {
115 | "name": "phar-io/manifest",
116 | "version": "1.0.3",
117 | "source": {
118 | "type": "git",
119 | "url": "https://github.com/phar-io/manifest.git",
120 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
121 | },
122 | "dist": {
123 | "type": "zip",
124 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
125 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
126 | "shasum": ""
127 | },
128 | "require": {
129 | "ext-dom": "*",
130 | "ext-phar": "*",
131 | "phar-io/version": "^2.0",
132 | "php": "^5.6 || ^7.0"
133 | },
134 | "type": "library",
135 | "extra": {
136 | "branch-alias": {
137 | "dev-master": "1.0.x-dev"
138 | }
139 | },
140 | "autoload": {
141 | "classmap": [
142 | "src/"
143 | ]
144 | },
145 | "notification-url": "https://packagist.org/downloads/",
146 | "license": [
147 | "BSD-3-Clause"
148 | ],
149 | "authors": [
150 | {
151 | "name": "Arne Blankerts",
152 | "email": "arne@blankerts.de",
153 | "role": "Developer"
154 | },
155 | {
156 | "name": "Sebastian Heuer",
157 | "email": "sebastian@phpeople.de",
158 | "role": "Developer"
159 | },
160 | {
161 | "name": "Sebastian Bergmann",
162 | "email": "sebastian@phpunit.de",
163 | "role": "Developer"
164 | }
165 | ],
166 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
167 | "time": "2018-07-08T19:23:20+00:00"
168 | },
169 | {
170 | "name": "phar-io/version",
171 | "version": "2.0.1",
172 | "source": {
173 | "type": "git",
174 | "url": "https://github.com/phar-io/version.git",
175 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
176 | },
177 | "dist": {
178 | "type": "zip",
179 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
180 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
181 | "shasum": ""
182 | },
183 | "require": {
184 | "php": "^5.6 || ^7.0"
185 | },
186 | "type": "library",
187 | "autoload": {
188 | "classmap": [
189 | "src/"
190 | ]
191 | },
192 | "notification-url": "https://packagist.org/downloads/",
193 | "license": [
194 | "BSD-3-Clause"
195 | ],
196 | "authors": [
197 | {
198 | "name": "Arne Blankerts",
199 | "email": "arne@blankerts.de",
200 | "role": "Developer"
201 | },
202 | {
203 | "name": "Sebastian Heuer",
204 | "email": "sebastian@phpeople.de",
205 | "role": "Developer"
206 | },
207 | {
208 | "name": "Sebastian Bergmann",
209 | "email": "sebastian@phpunit.de",
210 | "role": "Developer"
211 | }
212 | ],
213 | "description": "Library for handling version information and constraints",
214 | "time": "2018-07-08T19:19:57+00:00"
215 | },
216 | {
217 | "name": "phpdocumentor/reflection-common",
218 | "version": "1.0.1",
219 | "source": {
220 | "type": "git",
221 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
222 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
223 | },
224 | "dist": {
225 | "type": "zip",
226 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
227 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
228 | "shasum": ""
229 | },
230 | "require": {
231 | "php": ">=5.5"
232 | },
233 | "require-dev": {
234 | "phpunit/phpunit": "^4.6"
235 | },
236 | "type": "library",
237 | "extra": {
238 | "branch-alias": {
239 | "dev-master": "1.0.x-dev"
240 | }
241 | },
242 | "autoload": {
243 | "psr-4": {
244 | "phpDocumentor\\Reflection\\": [
245 | "src"
246 | ]
247 | }
248 | },
249 | "notification-url": "https://packagist.org/downloads/",
250 | "license": [
251 | "MIT"
252 | ],
253 | "authors": [
254 | {
255 | "name": "Jaap van Otterdijk",
256 | "email": "opensource@ijaap.nl"
257 | }
258 | ],
259 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
260 | "homepage": "http://www.phpdoc.org",
261 | "keywords": [
262 | "FQSEN",
263 | "phpDocumentor",
264 | "phpdoc",
265 | "reflection",
266 | "static analysis"
267 | ],
268 | "time": "2017-09-11T18:02:19+00:00"
269 | },
270 | {
271 | "name": "phpdocumentor/reflection-docblock",
272 | "version": "4.3.1",
273 | "source": {
274 | "type": "git",
275 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
276 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c"
277 | },
278 | "dist": {
279 | "type": "zip",
280 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
281 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
282 | "shasum": ""
283 | },
284 | "require": {
285 | "php": "^7.0",
286 | "phpdocumentor/reflection-common": "^1.0.0",
287 | "phpdocumentor/type-resolver": "^0.4.0",
288 | "webmozart/assert": "^1.0"
289 | },
290 | "require-dev": {
291 | "doctrine/instantiator": "~1.0.5",
292 | "mockery/mockery": "^1.0",
293 | "phpunit/phpunit": "^6.4"
294 | },
295 | "type": "library",
296 | "extra": {
297 | "branch-alias": {
298 | "dev-master": "4.x-dev"
299 | }
300 | },
301 | "autoload": {
302 | "psr-4": {
303 | "phpDocumentor\\Reflection\\": [
304 | "src/"
305 | ]
306 | }
307 | },
308 | "notification-url": "https://packagist.org/downloads/",
309 | "license": [
310 | "MIT"
311 | ],
312 | "authors": [
313 | {
314 | "name": "Mike van Riel",
315 | "email": "me@mikevanriel.com"
316 | }
317 | ],
318 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
319 | "time": "2019-04-30T17:48:53+00:00"
320 | },
321 | {
322 | "name": "phpdocumentor/type-resolver",
323 | "version": "0.4.0",
324 | "source": {
325 | "type": "git",
326 | "url": "https://github.com/phpDocumentor/TypeResolver.git",
327 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
328 | },
329 | "dist": {
330 | "type": "zip",
331 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
332 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
333 | "shasum": ""
334 | },
335 | "require": {
336 | "php": "^5.5 || ^7.0",
337 | "phpdocumentor/reflection-common": "^1.0"
338 | },
339 | "require-dev": {
340 | "mockery/mockery": "^0.9.4",
341 | "phpunit/phpunit": "^5.2||^4.8.24"
342 | },
343 | "type": "library",
344 | "extra": {
345 | "branch-alias": {
346 | "dev-master": "1.0.x-dev"
347 | }
348 | },
349 | "autoload": {
350 | "psr-4": {
351 | "phpDocumentor\\Reflection\\": [
352 | "src/"
353 | ]
354 | }
355 | },
356 | "notification-url": "https://packagist.org/downloads/",
357 | "license": [
358 | "MIT"
359 | ],
360 | "authors": [
361 | {
362 | "name": "Mike van Riel",
363 | "email": "me@mikevanriel.com"
364 | }
365 | ],
366 | "time": "2017-07-14T14:27:02+00:00"
367 | },
368 | {
369 | "name": "phpspec/prophecy",
370 | "version": "1.8.0",
371 | "source": {
372 | "type": "git",
373 | "url": "https://github.com/phpspec/prophecy.git",
374 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
375 | },
376 | "dist": {
377 | "type": "zip",
378 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
379 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
380 | "shasum": ""
381 | },
382 | "require": {
383 | "doctrine/instantiator": "^1.0.2",
384 | "php": "^5.3|^7.0",
385 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
386 | "sebastian/comparator": "^1.1|^2.0|^3.0",
387 | "sebastian/recursion-context": "^1.0|^2.0|^3.0"
388 | },
389 | "require-dev": {
390 | "phpspec/phpspec": "^2.5|^3.2",
391 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
392 | },
393 | "type": "library",
394 | "extra": {
395 | "branch-alias": {
396 | "dev-master": "1.8.x-dev"
397 | }
398 | },
399 | "autoload": {
400 | "psr-0": {
401 | "Prophecy\\": "src/"
402 | }
403 | },
404 | "notification-url": "https://packagist.org/downloads/",
405 | "license": [
406 | "MIT"
407 | ],
408 | "authors": [
409 | {
410 | "name": "Konstantin Kudryashov",
411 | "email": "ever.zet@gmail.com",
412 | "homepage": "http://everzet.com"
413 | },
414 | {
415 | "name": "Marcello Duarte",
416 | "email": "marcello.duarte@gmail.com"
417 | }
418 | ],
419 | "description": "Highly opinionated mocking framework for PHP 5.3+",
420 | "homepage": "https://github.com/phpspec/prophecy",
421 | "keywords": [
422 | "Double",
423 | "Dummy",
424 | "fake",
425 | "mock",
426 | "spy",
427 | "stub"
428 | ],
429 | "time": "2018-08-05T17:53:17+00:00"
430 | },
431 | {
432 | "name": "phpunit/php-code-coverage",
433 | "version": "6.1.4",
434 | "source": {
435 | "type": "git",
436 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
437 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
438 | },
439 | "dist": {
440 | "type": "zip",
441 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
442 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
443 | "shasum": ""
444 | },
445 | "require": {
446 | "ext-dom": "*",
447 | "ext-xmlwriter": "*",
448 | "php": "^7.1",
449 | "phpunit/php-file-iterator": "^2.0",
450 | "phpunit/php-text-template": "^1.2.1",
451 | "phpunit/php-token-stream": "^3.0",
452 | "sebastian/code-unit-reverse-lookup": "^1.0.1",
453 | "sebastian/environment": "^3.1 || ^4.0",
454 | "sebastian/version": "^2.0.1",
455 | "theseer/tokenizer": "^1.1"
456 | },
457 | "require-dev": {
458 | "phpunit/phpunit": "^7.0"
459 | },
460 | "suggest": {
461 | "ext-xdebug": "^2.6.0"
462 | },
463 | "type": "library",
464 | "extra": {
465 | "branch-alias": {
466 | "dev-master": "6.1-dev"
467 | }
468 | },
469 | "autoload": {
470 | "classmap": [
471 | "src/"
472 | ]
473 | },
474 | "notification-url": "https://packagist.org/downloads/",
475 | "license": [
476 | "BSD-3-Clause"
477 | ],
478 | "authors": [
479 | {
480 | "name": "Sebastian Bergmann",
481 | "email": "sebastian@phpunit.de",
482 | "role": "lead"
483 | }
484 | ],
485 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
486 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
487 | "keywords": [
488 | "coverage",
489 | "testing",
490 | "xunit"
491 | ],
492 | "time": "2018-10-31T16:06:48+00:00"
493 | },
494 | {
495 | "name": "phpunit/php-file-iterator",
496 | "version": "2.0.2",
497 | "source": {
498 | "type": "git",
499 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
500 | "reference": "050bedf145a257b1ff02746c31894800e5122946"
501 | },
502 | "dist": {
503 | "type": "zip",
504 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
505 | "reference": "050bedf145a257b1ff02746c31894800e5122946",
506 | "shasum": ""
507 | },
508 | "require": {
509 | "php": "^7.1"
510 | },
511 | "require-dev": {
512 | "phpunit/phpunit": "^7.1"
513 | },
514 | "type": "library",
515 | "extra": {
516 | "branch-alias": {
517 | "dev-master": "2.0.x-dev"
518 | }
519 | },
520 | "autoload": {
521 | "classmap": [
522 | "src/"
523 | ]
524 | },
525 | "notification-url": "https://packagist.org/downloads/",
526 | "license": [
527 | "BSD-3-Clause"
528 | ],
529 | "authors": [
530 | {
531 | "name": "Sebastian Bergmann",
532 | "email": "sebastian@phpunit.de",
533 | "role": "lead"
534 | }
535 | ],
536 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
537 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
538 | "keywords": [
539 | "filesystem",
540 | "iterator"
541 | ],
542 | "time": "2018-09-13T20:33:42+00:00"
543 | },
544 | {
545 | "name": "phpunit/php-text-template",
546 | "version": "1.2.1",
547 | "source": {
548 | "type": "git",
549 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
550 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
551 | },
552 | "dist": {
553 | "type": "zip",
554 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
555 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
556 | "shasum": ""
557 | },
558 | "require": {
559 | "php": ">=5.3.3"
560 | },
561 | "type": "library",
562 | "autoload": {
563 | "classmap": [
564 | "src/"
565 | ]
566 | },
567 | "notification-url": "https://packagist.org/downloads/",
568 | "license": [
569 | "BSD-3-Clause"
570 | ],
571 | "authors": [
572 | {
573 | "name": "Sebastian Bergmann",
574 | "email": "sebastian@phpunit.de",
575 | "role": "lead"
576 | }
577 | ],
578 | "description": "Simple template engine.",
579 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
580 | "keywords": [
581 | "template"
582 | ],
583 | "time": "2015-06-21T13:50:34+00:00"
584 | },
585 | {
586 | "name": "phpunit/php-timer",
587 | "version": "2.1.1",
588 | "source": {
589 | "type": "git",
590 | "url": "https://github.com/sebastianbergmann/php-timer.git",
591 | "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059"
592 | },
593 | "dist": {
594 | "type": "zip",
595 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059",
596 | "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059",
597 | "shasum": ""
598 | },
599 | "require": {
600 | "php": "^7.1"
601 | },
602 | "require-dev": {
603 | "phpunit/phpunit": "^7.0"
604 | },
605 | "type": "library",
606 | "extra": {
607 | "branch-alias": {
608 | "dev-master": "2.1-dev"
609 | }
610 | },
611 | "autoload": {
612 | "classmap": [
613 | "src/"
614 | ]
615 | },
616 | "notification-url": "https://packagist.org/downloads/",
617 | "license": [
618 | "BSD-3-Clause"
619 | ],
620 | "authors": [
621 | {
622 | "name": "Sebastian Bergmann",
623 | "email": "sebastian@phpunit.de",
624 | "role": "lead"
625 | }
626 | ],
627 | "description": "Utility class for timing",
628 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
629 | "keywords": [
630 | "timer"
631 | ],
632 | "time": "2019-02-20T10:12:59+00:00"
633 | },
634 | {
635 | "name": "phpunit/php-token-stream",
636 | "version": "3.0.1",
637 | "source": {
638 | "type": "git",
639 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
640 | "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
641 | },
642 | "dist": {
643 | "type": "zip",
644 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
645 | "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
646 | "shasum": ""
647 | },
648 | "require": {
649 | "ext-tokenizer": "*",
650 | "php": "^7.1"
651 | },
652 | "require-dev": {
653 | "phpunit/phpunit": "^7.0"
654 | },
655 | "type": "library",
656 | "extra": {
657 | "branch-alias": {
658 | "dev-master": "3.0-dev"
659 | }
660 | },
661 | "autoload": {
662 | "classmap": [
663 | "src/"
664 | ]
665 | },
666 | "notification-url": "https://packagist.org/downloads/",
667 | "license": [
668 | "BSD-3-Clause"
669 | ],
670 | "authors": [
671 | {
672 | "name": "Sebastian Bergmann",
673 | "email": "sebastian@phpunit.de"
674 | }
675 | ],
676 | "description": "Wrapper around PHP's tokenizer extension.",
677 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
678 | "keywords": [
679 | "tokenizer"
680 | ],
681 | "time": "2018-10-30T05:52:18+00:00"
682 | },
683 | {
684 | "name": "phpunit/phpunit",
685 | "version": "7.5.9",
686 | "source": {
687 | "type": "git",
688 | "url": "https://github.com/sebastianbergmann/phpunit.git",
689 | "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160"
690 | },
691 | "dist": {
692 | "type": "zip",
693 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/134669cf0eeac3f79bc7f0c793efbc158bffc160",
694 | "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160",
695 | "shasum": ""
696 | },
697 | "require": {
698 | "doctrine/instantiator": "^1.1",
699 | "ext-dom": "*",
700 | "ext-json": "*",
701 | "ext-libxml": "*",
702 | "ext-mbstring": "*",
703 | "ext-xml": "*",
704 | "myclabs/deep-copy": "^1.7",
705 | "phar-io/manifest": "^1.0.2",
706 | "phar-io/version": "^2.0",
707 | "php": "^7.1",
708 | "phpspec/prophecy": "^1.7",
709 | "phpunit/php-code-coverage": "^6.0.7",
710 | "phpunit/php-file-iterator": "^2.0.1",
711 | "phpunit/php-text-template": "^1.2.1",
712 | "phpunit/php-timer": "^2.1",
713 | "sebastian/comparator": "^3.0",
714 | "sebastian/diff": "^3.0",
715 | "sebastian/environment": "^4.0",
716 | "sebastian/exporter": "^3.1",
717 | "sebastian/global-state": "^2.0",
718 | "sebastian/object-enumerator": "^3.0.3",
719 | "sebastian/resource-operations": "^2.0",
720 | "sebastian/version": "^2.0.1"
721 | },
722 | "conflict": {
723 | "phpunit/phpunit-mock-objects": "*"
724 | },
725 | "require-dev": {
726 | "ext-pdo": "*"
727 | },
728 | "suggest": {
729 | "ext-soap": "*",
730 | "ext-xdebug": "*",
731 | "phpunit/php-invoker": "^2.0"
732 | },
733 | "bin": [
734 | "phpunit"
735 | ],
736 | "type": "library",
737 | "extra": {
738 | "branch-alias": {
739 | "dev-master": "7.5-dev"
740 | }
741 | },
742 | "autoload": {
743 | "classmap": [
744 | "src/"
745 | ]
746 | },
747 | "notification-url": "https://packagist.org/downloads/",
748 | "license": [
749 | "BSD-3-Clause"
750 | ],
751 | "authors": [
752 | {
753 | "name": "Sebastian Bergmann",
754 | "email": "sebastian@phpunit.de",
755 | "role": "lead"
756 | }
757 | ],
758 | "description": "The PHP Unit Testing framework.",
759 | "homepage": "https://phpunit.de/",
760 | "keywords": [
761 | "phpunit",
762 | "testing",
763 | "xunit"
764 | ],
765 | "time": "2019-04-19T15:50:46+00:00"
766 | },
767 | {
768 | "name": "sebastian/code-unit-reverse-lookup",
769 | "version": "1.0.1",
770 | "source": {
771 | "type": "git",
772 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
773 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
774 | },
775 | "dist": {
776 | "type": "zip",
777 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
778 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
779 | "shasum": ""
780 | },
781 | "require": {
782 | "php": "^5.6 || ^7.0"
783 | },
784 | "require-dev": {
785 | "phpunit/phpunit": "^5.7 || ^6.0"
786 | },
787 | "type": "library",
788 | "extra": {
789 | "branch-alias": {
790 | "dev-master": "1.0.x-dev"
791 | }
792 | },
793 | "autoload": {
794 | "classmap": [
795 | "src/"
796 | ]
797 | },
798 | "notification-url": "https://packagist.org/downloads/",
799 | "license": [
800 | "BSD-3-Clause"
801 | ],
802 | "authors": [
803 | {
804 | "name": "Sebastian Bergmann",
805 | "email": "sebastian@phpunit.de"
806 | }
807 | ],
808 | "description": "Looks up which function or method a line of code belongs to",
809 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
810 | "time": "2017-03-04T06:30:41+00:00"
811 | },
812 | {
813 | "name": "sebastian/comparator",
814 | "version": "3.0.2",
815 | "source": {
816 | "type": "git",
817 | "url": "https://github.com/sebastianbergmann/comparator.git",
818 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
819 | },
820 | "dist": {
821 | "type": "zip",
822 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
823 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
824 | "shasum": ""
825 | },
826 | "require": {
827 | "php": "^7.1",
828 | "sebastian/diff": "^3.0",
829 | "sebastian/exporter": "^3.1"
830 | },
831 | "require-dev": {
832 | "phpunit/phpunit": "^7.1"
833 | },
834 | "type": "library",
835 | "extra": {
836 | "branch-alias": {
837 | "dev-master": "3.0-dev"
838 | }
839 | },
840 | "autoload": {
841 | "classmap": [
842 | "src/"
843 | ]
844 | },
845 | "notification-url": "https://packagist.org/downloads/",
846 | "license": [
847 | "BSD-3-Clause"
848 | ],
849 | "authors": [
850 | {
851 | "name": "Jeff Welch",
852 | "email": "whatthejeff@gmail.com"
853 | },
854 | {
855 | "name": "Volker Dusch",
856 | "email": "github@wallbash.com"
857 | },
858 | {
859 | "name": "Bernhard Schussek",
860 | "email": "bschussek@2bepublished.at"
861 | },
862 | {
863 | "name": "Sebastian Bergmann",
864 | "email": "sebastian@phpunit.de"
865 | }
866 | ],
867 | "description": "Provides the functionality to compare PHP values for equality",
868 | "homepage": "https://github.com/sebastianbergmann/comparator",
869 | "keywords": [
870 | "comparator",
871 | "compare",
872 | "equality"
873 | ],
874 | "time": "2018-07-12T15:12:46+00:00"
875 | },
876 | {
877 | "name": "sebastian/diff",
878 | "version": "3.0.2",
879 | "source": {
880 | "type": "git",
881 | "url": "https://github.com/sebastianbergmann/diff.git",
882 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
883 | },
884 | "dist": {
885 | "type": "zip",
886 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
887 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
888 | "shasum": ""
889 | },
890 | "require": {
891 | "php": "^7.1"
892 | },
893 | "require-dev": {
894 | "phpunit/phpunit": "^7.5 || ^8.0",
895 | "symfony/process": "^2 || ^3.3 || ^4"
896 | },
897 | "type": "library",
898 | "extra": {
899 | "branch-alias": {
900 | "dev-master": "3.0-dev"
901 | }
902 | },
903 | "autoload": {
904 | "classmap": [
905 | "src/"
906 | ]
907 | },
908 | "notification-url": "https://packagist.org/downloads/",
909 | "license": [
910 | "BSD-3-Clause"
911 | ],
912 | "authors": [
913 | {
914 | "name": "Kore Nordmann",
915 | "email": "mail@kore-nordmann.de"
916 | },
917 | {
918 | "name": "Sebastian Bergmann",
919 | "email": "sebastian@phpunit.de"
920 | }
921 | ],
922 | "description": "Diff implementation",
923 | "homepage": "https://github.com/sebastianbergmann/diff",
924 | "keywords": [
925 | "diff",
926 | "udiff",
927 | "unidiff",
928 | "unified diff"
929 | ],
930 | "time": "2019-02-04T06:01:07+00:00"
931 | },
932 | {
933 | "name": "sebastian/environment",
934 | "version": "4.2.1",
935 | "source": {
936 | "type": "git",
937 | "url": "https://github.com/sebastianbergmann/environment.git",
938 | "reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a"
939 | },
940 | "dist": {
941 | "type": "zip",
942 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/3095910f0f0fb155ac4021fc51a4a7a39ac04e8a",
943 | "reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a",
944 | "shasum": ""
945 | },
946 | "require": {
947 | "php": "^7.1"
948 | },
949 | "require-dev": {
950 | "phpunit/phpunit": "^7.5"
951 | },
952 | "suggest": {
953 | "ext-posix": "*"
954 | },
955 | "type": "library",
956 | "extra": {
957 | "branch-alias": {
958 | "dev-master": "4.2-dev"
959 | }
960 | },
961 | "autoload": {
962 | "classmap": [
963 | "src/"
964 | ]
965 | },
966 | "notification-url": "https://packagist.org/downloads/",
967 | "license": [
968 | "BSD-3-Clause"
969 | ],
970 | "authors": [
971 | {
972 | "name": "Sebastian Bergmann",
973 | "email": "sebastian@phpunit.de"
974 | }
975 | ],
976 | "description": "Provides functionality to handle HHVM/PHP environments",
977 | "homepage": "http://www.github.com/sebastianbergmann/environment",
978 | "keywords": [
979 | "Xdebug",
980 | "environment",
981 | "hhvm"
982 | ],
983 | "time": "2019-04-25T07:55:20+00:00"
984 | },
985 | {
986 | "name": "sebastian/exporter",
987 | "version": "3.1.0",
988 | "source": {
989 | "type": "git",
990 | "url": "https://github.com/sebastianbergmann/exporter.git",
991 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
992 | },
993 | "dist": {
994 | "type": "zip",
995 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
996 | "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
997 | "shasum": ""
998 | },
999 | "require": {
1000 | "php": "^7.0",
1001 | "sebastian/recursion-context": "^3.0"
1002 | },
1003 | "require-dev": {
1004 | "ext-mbstring": "*",
1005 | "phpunit/phpunit": "^6.0"
1006 | },
1007 | "type": "library",
1008 | "extra": {
1009 | "branch-alias": {
1010 | "dev-master": "3.1.x-dev"
1011 | }
1012 | },
1013 | "autoload": {
1014 | "classmap": [
1015 | "src/"
1016 | ]
1017 | },
1018 | "notification-url": "https://packagist.org/downloads/",
1019 | "license": [
1020 | "BSD-3-Clause"
1021 | ],
1022 | "authors": [
1023 | {
1024 | "name": "Jeff Welch",
1025 | "email": "whatthejeff@gmail.com"
1026 | },
1027 | {
1028 | "name": "Volker Dusch",
1029 | "email": "github@wallbash.com"
1030 | },
1031 | {
1032 | "name": "Bernhard Schussek",
1033 | "email": "bschussek@2bepublished.at"
1034 | },
1035 | {
1036 | "name": "Sebastian Bergmann",
1037 | "email": "sebastian@phpunit.de"
1038 | },
1039 | {
1040 | "name": "Adam Harvey",
1041 | "email": "aharvey@php.net"
1042 | }
1043 | ],
1044 | "description": "Provides the functionality to export PHP variables for visualization",
1045 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
1046 | "keywords": [
1047 | "export",
1048 | "exporter"
1049 | ],
1050 | "time": "2017-04-03T13:19:02+00:00"
1051 | },
1052 | {
1053 | "name": "sebastian/global-state",
1054 | "version": "2.0.0",
1055 | "source": {
1056 | "type": "git",
1057 | "url": "https://github.com/sebastianbergmann/global-state.git",
1058 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
1059 | },
1060 | "dist": {
1061 | "type": "zip",
1062 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
1063 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
1064 | "shasum": ""
1065 | },
1066 | "require": {
1067 | "php": "^7.0"
1068 | },
1069 | "require-dev": {
1070 | "phpunit/phpunit": "^6.0"
1071 | },
1072 | "suggest": {
1073 | "ext-uopz": "*"
1074 | },
1075 | "type": "library",
1076 | "extra": {
1077 | "branch-alias": {
1078 | "dev-master": "2.0-dev"
1079 | }
1080 | },
1081 | "autoload": {
1082 | "classmap": [
1083 | "src/"
1084 | ]
1085 | },
1086 | "notification-url": "https://packagist.org/downloads/",
1087 | "license": [
1088 | "BSD-3-Clause"
1089 | ],
1090 | "authors": [
1091 | {
1092 | "name": "Sebastian Bergmann",
1093 | "email": "sebastian@phpunit.de"
1094 | }
1095 | ],
1096 | "description": "Snapshotting of global state",
1097 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1098 | "keywords": [
1099 | "global state"
1100 | ],
1101 | "time": "2017-04-27T15:39:26+00:00"
1102 | },
1103 | {
1104 | "name": "sebastian/object-enumerator",
1105 | "version": "3.0.3",
1106 | "source": {
1107 | "type": "git",
1108 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1109 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
1110 | },
1111 | "dist": {
1112 | "type": "zip",
1113 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
1114 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
1115 | "shasum": ""
1116 | },
1117 | "require": {
1118 | "php": "^7.0",
1119 | "sebastian/object-reflector": "^1.1.1",
1120 | "sebastian/recursion-context": "^3.0"
1121 | },
1122 | "require-dev": {
1123 | "phpunit/phpunit": "^6.0"
1124 | },
1125 | "type": "library",
1126 | "extra": {
1127 | "branch-alias": {
1128 | "dev-master": "3.0.x-dev"
1129 | }
1130 | },
1131 | "autoload": {
1132 | "classmap": [
1133 | "src/"
1134 | ]
1135 | },
1136 | "notification-url": "https://packagist.org/downloads/",
1137 | "license": [
1138 | "BSD-3-Clause"
1139 | ],
1140 | "authors": [
1141 | {
1142 | "name": "Sebastian Bergmann",
1143 | "email": "sebastian@phpunit.de"
1144 | }
1145 | ],
1146 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1147 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1148 | "time": "2017-08-03T12:35:26+00:00"
1149 | },
1150 | {
1151 | "name": "sebastian/object-reflector",
1152 | "version": "1.1.1",
1153 | "source": {
1154 | "type": "git",
1155 | "url": "https://github.com/sebastianbergmann/object-reflector.git",
1156 | "reference": "773f97c67f28de00d397be301821b06708fca0be"
1157 | },
1158 | "dist": {
1159 | "type": "zip",
1160 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
1161 | "reference": "773f97c67f28de00d397be301821b06708fca0be",
1162 | "shasum": ""
1163 | },
1164 | "require": {
1165 | "php": "^7.0"
1166 | },
1167 | "require-dev": {
1168 | "phpunit/phpunit": "^6.0"
1169 | },
1170 | "type": "library",
1171 | "extra": {
1172 | "branch-alias": {
1173 | "dev-master": "1.1-dev"
1174 | }
1175 | },
1176 | "autoload": {
1177 | "classmap": [
1178 | "src/"
1179 | ]
1180 | },
1181 | "notification-url": "https://packagist.org/downloads/",
1182 | "license": [
1183 | "BSD-3-Clause"
1184 | ],
1185 | "authors": [
1186 | {
1187 | "name": "Sebastian Bergmann",
1188 | "email": "sebastian@phpunit.de"
1189 | }
1190 | ],
1191 | "description": "Allows reflection of object attributes, including inherited and non-public ones",
1192 | "homepage": "https://github.com/sebastianbergmann/object-reflector/",
1193 | "time": "2017-03-29T09:07:27+00:00"
1194 | },
1195 | {
1196 | "name": "sebastian/recursion-context",
1197 | "version": "3.0.0",
1198 | "source": {
1199 | "type": "git",
1200 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1201 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
1202 | },
1203 | "dist": {
1204 | "type": "zip",
1205 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
1206 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
1207 | "shasum": ""
1208 | },
1209 | "require": {
1210 | "php": "^7.0"
1211 | },
1212 | "require-dev": {
1213 | "phpunit/phpunit": "^6.0"
1214 | },
1215 | "type": "library",
1216 | "extra": {
1217 | "branch-alias": {
1218 | "dev-master": "3.0.x-dev"
1219 | }
1220 | },
1221 | "autoload": {
1222 | "classmap": [
1223 | "src/"
1224 | ]
1225 | },
1226 | "notification-url": "https://packagist.org/downloads/",
1227 | "license": [
1228 | "BSD-3-Clause"
1229 | ],
1230 | "authors": [
1231 | {
1232 | "name": "Jeff Welch",
1233 | "email": "whatthejeff@gmail.com"
1234 | },
1235 | {
1236 | "name": "Sebastian Bergmann",
1237 | "email": "sebastian@phpunit.de"
1238 | },
1239 | {
1240 | "name": "Adam Harvey",
1241 | "email": "aharvey@php.net"
1242 | }
1243 | ],
1244 | "description": "Provides functionality to recursively process PHP variables",
1245 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1246 | "time": "2017-03-03T06:23:57+00:00"
1247 | },
1248 | {
1249 | "name": "sebastian/resource-operations",
1250 | "version": "2.0.1",
1251 | "source": {
1252 | "type": "git",
1253 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
1254 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
1255 | },
1256 | "dist": {
1257 | "type": "zip",
1258 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
1259 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
1260 | "shasum": ""
1261 | },
1262 | "require": {
1263 | "php": "^7.1"
1264 | },
1265 | "type": "library",
1266 | "extra": {
1267 | "branch-alias": {
1268 | "dev-master": "2.0-dev"
1269 | }
1270 | },
1271 | "autoload": {
1272 | "classmap": [
1273 | "src/"
1274 | ]
1275 | },
1276 | "notification-url": "https://packagist.org/downloads/",
1277 | "license": [
1278 | "BSD-3-Clause"
1279 | ],
1280 | "authors": [
1281 | {
1282 | "name": "Sebastian Bergmann",
1283 | "email": "sebastian@phpunit.de"
1284 | }
1285 | ],
1286 | "description": "Provides a list of PHP built-in functions that operate on resources",
1287 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1288 | "time": "2018-10-04T04:07:39+00:00"
1289 | },
1290 | {
1291 | "name": "sebastian/version",
1292 | "version": "2.0.1",
1293 | "source": {
1294 | "type": "git",
1295 | "url": "https://github.com/sebastianbergmann/version.git",
1296 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
1297 | },
1298 | "dist": {
1299 | "type": "zip",
1300 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
1301 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
1302 | "shasum": ""
1303 | },
1304 | "require": {
1305 | "php": ">=5.6"
1306 | },
1307 | "type": "library",
1308 | "extra": {
1309 | "branch-alias": {
1310 | "dev-master": "2.0.x-dev"
1311 | }
1312 | },
1313 | "autoload": {
1314 | "classmap": [
1315 | "src/"
1316 | ]
1317 | },
1318 | "notification-url": "https://packagist.org/downloads/",
1319 | "license": [
1320 | "BSD-3-Clause"
1321 | ],
1322 | "authors": [
1323 | {
1324 | "name": "Sebastian Bergmann",
1325 | "email": "sebastian@phpunit.de",
1326 | "role": "lead"
1327 | }
1328 | ],
1329 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1330 | "homepage": "https://github.com/sebastianbergmann/version",
1331 | "time": "2016-10-03T07:35:21+00:00"
1332 | },
1333 | {
1334 | "name": "symfony/polyfill-ctype",
1335 | "version": "v1.11.0",
1336 | "source": {
1337 | "type": "git",
1338 | "url": "https://github.com/symfony/polyfill-ctype.git",
1339 | "reference": "82ebae02209c21113908c229e9883c419720738a"
1340 | },
1341 | "dist": {
1342 | "type": "zip",
1343 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
1344 | "reference": "82ebae02209c21113908c229e9883c419720738a",
1345 | "shasum": ""
1346 | },
1347 | "require": {
1348 | "php": ">=5.3.3"
1349 | },
1350 | "suggest": {
1351 | "ext-ctype": "For best performance"
1352 | },
1353 | "type": "library",
1354 | "extra": {
1355 | "branch-alias": {
1356 | "dev-master": "1.11-dev"
1357 | }
1358 | },
1359 | "autoload": {
1360 | "psr-4": {
1361 | "Symfony\\Polyfill\\Ctype\\": ""
1362 | },
1363 | "files": [
1364 | "bootstrap.php"
1365 | ]
1366 | },
1367 | "notification-url": "https://packagist.org/downloads/",
1368 | "license": [
1369 | "MIT"
1370 | ],
1371 | "authors": [
1372 | {
1373 | "name": "Symfony Community",
1374 | "homepage": "https://symfony.com/contributors"
1375 | },
1376 | {
1377 | "name": "Gert de Pagter",
1378 | "email": "BackEndTea@gmail.com"
1379 | }
1380 | ],
1381 | "description": "Symfony polyfill for ctype functions",
1382 | "homepage": "https://symfony.com",
1383 | "keywords": [
1384 | "compatibility",
1385 | "ctype",
1386 | "polyfill",
1387 | "portable"
1388 | ],
1389 | "time": "2019-02-06T07:57:58+00:00"
1390 | },
1391 | {
1392 | "name": "theseer/tokenizer",
1393 | "version": "1.1.2",
1394 | "source": {
1395 | "type": "git",
1396 | "url": "https://github.com/theseer/tokenizer.git",
1397 | "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8"
1398 | },
1399 | "dist": {
1400 | "type": "zip",
1401 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8",
1402 | "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8",
1403 | "shasum": ""
1404 | },
1405 | "require": {
1406 | "ext-dom": "*",
1407 | "ext-tokenizer": "*",
1408 | "ext-xmlwriter": "*",
1409 | "php": "^7.0"
1410 | },
1411 | "type": "library",
1412 | "autoload": {
1413 | "classmap": [
1414 | "src/"
1415 | ]
1416 | },
1417 | "notification-url": "https://packagist.org/downloads/",
1418 | "license": [
1419 | "BSD-3-Clause"
1420 | ],
1421 | "authors": [
1422 | {
1423 | "name": "Arne Blankerts",
1424 | "email": "arne@blankerts.de",
1425 | "role": "Developer"
1426 | }
1427 | ],
1428 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
1429 | "time": "2019-04-04T09:56:43+00:00"
1430 | },
1431 | {
1432 | "name": "webmozart/assert",
1433 | "version": "1.4.0",
1434 | "source": {
1435 | "type": "git",
1436 | "url": "https://github.com/webmozart/assert.git",
1437 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
1438 | },
1439 | "dist": {
1440 | "type": "zip",
1441 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
1442 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
1443 | "shasum": ""
1444 | },
1445 | "require": {
1446 | "php": "^5.3.3 || ^7.0",
1447 | "symfony/polyfill-ctype": "^1.8"
1448 | },
1449 | "require-dev": {
1450 | "phpunit/phpunit": "^4.6",
1451 | "sebastian/version": "^1.0.1"
1452 | },
1453 | "type": "library",
1454 | "extra": {
1455 | "branch-alias": {
1456 | "dev-master": "1.3-dev"
1457 | }
1458 | },
1459 | "autoload": {
1460 | "psr-4": {
1461 | "Webmozart\\Assert\\": "src/"
1462 | }
1463 | },
1464 | "notification-url": "https://packagist.org/downloads/",
1465 | "license": [
1466 | "MIT"
1467 | ],
1468 | "authors": [
1469 | {
1470 | "name": "Bernhard Schussek",
1471 | "email": "bschussek@gmail.com"
1472 | }
1473 | ],
1474 | "description": "Assertions to validate method input/output with nice error messages.",
1475 | "keywords": [
1476 | "assert",
1477 | "check",
1478 | "validate"
1479 | ],
1480 | "time": "2018-12-25T11:19:39+00:00"
1481 | }
1482 | ],
1483 | "aliases": [],
1484 | "minimum-stability": "stable",
1485 | "stability-flags": [],
1486 | "prefer-stable": false,
1487 | "prefer-lowest": false,
1488 | "platform": {
1489 | "php": "^7.1.3"
1490 | },
1491 | "platform-dev": []
1492 | }
1493 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/TestCase
15 |
16 |
17 |
18 |
19 |
20 | ./Messages
21 | ./Menu
22 | FbBotApp.php
23 | UserProfile.php
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/tests/Mocks/Menu/LocalizedMenu/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "locale": "default",
3 | "composer_input_disabled": false,
4 | "call_to_actions": [
5 | {
6 | "type": "postback",
7 | "title": "title_1",
8 | "payload": "PAYLOAD_1"
9 | },
10 | {
11 | "type": "postback",
12 | "title": "title_2",
13 | "payload": "PAYLOAD_2"
14 | },
15 | {
16 | "type": "postback",
17 | "title": "title_3",
18 | "payload": "PAYLOAD_3"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Mocks/Menu/LocalizedMenu/default_no_items.json:
--------------------------------------------------------------------------------
1 | {
2 | "locale": "default",
3 | "composer_input_disabled": false
4 | }
5 |
--------------------------------------------------------------------------------
/tests/Mocks/Menu/MenuItem/nested.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "nested",
3 | "title": "title",
4 | "call_to_actions": [
5 | {
6 | "type": "postback",
7 | "title": "title_1",
8 | "payload": "PAYLOAD_1"
9 | },
10 | {
11 | "type": "postback",
12 | "title": "title_2",
13 | "payload": "PAYLOAD_2"
14 | },
15 | {
16 | "type": "postback",
17 | "title": "title_3",
18 | "payload": "PAYLOAD_3"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Mocks/Menu/MenuItem/postback.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "postback",
3 | "title": "title",
4 | "payload": "PAYLOAD"
5 | }
6 |
--------------------------------------------------------------------------------
/tests/Mocks/Menu/MenuItem/web.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "web_url",
3 | "url": "https://github.com/pimax/fb-messenger-php/issues",
4 | "title": "title",
5 | "webview_height_ratio": "full",
6 | "messenger_extensions": true,
7 | "fallback_url": "https://github.com/pimax/fb-messenger-php",
8 | "webview_share_button": "hide"
9 | }
10 |
--------------------------------------------------------------------------------
/tests/Mocks/Messages/AccountLink/link.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "title",
3 | "subtitle": "subtitle",
4 | "image_url": "https://www.facebook.com/images/fb_icon_325x325.png",
5 | "buttons": [
6 | {
7 | "type": "account_link",
8 | "url": "https://www.example.com/oauth/authorize"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Mocks/Messages/AccountLink/unlink.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "title",
3 | "subtitle": "subtitle",
4 | "image_url": "https://www.facebook.com/images/fb_icon_325x325.png",
5 | "buttons": [
6 | {
7 | "type": "account_unlink"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/tests/Mocks/Messages/SenderAction/mark_seen.json:
--------------------------------------------------------------------------------
1 | {
2 | "recipient": {
3 | "id": "1234567890"
4 | },
5 | "sender_action": "mark_seen"
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Mocks/Messages/SenderAction/typing_off.json:
--------------------------------------------------------------------------------
1 | {
2 | "recipient": {
3 | "id": "1234567890"
4 | },
5 | "sender_action": "typing_off"
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Mocks/Messages/SenderAction/typing_on.json:
--------------------------------------------------------------------------------
1 | {
2 | "recipient": {
3 | "id": "1234567890"
4 | },
5 | "sender_action": "typing_on"
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Mocks/Response/User/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "first_name": "Peter",
3 | "last_name": "Chang",
4 | "profile_pic": "https://placeimg.com/200/200/nature",
5 | "locale": "en_US",
6 | "timezone": -7,
7 | "gender": "male"
8 | }
--------------------------------------------------------------------------------
/tests/TestCase/AbstractTestCase.php:
--------------------------------------------------------------------------------
1 | assertJsonStringEqualsJsonString($expectedJson, json_encode($localizedMenu->getData()));
29 | }
30 |
31 | public function testLocalizedMenuWithoutItems(): void
32 | {
33 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Menu/LocalizedMenu/default_no_items.json');
34 |
35 | $localizedMenu = new LocalizedMenu('default', false);
36 |
37 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($localizedMenu->getData()));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/TestCase/Menu/MenuItemTest.php:
--------------------------------------------------------------------------------
1 | assertJsonStringEqualsJsonString($expectedJson, json_encode($menuItem->getData()));
20 | }
21 |
22 | public function testItemWeb(): void
23 | {
24 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Menu/MenuItem/web.json');
25 |
26 | $menuItem = new MenuItem(
27 | MenuItem::TYPE_WEB,
28 | 'title',
29 | 'https://github.com/pimax/fb-messenger-php/issues',
30 | 'full',
31 | true,
32 | 'https://github.com/pimax/fb-messenger-php',
33 | 'hide'
34 | );
35 |
36 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($menuItem->getData()));
37 | }
38 |
39 | public function testItemNested(): void
40 | {
41 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Menu/MenuItem/nested.json');
42 |
43 | $menuItem = new MenuItem(
44 | MenuItem::TYPE_NESTED,
45 | 'title',
46 | [
47 | new MenuItem(MenuItem::TYPE_POSTBACK, 'title_1', 'PAYLOAD_1'),
48 | new MenuItem(MenuItem::TYPE_POSTBACK, 'title_2', 'PAYLOAD_2'),
49 | new MenuItem(MenuItem::TYPE_POSTBACK, 'title_3', 'PAYLOAD_3'),
50 | ]
51 | );
52 |
53 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($menuItem->getData()));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/TestCase/Messages/AccountLinkTest.php:
--------------------------------------------------------------------------------
1 | assertJsonStringEqualsJsonString($expectedJson, json_encode($accountLink->getData()));
26 | }
27 |
28 | public function testAccountUnlink(): void
29 | {
30 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Messages/AccountLink/unlink.json');
31 |
32 | $accountUnlink = new AccountLink(
33 | $title='title',
34 | $subtitle='subtitle',
35 | $url='',
36 | $image_url='https://www.facebook.com/images/fb_icon_325x325.png',
37 | $logout=true
38 | );
39 |
40 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($accountUnlink->getData()));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/TestCase/Messages/SenderActionTest.php:
--------------------------------------------------------------------------------
1 | assertJsonStringEqualsJsonString($expectedJson, json_encode($markSeen->getData()));
20 | }
21 |
22 | public function testTypingOn(): void
23 | {
24 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Messages/SenderAction/typing_on.json');
25 |
26 | $typingOn = new SenderAction('1234567890', SenderAction::ACTION_TYPING_ON);
27 |
28 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($typingOn->getData()));
29 | }
30 |
31 | public function testTypingOff(): void
32 | {
33 | $expectedJson = file_get_contents(__DIR__ . '/../../Mocks/Messages/SenderAction/typing_off.json');
34 |
35 | $typingOff = new SenderAction('1234567890', SenderAction::ACTION_TYPING_OFF);
36 |
37 | $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($typingOff->getData()));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/TestCase/UserProfile/UserProfileTest.php:
--------------------------------------------------------------------------------
1 | data = file_get_contents(__DIR__ . '/../../Mocks/Response/User/user.json');
23 |
24 | $this->userProfile = new UserProfile(json_decode($this->data, true));
25 | }
26 |
27 | public function testUserProfile(): void
28 | {
29 | $this->assertSame('Peter', $this->userProfile->getFirstName());
30 | $this->assertSame('Chang', $this->userProfile->getLastName());
31 | $this->assertSame('https://placeimg.com/200/200/nature', $this->userProfile->getPicture());
32 | $this->assertSame('en_US', $this->userProfile->getLocale());
33 | $this->assertSame(-7, $this->userProfile->getTimezone());
34 | $this->assertSame('male', $this->userProfile->getGender());
35 | }
36 |
37 | public function testUserProfileData(): void
38 | {
39 | $this->assertJsonStringEqualsJsonString($this->data, json_encode($this->userProfile->getData()));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------