├── .gitignore ├── README.md ├── composer.json ├── dns_example.php ├── example.php └── src ├── BunnyAPI.php ├── BunnyAPIDNS.php ├── BunnyAPIException.php ├── BunnyAPIPull.php ├── BunnyAPIStorage.php └── BunnyAPIStream.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | composer.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BunnyNET CDN API Class 2 | 3 | The most comprehensive, feature-packed and easy to use PHP class for [bunny.net](https://bunny.net?ref=qxdxfxutxf) ( 4 | BunnyCDN) pull, video streaming, DNS and storage zones [API](https://docs.bunny.net/reference/bunnynet-api-overview). 5 | 6 | This class whilst having a main focus on storage zone interaction includes pull zone features, DNS, Video streaming and 7 | more. Combining API with FTP managing and using your BunnyNet storage zones just got easier. 8 | 9 | [![Generic badge](https://img.shields.io/badge/version-1.9.7-blue.svg)]() 10 | [![Generic badge](https://img.shields.io/badge/PHP-8.2-purple.svg)]() 11 | 12 | ## Table of contents 13 | 14 | - [Features](#features) 15 | - [Installing & usage](#installing) 16 | - [Setting API key](#setting-api-key) 17 | - [Pullzone](#pullzone) 18 | - [List all pullzones](#list-pullzones) 19 | - [List a pullzone](#list-pullzone) 20 | - [Purge pullzone](#purge-pullzone) 21 | - [Delete pullzone](#delete-pullzone) 22 | - [List pullzone hostnames](#hostnames-pullzone) 23 | - [Add hostname to pullzone](#add-hostname-pullzone) 24 | - [Remove hostname from pullzone](#remove-hostname-pullzone) 25 | - [Change ssl status for pullzone](#ssl-pullzone) 26 | - [Add IP block for pullzone](#ip-block-pullzone) 27 | - [Remove IP block for pullzone](#ip-unblock-pullzone) 28 | - [List blocked IPs for pullzone](#ip-blocked-pullzone) 29 | - [Purge cache for a URL](#purge-url-pullzone) 30 | - [Pullzone logs are array](#logs-pullzone) 31 | - [Storage](#storage) 32 | - [Connect to storage zone](#storagezone-connect) 33 | - [List all storage zones](#storagezone-list) 34 | - [Add storage zone](#add-storagezone) 35 | - [Delete storage zone](#delete-storagezone) 36 | - [Get directory size](#get-directory-size) 37 | - [Return current directory](#current-directory) 38 | - [Change directory](#change-directory) 39 | - [Check folder exists](#folder-exists) 40 | - [Check file exists](#file-exists) 41 | - [Move to parent directory](#move-to-parent-directory) 42 | - [Create folder in current directory](#create-folder) 43 | - [Delete folder](#delete-folder) 44 | - [Delete file](#delete-file) 45 | - [Delete all files in a folder](#delete-all-files) 46 | - [Rename a file](#rename-file) 47 | - [Move a file](#move-file) 48 | - [Download a file](#download-file) 49 | - [Download all files in a directory](#download-all-files) 50 | - [Upload a file](#upload-file) 51 | - [Upload all files from a local folder](#upload-all-files) 52 | - [Return storage zone files and folder data](#return-file-folder-data) 53 | - [Return storage zone directory files formatted](#return-files-formatted) 54 | - [Return storage zone directory folders formatted](#return-folders-formatted) 55 | - [Return storage zone directory file and folders formatted](#return-file-folders-formatted) 56 | - [Video streaming](#video) 57 | - [Set video library](#set-video-library) 58 | - [Get video collections](#get-video-collection) 59 | - [Set video collection GUID](#get-video-collection) 60 | - [Get streams for collection](#get-streams-collection) 61 | - [Update stream collection](#update-stream-collection) 62 | - [Delete stream collection](#delete-stream-collection) 63 | - [Create stream collection](#create-stream-collection) 64 | - [List videos in library](#list-videos-library) 65 | - [Get video information](#get-video) 66 | - [Delete video](#delete-video) 67 | - [Create video](#create-video) 68 | - [Create video for collection](#create-video-collection) 69 | - [Upload video](#upload-video) 70 | - [Set thumbnail](#set-thumbnail) 71 | - [Get video resolutions](#video-resolutions) 72 | - [Get video size](#video-size) 73 | - [Add captions](#add-captions) 74 | - [Delete captions](#delete-captions) 75 | - [DNS](#dns) 76 | - [Get all DNS zones](#get-dns-zones) 77 | - [Get DNS zone](#get-dns-zone) 78 | - [Add DNS zone](#add-dns) 79 | - [Add DNS zone full](#add-dns-full) 80 | - [Delete DNS zone](#delete-dns) 81 | - [Get DNS zone statistics](#get-dns-stats) 82 | - [Update DNS zone nameservers](#update-nameservers) 83 | - [Update DNS zone SOA email](#update-soa-email) 84 | - [Add DNS record](#add-dns-record) 85 | - [Add DNS A record](#add-a-record) 86 | - [Add DNS AAAA record](#add-aaaa-record) 87 | - [Add DNS CNAME record](#add-cname-record) 88 | - [Add DNS MX record](#add-mx-record) 89 | - [Add DNS TXT record](#add-txt-record) 90 | - [Add DNS NS record](#add-ns-record) 91 | - [Add DNS redirect record](#add-redirect) 92 | - [Update DNS A record](#updated-a-record) 93 | - [Update DNS AAAA record](#update-aaaa-record) 94 | - [Disable DNS record](#disable-dns) 95 | - [Enable DNS record](#enable-dns) 96 | - [Delete DNS record](#delete-dns) 97 | - [Misc]() 98 | 99 | ### 1.9.7 changes 100 | #### 14th May 2024 101 | 102 | * Fixed dirSize() needing a slash 103 | * Fixed createFolder() throwing warning messages 104 | * Added fileExists() 105 | 106 | ### Requirements 107 | 108 | * PHP 8.2 109 | 110 | For Pull zone, billing and statistics API interaction you will need your BunnyNet API key, this is found in your 111 | dashboard in the My Account section. 112 | 113 | The video streaming API you need the video stream library access key which is found in the settings for the library at 114 | bunny.net. 115 | 116 | If you want to interact with storage zones you will need your BunnyCDN API key set and the name of the storage zone. 117 | 118 | You can get this with ```listStorageZones()``` as it returns all the storage zone data/info for the account. 119 | 120 | 121 | 122 | ## Features & abilities 123 | 124 | * List storage zones 125 | * Add/create storage zone 126 | * Delete storage zone 127 | * Create folder in storage zone 128 | * Delete folder in storage zone 129 | * Delete file in storage zone 130 | * Delete all files in a folder in storage zone 131 | * Download a file from storage zone 132 | * Download a file from storage zone with progress percentage 133 | * Download all files in a folder from storage zone 134 | * Upload file to storage zone 135 | * Upload file to storage zone with progress percentage 136 | * Upload all files in a folder to storage zone 137 | * Rename file or folder in storage zone 138 | * Move file in storage zone 139 | * Get file size in storage zone 140 | * Get directory size in storage zone 141 | * Navigate/List directories in storage zone 142 | * List all from storage zone directory 143 | * List all files formatted from storage zone directory 144 | * List all folders formatted from storage zone directory 145 | * List all formatted from storage zone directory 146 | * Create, edit and delete videos 147 | * Create, edit and delete DNS zones 148 | * Get usage statistics 149 | * Get billing data 150 | * View balance 151 | * View monthly charge 152 | * View monthly charge breakdown 153 | * Apply coupon code 154 | * List pull zones 155 | * Get pull zone 156 | * Add pull zone 157 | * Update pull zone 158 | * Delete pull zone 159 | * Purge pull zone 160 | * Add hostname to pull zone 161 | * Remove hostname from pull zone 162 | * Set force SSL for pull zone 163 | * List pull zone HTTP access logs 164 | * Calculate costs 165 | 166 | 167 | 168 | ## Usage 169 | 170 | Install with composer: 171 | 172 | ``` 173 | composer require corbpie/bunny-cdn-api 174 | ``` 175 | 176 | Use like: 177 | 178 | ```php 179 | require __DIR__ . '/vendor/autoload.php'; 180 | 181 | use Corbpie\BunnyCdn\BunnyAPIPull; 182 | 183 | $bunny = new BunnyAPIPull();//Initiate the class 184 | 185 | echo $bunny->listPullZones(); 186 | ``` 187 | 188 | #### Setting API key: 189 | 190 | **option 1 (preferred)** 191 | 192 | Line 12 ```bunnyAPI.php``` 193 | 194 | ```php 195 | const API_KEY = 'XXXX-XXXX-XXXX'; 196 | ``` 197 | 198 | **option 2** 199 | 200 | With ```apiKey()``` (needs setting with each calling of class) 201 | 202 | ```php 203 | $bunny->apiKey('XXXX-XXXX-XXXX');//Bunny api key 204 | ``` 205 | 206 | --- 207 | 208 | 209 | 210 | ### Storage zone interaction 211 | 212 | ```php 213 | require __DIR__ . '/vendor/autoload.php'; 214 | 215 | use Corbpie\BunnyCdn\BunnyAPIStorage; 216 | 217 | $bunny = new BunnyAPIStorage(); 218 | ``` 219 | 220 | --- 221 | 222 | Storage zone name and access key for storage zone interaction (**not needed if just using pull zone functions**) 223 | 224 | Set ```$access_key = ''``` to obtain key automatically (storage name must be accurate) 225 | 226 | 227 | ```php 228 | $bunny->zoneConnect($storagename, $access_key); 229 | ``` 230 | 231 | `$storagename` name of storage zone `string` 232 | 233 | `$access_key` key/password to storage zone ```string``` **optional** 234 | 235 | --- 236 | 237 | List storage zones 238 | 239 | 240 | ```php 241 | $bunny->listStorageZones(); 242 | ``` 243 | 244 | returns `array` 245 | 246 | --- 247 | 248 | Add a storage zone 249 | 250 | 251 | ```php 252 | $bunny->addStorageZone($newstoragezone); 253 | ``` 254 | 255 | `$newstoragezone` name of storage zone to create `string` 256 | 257 | --- 258 | 259 | Delete a storage zone 260 | 261 | 262 | ```php 263 | $bunny->deleteStorageZone($id); 264 | ``` 265 | 266 | `$id` id of storage zone to delete `int` 267 | 268 | --- 269 | 270 | Get directory size 271 | 272 | 273 | ```php 274 | $dir = "media/images/dogs"; 275 | 276 | $bunny->dirSize($dir); 277 | ``` 278 | 279 | `$dir` directory to get size of `string` 280 | 281 | --- 282 | 283 | Return current directory 284 | 285 | 286 | ```php 287 | $bunny->currentDir(); 288 | ``` 289 | 290 | returns `string` 291 | 292 | --- 293 | 294 | Change directory 295 | 296 | 297 | ```php 298 | $dir = "media/images/dogs"; 299 | 300 | $bunny->changeDir($dir); 301 | ``` 302 | 303 | `$dir` directory navigation (FTP rules) `string` 304 | 305 | --- 306 | 307 | Check folder exists 308 | 309 | 310 | ```php 311 | $bunny->folderExists($path); 312 | ``` 313 | 314 | `$path` the folder path `string` 315 | 316 | Returns `bool` 317 | 318 | --- 319 | 320 | Check file exists 321 | 322 | 323 | ```php 324 | $file = "media/images/dogs/collie.jpg"; 325 | 326 | $bunny->fileExists($file); 327 | ``` 328 | 329 | `$file` the full file path including the filename `string` 330 | 331 | Returns `bool` 332 | 333 | --- 334 | 335 | Move to the parent directory 336 | 337 | 338 | ```php 339 | $bunny->moveUpOne(); 340 | ``` 341 | 342 | --- 343 | 344 | Create a folder in the current directory 345 | 346 | 347 | ```php 348 | $new_folder = "dogs" 349 | 350 | $bunny->createFolder($new_folder); 351 | ``` 352 | 353 | `$new_folder` Create a folder in the current directory `string` 354 | 355 | --- 356 | 357 | Delete folder 358 | 359 | 360 | ```php 361 | $bunny->deleteFolder($folder_name); 362 | ``` 363 | 364 | `$folder_name` Name of the folder to delete (folder must be empty) `string` 365 | 366 | --- 367 | 368 | Delete a file 369 | 370 | 371 | ```php 372 | $bunny->deleteFile($name); 373 | ``` 374 | 375 | `$name` Name of file to delete `string` 376 | 377 | --- 378 | 379 | Delete all files in a folder 380 | 381 | 382 | ```php 383 | $bunny->deleteAllFiles($dir); 384 | ``` 385 | 386 | `$dir` Directory to delete all files in `string` 387 | 388 | --- 389 | 390 | Rename a file 391 | 392 | BunnyCDN does not allow for ftp_rename so file copied to a new name and then the old file is deleted. 393 | 394 | 395 | ```php 396 | $directory = "media/images/dogs"; 397 | $old_file_name = "collie.jpg"; 398 | $new_file_name = "poodle.jpg"; 399 | 400 | $bunny->renameFile($directory, $old_file_name, $new_file_name); 401 | ``` 402 | 403 | `$directory` Directory that contains the file `string` 404 | 405 | `$old_name` Object that is being renamed `string` 406 | 407 | `$new_name` New name for object `string` 408 | 409 | --- 410 | 411 | Move a file 412 | 413 | 414 | ```php 415 | $bunny->moveFile($file, $move_to); 416 | ``` 417 | 418 | `$file` File to move `string` 419 | 420 | `$move_to` Directory to move file to `string` 421 | 422 | --- 423 | 424 | Download a file 425 | 426 | 427 | ```php 428 | $bunny->downloadFile($save_as, $get_file, $mode); 429 | ``` 430 | 431 | `$save_as` Save file as `string` 432 | 433 | `$get_file` File to download `string` 434 | 435 | `$mode` FTP mode to use `INT` 436 | 437 | --- 438 | 439 | Download all files in a directory 440 | 441 | 442 | ```php 443 | $bunny->downloadAll($dir_dl_from, $dl_into, $mode); 444 | ``` 445 | 446 | `$dir_dl_from` Directory to download all from `string` 447 | 448 | `$dl_into` Download into `string` 449 | 450 | `$mode` FTP mode to use `INT` 451 | 452 | --- 453 | 454 | Upload a file 455 | 456 | 457 | ```php 458 | $bunny->uploadFile($upload, $upload_as, $mode); 459 | ``` 460 | 461 | `$upload` File to upload `string` 462 | 463 | `$upload_as` Upload as `string` 464 | 465 | `$mode` FTP mode to use `INT` 466 | 467 | --- 468 | 469 | Upload all files from a local folder 470 | 471 | 472 | ```php 473 | $bunny->uploadAllFiles($dir, $place, $mode); 474 | ``` 475 | 476 | `$dir` Upload all files from this directory `string` 477 | 478 | `$place` Upload to `string` 479 | 480 | `$mode` FTP mode to use `INT` 481 | 482 | --- 483 | 484 | Return storage zone files and folder data (Original) 485 | 486 | 487 | ```php 488 | $bunny->listAllOG(); 489 | ``` 490 | 491 | returns `array` 492 | 493 | --- 494 | 495 | Return storage zone directory files formatted 496 | 497 | 498 | ```php 499 | $bunny->listFiles($location); 500 | ``` 501 | 502 | `$location` Directory to get and return data `string` 503 | 504 | returns `array` 505 | 506 | --- 507 | 508 | Return storage zone directory folders formatted 509 | 510 | 511 | ```php 512 | $bunny->listFolders($location); 513 | ``` 514 | 515 | `$location` Directory to get and return data `string` 516 | 517 | returns `array` 518 | 519 | --- 520 | 521 | Return storage zone directory file and folders formatted 522 | 523 | 524 | ```php 525 | $bunny->listAll($location); 526 | ``` 527 | 528 | `$location` Directory to get and return data `string` 529 | 530 | returns `array` 531 | 532 | --- 533 | 534 | 535 | List all pull zones and data 536 | 537 | ```php 538 | $bunny->listPullZones(); 539 | ``` 540 | 541 | returns `array` 542 | 543 | --- 544 | 545 | List pull zones data for id 546 | 547 | ```php 548 | $bunny->pullZoneData($id); 549 | ``` 550 | 551 | `$id` Pull zone to get data from `int` 552 | 553 | returns `array` 554 | 555 | --- 556 | 557 | Purge pull zone data 558 | 559 | ```php 560 | $bunny->purgePullZone($id); 561 | ``` 562 | 563 | `$id` Pull zone to purge `int` 564 | 565 | --- 566 | 567 | Delete pull zone data 568 | 569 | ```php 570 | $bunny->deletePullZone($id); 571 | ``` 572 | 573 | `$id` Pull zone to delete `int` 574 | 575 | --- 576 | 577 | Lists pullzone hostnames and amount 578 | 579 | ```php 580 | $bunny->pullZoneHostnames($pullzone_id); 581 | ``` 582 | 583 | --- 584 | 585 | Add hostname to pull zone 586 | 587 | ```php 588 | $bunny->addHostnamePullZone($id, $hostname); 589 | ``` 590 | 591 | `$id` Pull zone hostname will be added to `int` 592 | 593 | `$hostname` Hostname to add `string` 594 | 595 | --- 596 | 597 | Remove a hostname from pull zone 598 | 599 | ```php 600 | $bunny->removeHostnamePullZone($id, $hostname); 601 | ``` 602 | 603 | `$id` Pull zone hostname be removed from `int` 604 | 605 | `$hostname` Hostname to remove `string` 606 | 607 | --- 608 | 609 | Change force SSL status for pull zone 610 | 611 | ```php 612 | $bunny->forceSSLPullZone($id, $hostname, $force_ssl); 613 | ``` 614 | 615 | `$id` Pull zone hostname change status `int` 616 | 617 | `$hostname` Affected hostname `string` 618 | 619 | `$force_ssl` True = on, FALSE = off `bool` 620 | 621 | --- 622 | 623 | Add ip to block for pullzone 624 | 625 | ```php 626 | $bunny->addBlockedIpPullZone($pullzone_id, $ip, $db_log = false); 627 | ``` 628 | 629 | --- 630 | 631 | Un block an ip for pullzone 632 | 633 | ```php 634 | $bunny->unBlockedIpPullZone($pullzone_id, $ip, $db_log = false); 635 | ``` 636 | 637 | --- 638 | 639 | List all blocked ip's for pullzone 640 | 641 | ```php 642 | $bunny->listBlockedIpPullZone($pullzone_id); 643 | ``` 644 | 645 | --- 646 | 647 | Purge cache for a URL 648 | 649 | ```php 650 | $bunny->purgeCache($url, $async = false); 651 | ``` 652 | 653 | `$url` Purge cache for this url `string` 654 | 655 | `$async` Dont wait for the purge before returning result `bool` 656 | 657 | --- 658 | 659 | Pull zone logs as formatted array 660 | 661 | ```php 662 | $bunny->pullZoneLogs($id, $date); 663 | ``` 664 | 665 | `$id` Pull zone id `int` 666 | 667 | `$date` Date for logs, only past 3 days (mm-dd-yy) `string` 668 | 669 | --- 670 | 671 | Get usage statistics 672 | 673 | ```php 674 | $bunny->getStatistics(); 675 | ``` 676 | 677 | returns `array` 678 | 679 | --- 680 | 681 | Get billing data 682 | 683 | ```php 684 | $bunny->getBilling(); 685 | ``` 686 | 687 | returns `array` 688 | 689 | --- 690 | 691 | Get account balance 692 | 693 | ```php 694 | $bunny->balance(); 695 | ``` 696 | 697 | returns `float` 698 | 699 | --- 700 | 701 | Get monthly charge 702 | 703 | ```php 704 | $bunny->monthCharges(); 705 | ``` 706 | 707 | returns `float` 708 | 709 | --- 710 | 711 | Get monthly charge breakdown for region 712 | 713 | ```php 714 | $bunny->monthChargeBreakdown(); 715 | ``` 716 | 717 | returns `array` 718 | 719 | --- 720 | 721 | Lists total billing amount and first date time 722 | 723 | ```php 724 | $bunny->totalBillingAmount(); 725 | ``` 726 | 727 | returns `array` 728 | 729 | --- 730 | 731 | Apply a coupon code 732 | 733 | ```php 734 | $bunny->applyCoupon($code); 735 | ``` 736 | 737 | --- 738 | 739 | Set Json header 740 | 741 | ```php 742 | $bunny->jsonHeader(); 743 | ``` 744 | 745 | --- 746 | 747 | Convert/format bytes to other data types 748 | 749 | ```php 750 | $bunny->convertBytes($bytes, $convert_to = 'GB', $format = true, $decimals = 2); 751 | ``` 752 | 753 | --- 754 | 755 | Convert bool to int value 756 | 757 | ```php 758 | $bunny->boolToInt($bool); 759 | ``` 760 | 761 | returns `int` 762 | 763 | --- 764 | 765 | Close connection (Optional) 766 | 767 | ```php 768 | $bunny->closeConnection(); 769 | ``` 770 | 771 | --- 772 | 773 | 774 | ### Video streaming zone interaction 775 | 776 | Calling and setting stream library access key 777 | 778 | ```php 779 | require __DIR__ . '/vendor/autoload.php'; 780 | 781 | use Corbpie\BunnyCdn\BunnyAPIStream; 782 | 783 | $bunny = new BunnyAPIStream(); 784 | 785 | $bunny->streamLibraryAccessKey('XXXX-XXXXX-XXXX-XXXX'); 786 | 787 | //Or set stream library access key at line 14 in BunnyAPI.php 788 | ``` 789 | 790 | --- 791 | 792 | **You can only get the video library id from your bunny.net stream library page** 793 | 794 | Set video stream library id 795 | 796 | ```php 797 | $bunny->setStreamLibraryId($library_id); 798 | ``` 799 | 800 | `$library_id` stream library id `int` 801 | 802 | --- 803 | 804 | Get video collections 805 | 806 | Requires ```setStreamLibraryId()``` to be set. 807 | 808 | ```php 809 | $bunny->getVideoCollections(); 810 | ``` 811 | 812 | --- 813 | 814 | Set video collection guid 815 | 816 | ```php 817 | $bunny->setStreamCollectionGuid($collection_guid); 818 | ``` 819 | 820 | `$collection_guid` video collection guid `string` 821 | 822 | --- 823 | Set video guid 824 | 825 | ```php 826 | $bunny->setStreamVideoGuid($video_guid); 827 | ``` 828 | 829 | `$video_guid` video guid `string` 830 | 831 | --- 832 | 833 | Get video collections for library id 834 | 835 | Requires ```setStreamLibraryId()``` to be set. 836 | 837 | ```php 838 | $bunny->getStreamCollections($page, $items_pp,$order_by); 839 | ``` 840 | 841 | `$page` page number `int` 842 | 843 | `$items_pp` items to show `int` 844 | 845 | `$order_by` order by `string` 846 | 847 | --- 848 | 849 | Get streams for a collection 850 | 851 | Requires ```setStreamLibraryId()``` and ```setStreamCollectionGuid()``` to be set. 852 | 853 | ```php 854 | $bunny->getStreamForCollection(); 855 | ``` 856 | 857 | --- 858 | 859 | Update stream collection 860 | 861 | Requires ```setStreamLibraryId()``` and ```setStreamCollectionGuid()``` to be set. 862 | 863 | ```php 864 | $bunny->updateCollection($updated_collection_name); 865 | ``` 866 | 867 | `$updated_collection_name` the name to update video collection to `string` 868 | 869 | --- 870 | 871 | Delete stream collection 872 | 873 | Requires ```setStreamLibraryId()``` and ```setStreamCollectionGuid()``` to be set. 874 | 875 | ```php 876 | $bunny->deleteCollection(); 877 | ``` 878 | 879 | --- 880 | 881 | Create stream collection 882 | 883 | Requires ```setStreamLibraryId()``` to be set. 884 | 885 | ```php 886 | $bunny->createCollection($new_collection_name); 887 | ``` 888 | 889 | `$new_collection_name` the name for your new video collection `string` 890 | 891 | --- 892 | 893 | List videos for library 894 | 895 | Requires ```setStreamLibraryId()``` to be set. 896 | 897 | ```php 898 | $bunny->listVideos($collection_guid); 899 | ``` 900 | 901 | `$collection_guid` video collection guid `string` 902 | 903 | --- 904 | 905 | Get video information 906 | 907 | Requires ```setStreamLibraryId()``` to be set. 908 | 909 | ```php 910 | $bunny->getVideo($collection_guid); 911 | ``` 912 | 913 | `$collection_guid` video collection guid `string` 914 | 915 | --- 916 | 917 | Delete video 918 | 919 | Requires ```setStreamLibraryId()``` to be set. 920 | 921 | ```php 922 | $bunny->deleteVideo($collection_guid); 923 | ``` 924 | 925 | `$library_id` library id `int` 926 | 927 | `$collection_guid` video collection guid `string` 928 | 929 | --- 930 | 931 | Create video 932 | 933 | Requires ```setStreamLibraryId()``` to be set. 934 | 935 | ```php 936 | $bunny->createVideo($video_title); 937 | ``` 938 | 939 | `$video_title` video title `string` 940 | 941 | 942 | --- 943 | 944 | Create video for collection 945 | 946 | Requires ```setStreamLibraryId()``` and ```setStreamCollectionGuid()``` to be set. 947 | 948 | ```php 949 | $bunny->createVideoForCollection($video_title); 950 | ``` 951 | 952 | `$video_title` video title `string` 953 | 954 | --- 955 | 956 | Upload video 957 | 958 | Requires ```setStreamLibraryId()``` to be set. 959 | 960 | Need to use ```createVideo()``` first to get video guid 961 | 962 | ```php 963 | $bunny->uploadVideo($video_guid, $video_to_upload); 964 | ``` 965 | 966 | `$video_guid` video guid `string` 967 | 968 | `$video_to_upload` video filename `string` 969 | 970 | --- 971 | 972 | Set thumbnail for video 973 | 974 | Requires ```setStreamLibraryId()``` to be set. 975 | 976 | ```php 977 | $bunny->setThumbnail($video_guid, $thumbnail_url); 978 | ``` 979 | 980 | `$video_guid` video guid `string` 981 | 982 | `$thumbnail_url` image url `string` 983 | 984 | --- 985 | 986 | Get video resolutions 987 | 988 | Requires ```setStreamLibraryId()``` to be set. 989 | 990 | ```php 991 | $bunny->videoResolutionsArray($video_guid); 992 | ``` 993 | 994 | --- 995 | 996 | Get video size 997 | 998 | Requires ```setStreamLibraryId()``` to be set. 999 | 1000 | ```php 1001 | $bunny->videoSize($video_guid); 1002 | ``` 1003 | 1004 | --- 1005 | 1006 | Add captions 1007 | 1008 | Requires ```setStreamLibraryId()``` to be set. 1009 | 1010 | ```php 1011 | $bunny->addCaptions($video_guid, $collection_guid, $label, $captions_file); 1012 | ``` 1013 | 1014 | `$video_guid` video guid `string` 1015 | 1016 | `$srclang` caption srclang `string` 1017 | 1018 | `$label` label for captions `string` 1019 | 1020 | `$captions_file` caption file URL `string` 1021 | 1022 | --- 1023 | 1024 | Delete captions 1025 | 1026 | Requires ```setStreamLibraryId()``` to be set. 1027 | 1028 | ```php 1029 | $bunny->deleteCaptions($library_id, $video_guid, $srclang); 1030 | ``` 1031 | 1032 | `$video_guid` video guid `string` 1033 | 1034 | `$srclang` captions srclang `string` 1035 | 1036 | --- 1037 | 1038 | ### DNS zone interaction 1039 | 1040 | 1041 | ```php 1042 | require __DIR__ . '/vendor/autoload.php'; 1043 | 1044 | use Corbpie\BunnyCdn\BunnyAPIDNS; 1045 | 1046 | $bunny = new BunnyAPIDNS(); 1047 | 1048 | ``` 1049 | 1050 | --- 1051 | 1052 | 1053 | Get DNS all zones 1054 | 1055 | ```php 1056 | $bunny->getDNSZones(); 1057 | ``` 1058 | 1059 | `$library_id` stream library id `int` 1060 | 1061 | --- 1062 | 1063 | Get DNS zone 1064 | 1065 | ```php 1066 | $bunny->getDNSZone($zone_id); 1067 | ``` 1068 | 1069 | `$zone_id` DNS zone id `int` 1070 | 1071 | --- 1072 | 1073 | 1074 | Add a DNS zone 1075 | 1076 | ```php 1077 | $bunny->addDNSZone($domain, $logging); 1078 | ``` 1079 | 1080 | `$domain` domain name `string` 1081 | `$logging` use logging `bool` 1082 | 1083 | --- 1084 | 1085 | 1086 | Add a DNS zone full 1087 | 1088 | ```php 1089 | $parameters = array( 1090 | 'Domain' => 'zonedomain.com', 'NameserversDetected' => true, 'CustomNameserversEnabled' => true, 1091 | 'Nameserver1' => 'customns1.com', 'Nameserver2' => 'customns2.com', 'SoaEmail' => 'contact@zonedomain.com', 1092 | 'DateModified' => '2022-08-18 23:59:59', 'DateCreated' => '2022-08-18 23:59:59', 'NameserversNextCheck' => '2022-08-28 23:59:59', 1093 | 'LoggingEnabled' => true, 'LoggingIPAnonymizationEnabled' => true 1094 | ); 1095 | $bunny->addDNSZoneFull($parameters); 1096 | ``` 1097 | 1098 | `$parameters` parameters to create `array` 1099 | 1100 | --- 1101 | 1102 | 1103 | Delete DNS zone 1104 | 1105 | ```php 1106 | $bunny->deleteDNSZone($zone_id); 1107 | ``` 1108 | 1109 | `$zone_id` DNS zone id `int` 1110 | 1111 | --- 1112 | 1113 | 1114 | DNS zone statistics 1115 | 1116 | ```php 1117 | $bunny->getDNSZoneStatistics($zone_id); 1118 | ``` 1119 | 1120 | `$zone_id` DNS zone id `int` 1121 | 1122 | --- 1123 | 1124 | 1125 | Update DNS nameservers 1126 | 1127 | ```php 1128 | $bunny->updateDNSZoneNameservers($zone_id, $custom_ns, $ns_one, $ns_two); 1129 | ``` 1130 | 1131 | `$zone_id` DNS zone id `int` 1132 | `$custom_ns` use custom nameservers `bool` 1133 | `$ns_one` NS one `string` 1134 | `$ns_two` NS two `string` 1135 | 1136 | --- 1137 | 1138 | 1139 | Update DNS SOA email 1140 | 1141 | ```php 1142 | $bunny->updateDNSZoneNameservers($zone_id, $soa_email); 1143 | ``` 1144 | 1145 | `$zone_id` DNS zone id `int` 1146 | `$soa_email` NS one `string` 1147 | 1148 | --- 1149 | 1150 | 1151 | Add a DNS record by using parameters https://docs.bunny.net/reference/dnszonepublic_addrecord 1152 | 1153 | ```php 1154 | $parameters = array('Type' => 0, 'Ttl' => 120, 'Accelerated' => true, 'Weight' => 200); 1155 | $bunny->addDNSRecord($zone_id, $name, $value, $parameters); 1156 | ``` 1157 | 1158 | `$zone_id` DNS zone id `int` 1159 | `$name` name `string` 1160 | `$value` IP address `string` 1161 | `$parameters` `array` 1162 | 1163 | --- 1164 | 1165 | 1166 | Add DNS A record 1167 | 1168 | ```php 1169 | $bunny->addDNSRecordA($zone_id, $hostname, $ipv4); 1170 | ``` 1171 | 1172 | `$zone_id` DNS zone id `int` 1173 | `$hostname` hostname `string` 1174 | `$ipv4` IPv4 address `string` 1175 | 1176 | --- 1177 | 1178 | 1179 | Add DNS AAAA record 1180 | 1181 | ```php 1182 | $bunny->addDNSRecordAAAA($zone_id, $hostname, $ipv6); 1183 | ``` 1184 | 1185 | `$zone_id` DNS zone id `int` 1186 | `$hostname` hostname `string` 1187 | `$ipv6` IPv6 address `string` 1188 | 1189 | --- 1190 | 1191 | 1192 | Add DNS CNAME record 1193 | 1194 | ```php 1195 | $bunny->addDNSRecordCNAME($zone_id, $hostname, $target); 1196 | ``` 1197 | 1198 | `$zone_id` DNS zone id `int` 1199 | `$hostname` hostname `string` 1200 | `$target` `string` 1201 | 1202 | --- 1203 | 1204 | 1205 | Add DNS MX record 1206 | 1207 | ```php 1208 | $bunny->addDNSRecordMX($zone_id, $hostname, $mail, $priority); 1209 | ``` 1210 | 1211 | `$zone_id` DNS zone id `int` 1212 | `$hostname` hostname `string` 1213 | `$mail` mail server `string` 1214 | `$priority` `int` 1215 | 1216 | --- 1217 | 1218 | 1219 | Add DNS TXT record 1220 | 1221 | ```php 1222 | $bunny->addDNSRecordTXT($zone_id, $hostname, $content); 1223 | ``` 1224 | 1225 | `$zone_id` DNS zone id `int` 1226 | `$hostname` hostname `string` 1227 | `$content` txt contents `string` 1228 | 1229 | --- 1230 | 1231 | 1232 | Add DNS NS record 1233 | 1234 | ```php 1235 | $bunny->addDNSRecordNS($zone_id, $hostname, $target); 1236 | ``` 1237 | 1238 | `$zone_id` DNS zone id `int` 1239 | `$hostname` hostname `string` 1240 | `$target` `string` 1241 | 1242 | --- 1243 | 1244 | 1245 | Add DNS redirect 1246 | 1247 | ```php 1248 | $bunny->addDNSRecordRedirect($zone_id, $hostname, $url); 1249 | ``` 1250 | 1251 | `$zone_id` DNS zone id `int` 1252 | `$hostname` hostname `string` 1253 | `$url` redirect to `string` 1254 | 1255 | --- 1256 | 1257 | 1258 | Update DNS A record 1259 | 1260 | ```php 1261 | $bunny->updateDNSRecordA($zone_id, $dns_id, $hostname, $ipv4); 1262 | ``` 1263 | 1264 | `$zone_id` DNS zone id `int` 1265 | `$dns_id` DNS record id `int` 1266 | `$hostname` hostname `string` 1267 | `$ipv4` ipv4 address `string` 1268 | 1269 | --- 1270 | 1271 | 1272 | Update DNS AAAA record 1273 | 1274 | ```php 1275 | $bunny->updateDNSRecordAAAA($zone_id, $dns_id, $hostname, $ipv6); 1276 | ``` 1277 | 1278 | `$zone_id` DNS zone id `int` 1279 | `$dns_id` DNS record id `int` 1280 | `$hostname` hostname `string` 1281 | `$ipv6` ipv6 address `string` 1282 | 1283 | --- 1284 | 1285 | 1286 | Disable DNS record 1287 | 1288 | ```php 1289 | $bunny->disableDNSRecord($zone_id, $dns_id); 1290 | ``` 1291 | 1292 | `$zone_id` DNS zone id `int` 1293 | `$dns_id` DNS record id `int` 1294 | 1295 | --- 1296 | 1297 | 1298 | Enable DNS record 1299 | 1300 | ```php 1301 | $bunny->enableDNSRecord($zone_id, $dns_id); 1302 | ``` 1303 | 1304 | `$zone_id` DNS zone id `int` 1305 | `$dns_id` DNS record id `int` 1306 | 1307 | --- 1308 | 1309 | 1310 | Delete DNS record 1311 | 1312 | ```php 1313 | $bunny->deleteDNSRecord($zone_id, $dns_id); 1314 | ``` 1315 | 1316 | `$zone_id` DNS zone id `int` 1317 | `$dns_id` DNS record id `int` 1318 | 1319 | --- 1320 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "corbpie/bunny-cdn-api", 3 | "description": "Bunny net CDN API class for handling pull zones, storage zones, video streaming and DNS.", 4 | "type": "library", 5 | "license": "MIT", 6 | "minimum-stability": "stable", 7 | "authors": [ 8 | { 9 | "name": "corbpie", 10 | "email": "contact@corbpie.com" 11 | } 12 | ], 13 | "repositories": [ 14 | { 15 | "type": "vcs", 16 | "url": "https://github.com/cp6/BunnyCDN-API" 17 | } 18 | ], 19 | "require": { 20 | "php": "^8.2", 21 | "ext-ftp": "*", 22 | "ext-curl": "*" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Corbpie\\BunnyCdn\\": "src/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dns_example.php: -------------------------------------------------------------------------------- 1 | getDNSZones(); 10 | 11 | //Returns all single DNS zone details 12 | $bunny->getDNSZone(1234); 13 | 14 | //Create a DNS zone with logging enable 15 | $bunny->addDNSZone('zonedomain.com', true); 16 | 17 | //Create a DNS zone with parameters from https://docs.bunny.net/reference/dnszonepublic_add 18 | $parameters = array( 19 | 'Domain' => 'zonedomain.com', 'NameserversDetected' => true, 'CustomNameserversEnabled' => true, 20 | 'Nameserver1' => 'customns1.com', 'Nameserver2' => 'customns2.com', 'SoaEmail' => 'contact@zonedomain.com', 21 | 'DateModified' => '2022-08-18 23:59:59', 'DateCreated' => '2022-08-18 23:59:59', 'NameserversNextCheck' => '2022-08-28 23:59:59', 22 | 'LoggingEnabled' => true, 'LoggingIPAnonymizationEnabled' => true 23 | ); 24 | $bunny->addDNSZoneFull($parameters); 25 | 26 | //Delete DNS zone (1234 is the DNS zone id) 27 | $bunny->deleteDNSZone(1234); 28 | 29 | //Returns DNS zone statistics 30 | $bunny->getDNSZoneStatistics(1234); 31 | 32 | //Update DNS nameservers 33 | $bunny->updateDNSZoneNameservers(12345, true, 'nameserverone.com', 'nameservertwo.com'); 34 | 35 | //Update DNS SOA email 36 | $bunny->updateDNSZoneSoaEmail(12345, 'mass_contact@mymail.com'); 37 | 38 | //Add a DNS record by using parameters of choice https://docs.bunny.net/reference/dnszonepublic_addrecord 39 | $parameters = array('Type' => 0, 'Ttl' => 120, 'Accelerated' => true, 'Weight' => 200); 40 | $bunny->addDNSRecord(12345, 'thehost.com', '114.12.219.52', $parameters); 41 | 42 | //Add DNS A record 43 | $bunny->addDNSRecordA(12345, 'thehost.com', '199.99.99.99'); 44 | 45 | //Add DNS AAAA record 46 | $bunny->addDNSRecordAAAA(12345, 'thehost.com', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'); 47 | 48 | //Add DNS CNAME record 49 | $bunny->addDNSRecordCNAME(12345, 'thehost.com', 'sometarget.com'); 50 | 51 | //Add DNS MX record (priority of 600) 52 | $bunny->addDNSRecordMX(12345, 'thehost.com', 'mailserver.com', 600); 53 | 54 | //Add DNS TXT record 55 | $bunny->addDNSRecordTXT(12345, 'thehost.com', 'the TXT content'); 56 | 57 | //Add DNS NS record 58 | $bunny->addDNSRecordNS(12345, 'thehost.com', 'targetns.com'); 59 | 60 | //Add DNS redirect record 61 | $bunny->addDNSRecordRedirect(12345, 'thehost.com', 'theurl.com'); 62 | 63 | //Update DNS A record (9876 is the DNS record id) 64 | $bunny->updateDNSRecordA(12345, 9876,'diffdomain.com', '162.55.44.12'); 65 | 66 | //Update DNS AAAA record (9876 is the DNS record id) 67 | $bunny->updateDNSRecordAAAA(12345, 9876,'thehost.com', '12001:0db8:85a3:0000:0000:8a2e:0370:6225'); 68 | 69 | //Disable a DNS record 70 | $bunny->disableDNSRecord(12345, 9876); 71 | 72 | //Enable a DNS record 73 | $bunny->enableDNSRecord(12345, 9876); 74 | 75 | //Delete DNS record 76 | $bunny->deleteDNSRecord(12345, 9876); -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | listPullZones());//Returns data for all Pull zones on account 16 | //Here you will find the ID's for your pullZones 17 | 18 | //Examples using pull zone id: 1337 19 | 20 | //Individual pull zone data 21 | echo json_encode($bunny->pullZoneData(26719)); 22 | 23 | //List hostnames for a pull zone 24 | $bunny->pullZoneHostnames(1337); 25 | 26 | //Add hostname to pull zone 27 | $bunny->addHostnamePullZone(1337, 'cdn.domain.com'); 28 | 29 | //Force SSL for pull zone hostname 30 | $bunny->forceSSLPullZone(1337, 'cdn.domain.com', true); 31 | 32 | //Disable SSL for pull zone hostname 33 | $bunny->forceSSLPullZone(1337, 'cdn.domain.com', false); 34 | 35 | //Remove hostname for pull zone 36 | $bunny->removeHostnamePullZone(1337, 'cdn.domain.com'); 37 | 38 | //List blocked ip addresses 39 | $bunny->listBlockedIpPullZone(1337); 40 | 41 | //Add ip to blocked 42 | $bunny->addBlockedIpPullZone(1337, '199.000.111.222'); 43 | 44 | //Remove blocked ip 45 | $bunny->unBlockedIpPullZone(1337, '199.000.111.222'); 46 | 47 | //Pull zone HTTP access logs (mm-dd-yy) 48 | $bunny->pullZoneLogs(1337, '10-29-20'); 49 | 50 | //Create pull zone 51 | $bunny->createPullZone('a_test_pull_zone', 'https://domain.com'); 52 | 53 | //Purge pull zone 54 | $bunny->purgePullZone(1337); 55 | 56 | //Purge cache for a URL 57 | $bunny->purgeCache('https://cdn.domain.com/css/style.min.css'); 58 | 59 | //Get monthly charges 60 | $bunny->monthCharges(); 61 | 62 | //Total billing amount 63 | $bunny->totalBillingAmount(); 64 | 65 | //Current account balance 66 | $bunny->balance(); 67 | 68 | //Monthly charges break down (per zone) 69 | $bunny->monthChargeBreakdown(); 70 | 71 | //Bandwidth stats 72 | $bunny->getStatistics(); 73 | 74 | 75 | /* 76 | * 77 | * STORAGE ZONE EXAMPLES 78 | * 79 | */ 80 | 81 | use Corbpie\BunnyCdn\BunnyAPIStorage; 82 | 83 | $bunny = new BunnyAPIStorage(); 84 | //View all storage zones for account 85 | echo $bunny->listStorageZones();//Returns data for all Storage zones on account 86 | 87 | $bunny->zoneConnect('homeimagebackups', '');//Create connection to 'homeimagebackups' storage zone 88 | //Access key (2nd param) can be set or left empty to which it will auto fetch from a listStorageZones() call 89 | 90 | //List folders for storage zone 'homeimagebackups' 91 | echo $bunny->listFolders(); 92 | 93 | //Check if a folder (path) exists by using its path 94 | $bunny->folderExists('pets');//Returns true if exists 95 | 96 | //Create a new folder 97 | echo $bunny->createFolder('pets');//Creates a new folder called pets 98 | 99 | //Upload file into folder 100 | echo $bunny->uploadFile('fluffy.jpg', '/pets/fluffy.jpg');//Uploads fluffy.jpg as pets/fluffy.jpg 101 | 102 | //Check if a file exists by using its path and name 103 | $bunny->fileExists('pets/fluffy.jpg');//Returns true 104 | 105 | //Rename a file 106 | echo $bunny->renameFile('pets/', 'fluffy.jpg', 'fluffy_young.jpg');//Renames pets/fluffy.jpg as pets/fluffy_young.jpg 107 | 108 | //Move a file 109 | echo $bunny->moveFile('pets/', 'fluffy_young.jpg', 'pets/puppy_fluffy/');//Moves pets/fluffy_young.jpg to pets/puppy_fluffy/fluffy_young.jpg 110 | 111 | //Get file size 112 | echo $bunny->getFileSize('pets/puppy_fluffy/fluffy_young.jpg');//File size as bytes 113 | echo $bunny->convertBytes($bunny->getFileSize('pets/puppy_fluffy/fluffy_young.jpg'), 'MB');//File size as megabytes 114 | 115 | //Delete a file 116 | echo $bunny->deleteFile('pets/puppy_fluffy/fluffy_young.jpg');//Deletes fluffy_young.jpg 117 | 118 | //Delete folders (only works if folder empty) 119 | echo $bunny->deleteFolder('pets/puppy_fluffy/'); 120 | echo $bunny->deleteFolder('pets/'); 121 | 122 | /* 123 | * 124 | * Video stream API examples 125 | * 126 | */ 127 | 128 | use Corbpie\BunnyCdn\BunnyAPIStream; 129 | 130 | $bunny = new BunnyAPIStream(); 131 | 132 | //List collections for library 1234 133 | echo json_encode($bunny->getStreamCollections(1234)); 134 | 135 | //List videos for library 1234 and collection 886gce58-1482-416f-b908-fca0b60f49ba 136 | $bunny->setStreamLibraryId(1234); 137 | $bunny->setStreamCollectionGuid('886gce58-1482-416f-b908-fca0b60f49ba'); 138 | echo json_encode($bunny->listVideosForCollectionId()); 139 | 140 | //List video information individually 141 | echo json_encode($bunny->getVideo(1234,'e6410005-d591-4a7e-a83d-6c1eef0fdc78')); 142 | 143 | //Get array of resolutions for video 144 | echo json_encode($bunny->videoResolutionsArray('e6410005-d591-4a7e-a83d-6c1eef0fdc78')); 145 | 146 | //Get size of video 147 | echo json_encode($bunny->videoSize('e6410005-d591-4a7e-a83d-6c1eef0fdc78', 'MB')); 148 | 149 | 150 | //Create a video (prepare for upload) 151 | echo json_encode($bunny->createVideo('title_for_the_video')); 152 | //OR In collection 153 | echo json_encode($bunny->createVideoForCollection('title_for_the_video')); 154 | //These return information for the video. Importantly the video guid 155 | 156 | //Upload the video file 157 | echo json_encode($bunny->uploadVideo('a6e8483a-7538-4eb1-bb1f-6c1eef0fdc78', 'test_video.mp4')); 158 | //Uploads test_video.mp4 -------------------------------------------------------------------------------- /src/BunnyAPI.php: -------------------------------------------------------------------------------- 1 | constApiKeySet()) { 28 | throw new BunnyAPIException("You must provide an API key"); 29 | } 30 | $this->api_key = self::API_KEY; 31 | if (!isset($this->stream_library_access_key)) { 32 | $this->stream_library_access_key = self::STREAM_LIBRARY_ACCESS_KEY; 33 | } 34 | } catch (BunnyAPIException $e) {//display error message 35 | echo $e->errorMessage(); 36 | } 37 | } 38 | 39 | public function apiKey(string $api_key = ''): void 40 | { 41 | try { 42 | if (!isset($api_key) || trim($api_key) === '') { 43 | throw new BunnyAPIException('$api_key cannot be empty'); 44 | } 45 | $this->api_key = $api_key; 46 | } catch (BunnyAPIException $e) {//display error message 47 | echo $e->errorMessage(); 48 | } 49 | } 50 | 51 | public function streamLibraryAccessKey(string $stream_library_access_key = ''): void 52 | { 53 | try { 54 | if (!isset($stream_library_access_key) || trim($stream_library_access_key) === '') { 55 | throw new BunnyAPIException('$stream_library_access_key cannot be empty'); 56 | } 57 | $this->stream_library_access_key = $stream_library_access_key; 58 | } catch (BunnyAPIException $e) {//display error message 59 | echo $e->errorMessage(); 60 | } 61 | } 62 | 63 | protected function constApiKeySet(): bool 64 | { 65 | return !(!defined("self::API_KEY") || empty(self::API_KEY)); 66 | } 67 | 68 | protected function APIcall(string $method, string $url, array $params = [], string $url_type = 'BASE'): array 69 | { 70 | $curl = curl_init(); 71 | if ($method === "GET") {//GET request 72 | if (!empty($params)) { 73 | $url = sprintf("%s?%s", $url, http_build_query($params)); 74 | } 75 | } elseif ($method === "POST") {//POST request 76 | curl_setopt($curl, CURLOPT_POST, 1); 77 | if (!empty($params)) { 78 | $data = json_encode($params); 79 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 80 | } 81 | } elseif ($method === "PUT") {//PUT request 82 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); 83 | if ($url_type === 'STORAGE') { 84 | $params = json_decode(json_encode($params)); 85 | curl_setopt($curl, CURLOPT_POST, 1); 86 | curl_setopt($curl, CURLOPT_UPLOAD, 1); 87 | curl_setopt($curl, CURLOPT_INFILE, fopen($params->file, 'rb')); 88 | curl_setopt($curl, CURLOPT_INFILESIZE, filesize($params->file)); 89 | } else { 90 | $data = json_encode($params); 91 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 92 | } 93 | } elseif ($method === "DELETE") {//DELETE request 94 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); 95 | if (!empty($params)) { 96 | curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params)); 97 | } 98 | } 99 | 100 | if ($url_type === 'BASE') {//General CDN 101 | curl_setopt($curl, CURLOPT_URL, self::API_URL . $url); 102 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Accept: application/json", "AccessKey: $this->api_key", "Content-Type: application/json")); 103 | } elseif ($url_type === 'STORAGE') {//Storage zone 104 | curl_setopt($curl, CURLOPT_URL, self::STORAGE_API_URL . $url); 105 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("AccessKey: $this->access_key")); 106 | } else {//Video stream 107 | curl_setopt($curl, CURLOPT_URL, self::VIDEO_STREAM_URL . $url); 108 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("AccessKey: " . $this->stream_library_access_key, "Content-Type: application/*+json")); 109 | if ($method === "PUT") { 110 | curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents($params['file'])); 111 | } 112 | } 113 | 114 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 115 | curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0); 116 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);//Need this (Bunny net issue??) 117 | 118 | $result = curl_exec($curl); 119 | $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); 120 | $debug_info = curl_getinfo($curl); 121 | curl_close($curl); 122 | 123 | if ($this->debug_request) { 124 | return $debug_info; 125 | } 126 | 127 | if ($responseCode === 204) { 128 | return [ 129 | 'http_code' => $responseCode, 130 | 'response' => json_decode($result, true), 131 | ]; 132 | } 133 | 134 | if ($responseCode >= 200 && $responseCode < 300) { 135 | return json_decode($result, true) ?? []; 136 | } 137 | 138 | return [ 139 | 'http_code' => $responseCode, 140 | 'response' => json_decode($result, true), 141 | ]; 142 | } 143 | 144 | public function purgeCache(string $url, bool $async = false): array 145 | { 146 | if ($async) { 147 | $url .= "&async=true"; 148 | } 149 | return $this->APIcall('POST', "purge?url=$url"); 150 | } 151 | 152 | public function convertBytes(int $bytes, string $convert_to = 'GB', bool $format = true, int $decimals = 2): float|int|string 153 | { 154 | if ($convert_to === 'GB') { 155 | $value = ($bytes / 1073741824); 156 | } elseif ($convert_to === 'MB') { 157 | $value = ($bytes / 1048576); 158 | } elseif ($convert_to === 'KB') { 159 | $value = ($bytes / 1024); 160 | } else { 161 | $value = $bytes; 162 | } 163 | if ($format) { 164 | return number_format($value, $decimals); 165 | } 166 | return $value; 167 | } 168 | 169 | public function getStatistics(int $pullzone_id = -1, int $serverzone_id = -1, bool $hourly = false): array 170 | { 171 | return $this->APIcall('GET', 'statistics', ['pullZone' => $pullzone_id, 'serverZoneId' => $serverzone_id, 'hourly' => $hourly]); 172 | } 173 | 174 | public function getBilling(): array 175 | { 176 | return $this->APIcall('GET', 'billing'); 177 | } 178 | 179 | public function getAffiliate(): array 180 | { 181 | return $this->APIcall('GET', 'billing/affiliate'); 182 | } 183 | 184 | public function claimAffiliate(): array 185 | { 186 | return $this->APIcall('POST', 'billing/affiliate/claim'); 187 | } 188 | 189 | public function balance(): float 190 | { 191 | return $this->getBilling()['Balance']; 192 | } 193 | 194 | public function monthCharges(): float 195 | { 196 | return $this->getBilling()['ThisMonthCharges']; 197 | } 198 | 199 | public function totalBillingAmount(bool $format = false, int $decimals = 2): array 200 | { 201 | $data = $this->getBilling(); 202 | $tally = 0; 203 | foreach ($data['BillingRecords'] as $charge) { 204 | $tally += $charge['Amount']; 205 | } 206 | if ($format) { 207 | return array('amount' => (float)number_format($tally, $decimals), 'since' => str_replace('T', ' ', $charge['Timestamp'])); 208 | } 209 | return array('amount' => $tally, 'since' => str_replace('T', ' ', $charge['Timestamp'])); 210 | } 211 | 212 | public function monthChargeBreakdown(): array 213 | { 214 | $ar = $this->getBilling(); 215 | return array('storage' => $ar['MonthlyChargesStorage'], 'EU' => $ar['MonthlyChargesEUTraffic'], 216 | 'US' => $ar['MonthlyChargesUSTraffic'], 'ASIA' => $ar['MonthlyChargesASIATraffic'], 217 | 'SA' => $ar['MonthlyChargesSATraffic']); 218 | } 219 | 220 | public function applyCoupon(string $code): array 221 | { 222 | return $this->APIcall('POST', 'applycode', array("couponCode" => $code)); 223 | } 224 | 225 | public function getCountries(): array 226 | { 227 | return $this->APIcall('GET', 'country'); 228 | } 229 | 230 | public function getRegions(): array 231 | { 232 | return $this->APIcall('GET', 'region'); 233 | } 234 | 235 | public function getAbuseCases(): array 236 | { 237 | return $this->APIcall('GET', 'abusecase'); 238 | } 239 | 240 | public function checkAbuseCase(int $id): array 241 | { 242 | return $this->APIcall('POST', "abusecase/$id/check"); 243 | } 244 | 245 | public function getSupportTickets(): array 246 | { 247 | return $this->APIcall('GET', 'support/ticket/list'); 248 | } 249 | 250 | public function getSupportTicketDetails(int $id): array 251 | { 252 | return $this->APIcall('GET', "support/ticket/details/$id"); 253 | } 254 | 255 | public function closeSupportTicket(int $id): array 256 | { 257 | return $this->APIcall('POST', "support/ticket/close/$id"); 258 | } 259 | 260 | public function createSupportTicket(string $subject, int $pullzone_id, int $storagezone_id, string $message): array 261 | { 262 | return $this->APIcall('POST', "support/ticket/create", ['Subject' => $subject, 'LinkedPullZone' => $pullzone_id, 'LinkedStorageZone' => $storagezone_id, 'Message' => $message]); 263 | } 264 | 265 | public function costCalculator(int $bytes): array 266 | { 267 | $zone1 = 0.01; 268 | $zone2 = 0.03; 269 | $zone3 = 0.045; 270 | $zone4 = 0.06; 271 | $s500t = 0.005; 272 | $s1pb = 0.004; 273 | $s2pb = 0.003; 274 | $s2pb_plus = 0.0025; 275 | $gigabytes = (float)($bytes / 1073741824); 276 | $terabytes = (float)($gigabytes / 1024); 277 | return array( 278 | 'bytes' => $bytes, 279 | 'gigabytes' => $gigabytes, 280 | 'terabytes' => $terabytes, 281 | 'EU_NA' => ($zone1 * $gigabytes), 282 | 'ASIA_OC' => ($zone2 * $gigabytes), 283 | 'SOUTH_AMERICA' => ($zone3 * $gigabytes), 284 | 'MIDDLE_EAST_AFRICA' => ($zone4 * $gigabytes), 285 | 'storage_500tb' => sprintf('%f', ($s500t * $terabytes)), 286 | 'storage_500tb_1PB' => sprintf('%f', ($s1pb * $terabytes)), 287 | 'storage_1PB_2PB' => sprintf('%f', ($s2pb * $terabytes)), 288 | 'storage_2PB_PLUS' => sprintf('%f', ($s2pb_plus * $terabytes)) 289 | ); 290 | } 291 | 292 | } 293 | -------------------------------------------------------------------------------- /src/BunnyAPIDNS.php: -------------------------------------------------------------------------------- 1 | APIcall('GET', "dnszone?page=$page&perPage=$per_page"); 10 | } 11 | 12 | public function getDNSZone(int $zone_id): array 13 | { 14 | return $this->APIcall('GET', "dnszone/$zone_id"); 15 | } 16 | 17 | public function getDNSZoneStatistics(int $zone_id, $date_from = null, $date_to = null): array 18 | { 19 | $url = "dnszone/$zone_id/statistics"; 20 | if (!is_null($date_from) && is_null($date_to)) { 21 | $url .= "?dateFrom=$date_from"; 22 | } else if (!is_null($date_to) && is_null($date_from)) { 23 | $url .= "?dateTo=$date_to"; 24 | } elseif (!is_null($date_to) && !is_null($date_from)) { 25 | $url .= "?dateFrom=$date_from&dateTo=$date_to"; 26 | } 27 | return $this->APIcall('GET', $url); 28 | } 29 | 30 | public function addDNSZoneFull(array $parameters): array 31 | {//Add DNS zone by building up parameters from https://docs.bunny.net/reference/dnszonepublic_add 32 | return $this->APIcall('POST', "dnszone", $parameters); 33 | } 34 | 35 | public function addDNSZone(string $domain, bool $logging = false, bool $log_ip_anon = true): array 36 | { 37 | $parameters = array( 38 | "Domain" => $domain, "LoggingEnabled" => $logging, "LoggingIPAnonymizationEnabled" => $log_ip_anon 39 | ); 40 | return $this->APIcall('POST', "dnszone", $parameters); 41 | } 42 | 43 | public function updateDNSZoneNameservers(int $zone_id, bool $custom_ns, string $ns_one = '', string $ns_two = ''): array 44 | { 45 | $parameters = array( 46 | "CustomNameserversEnabled" => $custom_ns, "Nameserver1" => $ns_one, "Nameserver2" => $ns_two 47 | ); 48 | return $this->APIcall('POST', "dnszone/$zone_id", $parameters); 49 | } 50 | 51 | public function updateDNSZoneLogging(int $zone_id, bool $enable_logging, int $log_anon_type, bool $use_log_anon): array 52 | { 53 | $parameters = array( 54 | "LoggingEnabled" => $enable_logging, "LogAnonymizationType" => $log_anon_type, "LoggingIPAnonymizationEnabled" => $use_log_anon 55 | ); 56 | return $this->APIcall('POST', "dnszone/$zone_id", $parameters); 57 | } 58 | 59 | public function updateDNSZoneSoaEmail(int $zone_id, string $soa_email): array 60 | { 61 | return $this->APIcall('POST', "dnszone/$zone_id", array("SoaEmail" => $soa_email)); 62 | } 63 | 64 | public function deleteDNSZone(int $zone_id): array 65 | { 66 | return $this->APIcall('DELETE', "dnszone/$zone_id"); 67 | } 68 | 69 | public function addDNSRecord(int $zone_id, string $name, string $value, array $parameters = []): array 70 | {//Add DNS record by building up parameters from https://docs.bunny.net/reference/dnszonepublic_addrecord 71 | $parameters = array_merge( 72 | [ 73 | 'Name' => $name, 74 | 'Value' => $value, 75 | ], 76 | $parameters 77 | ); 78 | return $this->APIcall('PUT', "dnszone/$zone_id/records", $parameters); 79 | } 80 | 81 | public function addDNSRecordA(int $zone_id, string $hostname, string $ipv4, int $ttl = 300, int $weight = 100): array 82 | { 83 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 0, "Value" => $ipv4, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 84 | } 85 | 86 | public function addDNSRecordAAAA(int $zone_id, string $hostname, string $ipv6, int $ttl = 300, int $weight = 100): array 87 | { 88 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 1, "Value" => $ipv6, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 89 | } 90 | 91 | public function addDNSRecordCNAME(int $zone_id, string $hostname, string $target, int $ttl = 300, int $weight = 100): array 92 | { 93 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 2, "Value" => $target, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 94 | } 95 | 96 | public function addDNSRecordMX(int $zone_id, string $hostname, string $mail_server, int $priority = 2000, int $ttl = 300, int $weight = 100): array 97 | { 98 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 4, "Value" => $mail_server, "Name" => $hostname, "Priority" => $priority, "Ttl" => $ttl, "Weight" => $weight)); 99 | } 100 | 101 | public function addDNSRecordTXT(int $zone_id, string $hostname, string $content, int $ttl = 300, int $weight = 100): array 102 | { 103 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 3, "Value" => $content, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 104 | } 105 | 106 | public function addDNSRecordNS(int $zone_id, string $hostname, string $target, int $ttl = 300, int $weight = 100): array 107 | { 108 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 12, "Value" => $target, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 109 | } 110 | 111 | public function addDNSRecordRedirect(int $zone_id, string $hostname, string $url, int $ttl = 300, int $weight = 100): array 112 | { 113 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 5, "Value" => $url, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 114 | } 115 | 116 | public function addDNSRecordPullZone(int $zone_id, string $hostname, int $pullzone_id, int $ttl = 300, int $weight = 100): array 117 | { 118 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 7, "PullZoneId" => $pullzone_id, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 119 | } 120 | 121 | public function addDNSRecordScript(int $zone_id, string $hostname, int $script_id, int $ttl = 300, int $weight = 100): array 122 | { 123 | return $this->APIcall('PUT', "dnszone/$zone_id/records", array("Type" => 11, "ScriptId" => $script_id, "Name" => $hostname, "Ttl" => $ttl, "Weight" => $weight)); 124 | } 125 | 126 | public function updateDNSRecordA(int $zone_id, int $dns_id, string $hostname, string $ipv4): array 127 | { 128 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 0, "Value" => $ipv4, "Name" => $hostname)); 129 | } 130 | 131 | public function updateDNSRecordAAAA(int $zone_id, int $dns_id, string $hostname, string $ipv6): array 132 | { 133 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 1, "Value" => $ipv6, "Name" => $hostname)); 134 | } 135 | 136 | public function updateDNSRecordCNAME(int $zone_id, int $dns_id, string $hostname, string $target): array 137 | { 138 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 2, "Value" => $target, "Name" => $hostname)); 139 | } 140 | 141 | public function updateDNSRecordMX(int $zone_id, int $dns_id, string $hostname, string $mail_server, int $priority = 2000): array 142 | { 143 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 4, "Value" => $mail_server, "Priority" => $priority, "Name" => $hostname)); 144 | } 145 | 146 | public function updateDNSRecordTXT(int $zone_id, int $dns_id, string $hostname, string $content): array 147 | { 148 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 3, "Value" => $content, "Name" => $hostname)); 149 | } 150 | 151 | public function updateDNSRecordNS(int $zone_id, int $dns_id, string $hostname, string $target): array 152 | { 153 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Type" => 12, "Value" => $target, "Name" => $hostname)); 154 | } 155 | 156 | public function disableDNSRecord(int $zone_id, int $dns_id): array 157 | { 158 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Disabled" => true)); 159 | } 160 | 161 | public function enableDNSRecord(int $zone_id, int $dns_id): array 162 | { 163 | return $this->APIcall('POST', "dnszone/$zone_id/records/$dns_id", array("Disabled" => false)); 164 | } 165 | 166 | public function deleteDNSRecord(int $zone_id, int $dns_id): array 167 | { 168 | return $this->APIcall('DELETE', "dnszone/$zone_id/records/$dns_id"); 169 | } 170 | 171 | public function recheckDNSRecord(int $zone_id): array 172 | { 173 | return $this->APIcall('POST', "dnszone/$zone_id/recheckdns"); 174 | } 175 | 176 | public function dismissDNSConfigNotice(int $zone_id): array 177 | { 178 | return $this->APIcall('POST', "dnszone/$zone_id/dismissnameservercheck"); 179 | } 180 | } -------------------------------------------------------------------------------- /src/BunnyAPIException.php: -------------------------------------------------------------------------------- 1 | getLine()} in {$this->getFile()}. {$this->getMessage()}."; 12 | } 13 | } -------------------------------------------------------------------------------- /src/BunnyAPIPull.php: -------------------------------------------------------------------------------- 1 | APIcall('GET', 'pullzone', ['page' => $page, 'perPage' => $per_page, 'includeCertificate' => $include_cert]); 10 | } 11 | 12 | public function getPullZone(int $id): array 13 | { 14 | return $this->APIcall('GET', "pullzone/$id"); 15 | } 16 | 17 | public function createPullZone(string $name, string $origin, array $args = []): array 18 | { 19 | $args = array_merge( 20 | [ 21 | 'Name' => $name, 22 | 'OriginUrl' => $origin, 23 | ], 24 | $args 25 | ); 26 | return $this->APIcall('POST', 'pullzone', $args); 27 | } 28 | 29 | public function updatePullZone(int $id, array $args = []): array 30 | { 31 | return $this->APIcall('POST', "pullzone/$id", $args); 32 | } 33 | 34 | public function pullZoneData(int $id): array 35 | { 36 | return $this->APIcall('GET', "pullzone/$id"); 37 | } 38 | 39 | public function purgePullZone(int $id): array 40 | { 41 | return $this->APIcall('POST', "pullzone/$id/purgeCache"); 42 | } 43 | 44 | public function deletePullZone(int $id): array 45 | { 46 | return $this->APIcall('DELETE', "pullzone/$id"); 47 | } 48 | 49 | public function pullZoneHostnames(int $id): ?array 50 | { 51 | $data = $this->pullZoneData($id); 52 | if (isset($this->pullZoneData($id)['Hostnames'])) { 53 | $hn_count = count($data['Hostnames']); 54 | $hn_arr = []; 55 | foreach ($data['Hostnames'] as $a_hn) { 56 | $hn_arr[] = [ 57 | 'id' => $a_hn['Id'], 58 | 'hostname' => $a_hn['Value'], 59 | 'force_ssl' => $a_hn['ForceSSL'] 60 | ]; 61 | } 62 | return [ 63 | 'hostname_count' => $hn_count, 64 | 'hostnames' => $hn_arr 65 | ]; 66 | } 67 | return ['hostname_count' => 0]; 68 | } 69 | 70 | public function addHostnamePullZone(int $id, string $hostname): array 71 | { 72 | return $this->APIcall('POST', "pullzone/$id/addHostname", ["Hostname" => $hostname]); 73 | } 74 | 75 | public function removeHostnamePullZone(int $id, string $hostname): array 76 | { 77 | return $this->APIcall('DELETE', "pullzone/$id/removeHostname", ["Hostname" => $hostname]); 78 | } 79 | 80 | public function addFreeSSLCertificate(string $hostname): array 81 | { 82 | return $this->APIcall('GET', 'pullzone/loadFreeCertificate?hostname=' . $hostname); 83 | } 84 | 85 | public function forceSSLPullZone(int $id, string $hostname, bool $force_ssl = true): array 86 | { 87 | return $this->APIcall('POST', "pullzone/$id/setForceSSL", ["Hostname" => $hostname, 'ForceSSL' => $force_ssl]); 88 | } 89 | 90 | public function listBlockedIpPullZone(int $id): array 91 | { 92 | $data = $this->pullZoneData($id); 93 | if (isset($data['BlockedIps'])) { 94 | $ip_count = count($data['BlockedIps']); 95 | $ip_arr = []; 96 | foreach ($data['BlockedIps'] as $a_hn) { 97 | $ip_arr[] = $a_hn; 98 | } 99 | return [ 100 | 'blocked_ip_count' => $ip_count, 101 | 'ips' => $ip_arr 102 | ]; 103 | } 104 | return ['blocked_ip_count' => 0, 'ips' => []]; 105 | } 106 | 107 | public function resetTokenKey(int $id): array 108 | { 109 | return $this->APIcall('POST', "pullzone/$id/resetSecurityKey", []); 110 | } 111 | 112 | public function addBlockedIpPullZone(int $id, string $ip): array 113 | { 114 | return $this->APIcall('POST', "pullzone/$id/addBlockedIp", ["BlockedIp" => $ip]); 115 | } 116 | 117 | public function unBlockedIpPullZone(int $id, string $ip): array 118 | { 119 | return $this->APIcall('POST', "pullzone/$id/removeBlockedIp", ["BlockedIp" => $ip]); 120 | } 121 | 122 | public function addAllowedReferrer(int $id, string $hostname): array 123 | { 124 | return $this->APIcall('POST', "pullzone/$id/addAllowedReferrer", ["Hostname" => $hostname]); 125 | } 126 | 127 | public function removeAllowedReferrer(int $id, string $hostname): array 128 | { 129 | return $this->APIcall('POST', "pullzone/$id/removeAllowedReferrer", ["Hostname" => $hostname]); 130 | } 131 | 132 | public function addBlockedReferrer(int $id, string $hostname): array 133 | { 134 | return $this->APIcall('POST', "pullzone/$id/addBlockedReferrer", ["Hostname" => $hostname]); 135 | } 136 | 137 | public function removeBlockedReferrer(int $id, string $hostname): array 138 | { 139 | return $this->APIcall('POST', "pullzone/$id/removeBlockedReferrer", ["Hostname" => $hostname]); 140 | } 141 | 142 | public function pullZoneLogs(int $id, string $date): array 143 | { 144 | $curl = curl_init(); 145 | curl_setopt($curl, CURLOPT_URL, "https://logging.bunnycdn.com/$date/$id.log"); 146 | curl_setopt($curl, CURLOPT_HTTPHEADER, [ 147 | "Content-Type: application/json", 148 | "AccessKey: {$this->api_key}"] 149 | ); 150 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 151 | curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 152 | $result = curl_exec($curl); 153 | curl_close($curl); 154 | $line_to_line = explode("\n", $result); 155 | $line = []; 156 | foreach ($line_to_line as $v1) { 157 | if (isset($v1) && $v1 !== '') { 158 | $log_format = explode('|', $v1); 159 | $details = [ 160 | 'cache_result' => $log_format[0], 161 | 'status' => (int)$log_format[1], 162 | 'datetime' => date('Y-m-d H:i:s', round($log_format[2] / 1000, 0)), 163 | 'bytes' => (int)$log_format[3], 164 | 'ip' => $log_format[5], 165 | 'referer' => $log_format[6], 166 | 'file_url' => $log_format[7], 167 | 'user_agent' => $log_format[9], 168 | 'request_id' => $log_format[10], 169 | 'cdn_dc' => $log_format[8], 170 | 'zone_id' => (int)$log_format[4], 171 | 'country_code' => $log_format[11] 172 | ]; 173 | $line[] = $details; 174 | } 175 | } 176 | return $line; 177 | } 178 | } -------------------------------------------------------------------------------- /src/BunnyAPIStorage.php: -------------------------------------------------------------------------------- 1 | storage_name = $storage_name; 12 | (empty($access_key)) ? $this->findStorageZoneAccessKey($storage_name) : $this->access_key = $access_key; 13 | $conn_id = ftp_connect((self::HOSTNAME)); 14 | $login = ftp_login($conn_id, $storage_name, $this->access_key); 15 | ftp_pasv($conn_id, true); 16 | try { 17 | if (!$conn_id) { 18 | throw new BunnyAPIException("Could not make FTP connection to " . (self::HOSTNAME)); 19 | } 20 | $this->connection = $conn_id; 21 | } catch (BunnyAPIException $e) {//display error message 22 | echo $e->errorMessage(); 23 | } 24 | } 25 | 26 | protected function findStorageZoneAccessKey(string $storage_name): ?string 27 | { 28 | $data = $this->listStorageZones(); 29 | foreach ($data as $zone) { 30 | if ($zone['Name'] === $storage_name) { 31 | return $this->access_key = $zone['Password']; 32 | } 33 | } 34 | return null;//Never found access key for said storage zone 35 | } 36 | 37 | public function listStorageZones(): array 38 | { 39 | return $this->APIcall('GET', 'storagezone'); 40 | } 41 | 42 | public function addStorageZone(string $name, string $origin_url, string $main_region = 'DE', array $replicated_regions = []): array 43 | { 44 | return $this->APIcall('POST', 'storagezone', array("Name" => $name, "OriginUrl" => $origin_url, "Region" => $main_region, "ReplicationRegions" => $replicated_regions)); 45 | } 46 | 47 | public function deleteStorageZone(int $id): array 48 | { 49 | return $this->APIcall('DELETE', "storagezone/$id"); 50 | } 51 | 52 | public function uploadFileHTTP(string $file, string $save_as = 'folder/filename.jpg'): array 53 | { 54 | return $this->APIcall('PUT', $this->storage_name . "/" . $save_as, array('file' => $file), 'STORAGE'); 55 | } 56 | 57 | public function deleteFileHTTP(string $file): array 58 | { 59 | return $this->APIcall('DELETE', $this->storage_name . "/" . $file, [], 'STORAGE'); 60 | } 61 | 62 | public function downloadFileHTTP(string $file): array 63 | { 64 | return $this->APIcall('GET', $this->storage_name . "/" . $file, [], 'STORAGE'); 65 | } 66 | 67 | public function fileExists(string $file): bool 68 | { 69 | return ftp_size($this->connection, $file) >= 0; 70 | } 71 | 72 | public function folderExists(string $path): bool 73 | { 74 | if (!ftp_nlist($this->connection, $path)) { 75 | return false; 76 | } 77 | return true; 78 | } 79 | 80 | public function createFolder(string $name): array 81 | { 82 | if (@!ftp_chdir($this->connection, $name)) { 83 | if (ftp_mkdir($this->connection, $name)) { 84 | return array('response' => 'success', 'action' => __FUNCTION__, 'value' => $name); 85 | } 86 | return array('response' => 'fail', 'action' => __FUNCTION__, 'value' => $name, 'message' => "Failed to create directory $name"); 87 | } 88 | return array('response' => 'fail', 'action' => __FUNCTION__, 'value' => $name, 'message' => "Directory $name already exists"); 89 | } 90 | 91 | public function deleteFolder(string $name): array 92 | { 93 | if (ftp_rmdir($this->connection, $name)) { 94 | return array('response' => 'success', 'action' => __FUNCTION__, 'value' => $name); 95 | } 96 | return array('response' => 'fail', 'action' => __FUNCTION__, 'value' => $name); 97 | } 98 | 99 | public function deleteFile(string $name): array 100 | { 101 | if (ftp_delete($this->connection, $name)) { 102 | return array('response' => 'success', 'action' => __FUNCTION__, 'value' => $name); 103 | } 104 | return array('response' => 'fail', 'action' => __FUNCTION__, 'value' => $name); 105 | } 106 | 107 | public function deleteAllFiles(string $dir): array 108 | { 109 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name/{$dir}/?AccessKey=" . $this->access_key), true); 110 | $files_deleted = 0; 111 | foreach ($array as $value) { 112 | if ($value['IsDirectory'] === false) { 113 | $file_name = $value['ObjectName']; 114 | if (ftp_delete($this->connection, "$dir/$file_name")) { 115 | $files_deleted++; 116 | } 117 | } 118 | } 119 | return array('action' => __FUNCTION__, 'value' => $dir, 'files_deleted' => $files_deleted); 120 | } 121 | 122 | public function uploadAllFiles(string $dir, string $place, $mode = FTP_BINARY): array 123 | { 124 | $obj = scandir($dir); 125 | $files_uploaded = 0; 126 | foreach ($obj as $file) { 127 | if (!is_dir($file) && ftp_put($this->connection, $place . $file, "$dir/$file", $mode)) { 128 | $files_uploaded++; 129 | } 130 | } 131 | return array('action' => __FUNCTION__, 'value' => $dir, 'files_uploaded' => $files_uploaded); 132 | } 133 | 134 | public function getFileSize(string $file): int 135 | { 136 | return ftp_size($this->connection, $file); 137 | } 138 | 139 | public function dirSize(string $dir = ''): array 140 | { 141 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name/" . $dir . "/?AccessKey=" . $this->access_key), true); 142 | $size = $files = 0; 143 | foreach ($array as $value) { 144 | if ($value['IsDirectory'] === false) { 145 | $size += $value['Length']; 146 | $files++; 147 | } 148 | } 149 | return array('dir' => $dir, 'files' => $files, 'size_b' => $size, 'size_kb' => number_format(($size / 1024), 3), 150 | 'size_mb' => number_format(($size / 1048576), 3), 'size_gb' => number_format(($size / 1073741824), 3)); 151 | } 152 | 153 | public function currentDir(): string 154 | { 155 | return ftp_pwd($this->connection); 156 | } 157 | 158 | public function changeDir(string $moveto): array 159 | { 160 | if (ftp_chdir($this->connection, $moveto)) { 161 | return array('response' => 'success', 'action' => __FUNCTION__, 'value' => $moveto); 162 | } 163 | return array('response' => 'fail', 'action' => __FUNCTION__, 'value' => $moveto); 164 | } 165 | 166 | public function moveUpOne(): array 167 | { 168 | if (ftp_cdup($this->connection)) { 169 | return array('response' => 'success', 'action' => __FUNCTION__); 170 | } 171 | return array('response' => 'fail', 'action' => __FUNCTION__); 172 | } 173 | 174 | public function renameFile(string $dir, string $file_name, string $new_file_name): array 175 | { 176 | $path_data = pathinfo("{$dir}$file_name"); 177 | $file_type = $path_data['extension']; 178 | if (ftp_get($this->connection, "TEMPFILE.$file_type", "{$dir}$file_name", FTP_BINARY)) { 179 | if (ftp_put($this->connection, "{$dir}$new_file_name", "TEMPFILE.$file_type", FTP_BINARY)) { 180 | $this->deleteFile("{$dir}$file_name"); 181 | return array('response' => 'success', 'action' => __FUNCTION__, 'old' => "{$dir}$file_name", 'new' => "{$dir}$new_file_name"); 182 | } 183 | return array('response' => 'fail', 'action' => __FUNCTION__, 'old' => "{$dir}$file_name", 'new' => "{$dir}$new_file_name"); 184 | } 185 | return array('response' => 'fail', 'action' => __FUNCTION__, 'old' => "{$dir}$file_name", 'new' => "{$dir}$new_file_name"); 186 | } 187 | 188 | public function moveFile(string $dir, string $file_name, string $move_to): array 189 | { 190 | $path_data = pathinfo("{$dir}$file_name"); 191 | $file_type = $path_data['extension']; 192 | if (ftp_get($this->connection, "TEMPFILE.$file_type", "{$dir}$file_name", FTP_BINARY)) { 193 | if (ftp_put($this->connection, "$move_to{$file_name}", "TEMPFILE.$file_type", FTP_BINARY)) { 194 | $this->deleteFile("{$dir}$file_name"); 195 | return array('response' => 'success', 'action' => __FUNCTION__, 'file' => "{$dir}$file_name", 'move_to' => $move_to); 196 | } 197 | return array('response' => 'fail', 'action' => __FUNCTION__, 'file' => "{$dir}$file_name", 'move_to' => $move_to); 198 | } 199 | return array('response' => 'fail', 'action' => __FUNCTION__, 'file' => "{$dir}$file_name", 'move_to' => $move_to); 200 | } 201 | 202 | public function downloadFile(string $save_as, string $get_file, int $mode = FTP_BINARY): array 203 | { 204 | if (ftp_get($this->connection, $save_as, $get_file, $mode)) { 205 | return array('response' => 'success', 'action' => __FUNCTION__, 'file' => $get_file, 'save_as' => $save_as); 206 | } 207 | return array('response' => 'fail', 'action' => __FUNCTION__, 'file' => $get_file, 'save_as' => $save_as); 208 | } 209 | 210 | public function downloadFileWithProgress(string $save_as, string $get_file, string $progress_file = 'DOWNLOAD_PERCENT.txt'): void 211 | { 212 | $ftp_url = "ftp://$this->storage_name:$this->access_key@" . self::HOSTNAME . "/$this->storage_name/$get_file"; 213 | $size = filesize($ftp_url); 214 | $in = fopen($ftp_url, "rb") or die("Cannot open source file"); 215 | $out = fopen($save_as, "wb"); 216 | while (!feof($in)) { 217 | $buf = fread($in, 10240); 218 | fwrite($out, $buf); 219 | $file_data = (int)(ftell($out) / $size * 100); 220 | file_put_contents($progress_file, $file_data); 221 | } 222 | fclose($out); 223 | fclose($in); 224 | } 225 | 226 | public function downloadAll(string $dir_dl_from = '', string $dl_into = '', int $mode = FTP_BINARY): array 227 | { 228 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name" . $dir_dl_from . "/?AccessKey=" . $this->access_key), true); 229 | $files_downloaded = 0; 230 | foreach ($array as $value) { 231 | if ($value['IsDirectory'] === false) { 232 | $file_name = $value['ObjectName']; 233 | if (ftp_get($this->connection, $dl_into . (string)$file_name, $file_name, $mode)) { 234 | $files_downloaded++; 235 | } 236 | } 237 | } 238 | return array('action' => __FUNCTION__, 'files_downloaded' => $files_downloaded); 239 | } 240 | 241 | public function uploadFile(string $upload, string $upload_as, int $mode = FTP_BINARY): array 242 | { 243 | if (ftp_put($this->connection, $upload_as, $upload, $mode)) { 244 | return array('response' => 'success', 'action' => __FUNCTION__, 'file' => $upload, 'upload_as' => $upload_as); 245 | } 246 | return array('response' => 'fail', 'action' => __FUNCTION__, 'file' => $upload, 'upload_as' => $upload_as); 247 | } 248 | 249 | public function uploadFileWithProgress(string $upload, string $upload_as, string $progress_file = 'UPLOAD_PERCENT.txt'): void 250 | { 251 | $ftp_url = "ftp://$this->storage_name:$this->access_key@" . self::HOSTNAME . "/$this->storage_name/$upload_as"; 252 | $size = filesize($upload); 253 | $out = fopen($ftp_url, "wb"); 254 | $in = fopen($upload, "rb"); 255 | while (!feof($in)) { 256 | $buffer = fread($in, 10240); 257 | fwrite($out, $buffer); 258 | $file_data = (int)(ftell($in) / $size * 100); 259 | file_put_contents($progress_file, $file_data); 260 | } 261 | fclose($in); 262 | fclose($out); 263 | } 264 | 265 | public function listAllOG(): array 266 | { 267 | return json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name/?AccessKey=" . $this->access_key), true); 268 | } 269 | 270 | public function listFiles(string $location = ''): array 271 | { 272 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name" . $location . "/?AccessKey=" . $this->access_key), true); 273 | $items = array('storage_name' => $this->storage_name, 'current_dir' => $location, 'data' => []); 274 | foreach ($array as $value) { 275 | if ($value['IsDirectory'] === false) { 276 | $created = date('Y-m-d H:i:s', strtotime($value['DateCreated'])); 277 | $last_changed = date('Y-m-d H:i:s', strtotime($value['LastChanged'])); 278 | if (isset(pathinfo($value['ObjectName'])['extension'])) { 279 | $file_type = pathinfo($value['ObjectName'])['extension']; 280 | } else { 281 | $file_type = null; 282 | } 283 | $file_name = $value['ObjectName']; 284 | $size_kb = (float)($value['Length'] / 1024); 285 | $guid = $value['Guid']; 286 | $items['data'][] = array('name' => $file_name, 'file_type' => $file_type, 'size' => $size_kb, 'created' => $created, 287 | 'last_changed' => $last_changed, 'guid' => $guid); 288 | } 289 | } 290 | return $items; 291 | } 292 | 293 | public function listFolders(string $location = ''): array 294 | { 295 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name" . $location . "/?AccessKey=$this->access_key"), true); 296 | $items = array('storage_name' => $this->storage_name, 'current_dir' => $location, 'data' => []); 297 | foreach ($array as $value) { 298 | $created = date('Y-m-d H:i:s', strtotime($value['DateCreated'])); 299 | $last_changed = date('Y-m-d H:i:s', strtotime($value['LastChanged'])); 300 | $folder_name = $value['ObjectName']; 301 | $guid = $value['Guid']; 302 | if ($value['IsDirectory'] === true) { 303 | $items['data'][] = [ 304 | 'name' => $folder_name, 'created' => $created, 305 | 'last_changed' => $last_changed, 'guid' => $guid 306 | ]; 307 | } 308 | } 309 | return $items; 310 | } 311 | 312 | public function listAll(string $location = ''): array 313 | { 314 | $array = json_decode(file_get_contents(self::STORAGE_API_URL . "/$this->storage_name" . $location . "/?AccessKey=" . $this->access_key), true); 315 | $items = array('storage_name' => $this->storage_name, 'current_dir' => $location, 'data' => []); 316 | foreach ($array as $value) { 317 | $created = date('Y-m-d H:i:s', strtotime($value['DateCreated'])); 318 | $last_changed = date('Y-m-d H:i:s', strtotime($value['LastChanged'])); 319 | $file_name = $value['ObjectName']; 320 | $guid = $value['Guid']; 321 | if ($value['IsDirectory'] === true) { 322 | $file_type = null; 323 | $size_kb = null; 324 | } else { 325 | $file_type = pathinfo($value['ObjectName'])['extension'] ?? null; 326 | $size_kb = (float)($value['Length'] / 1024); 327 | } 328 | $items['data'][] = array('name' => $file_name, 'file_type' => $file_type, 'size' => $size_kb, 'is_dir' => $value['IsDirectory'], 'created' => $created, 329 | 'last_changed' => $last_changed, 'guid' => $guid); 330 | } 331 | return $items; 332 | } 333 | 334 | public function closeConnection(): array 335 | { 336 | if (ftp_close($this->connection)) { 337 | return array('response' => 'success', 'action' => __FUNCTION__); 338 | } 339 | return array('response' => 'fail', 'action' => __FUNCTION__); 340 | } 341 | 342 | } -------------------------------------------------------------------------------- /src/BunnyAPIStream.php: -------------------------------------------------------------------------------- 1 | collection -> video 12 | public function setStreamLibraryId(int $library_id): void 13 | { 14 | $this->stream_library_id = $library_id; 15 | } 16 | 17 | public function setStreamCollectionGuid(string $collection_guid): void 18 | { 19 | $this->stream_collection_guid = $collection_guid; 20 | } 21 | 22 | public function setStreamVideoGuid(string $video_guid): void 23 | { 24 | $this->stream_video_guid = $video_guid; 25 | } 26 | 27 | public function getVideoCollections(int $page = 1, int $items_per_page = 100): array 28 | { 29 | return $this->APIcall('GET', "library/{$this->stream_library_id}/collections", ['page' => $page, 'itemsPerPage' => $items_per_page], 'STREAM'); 30 | } 31 | 32 | public function getStreamCollections(int $page = 1, int $items_pp = 100, string $order_by = 'date'): array 33 | { 34 | $this->checkStreamLibraryIdSet(); 35 | return $this->APIcall('GET', "library/{$this->stream_library_id}/collections?page=$page&itemsPerPage=$items_pp&orderBy=$order_by", [], 'STREAM'); 36 | } 37 | 38 | public function getStreamForCollection(): array 39 | { 40 | $this->checkStreamLibraryIdSet(); 41 | $this->checkStreamCollectionGuidSet(); 42 | return $this->APIcall('GET', "library/{$this->stream_library_id}/collections/" . $this->stream_collection_guid, [], 'STREAM'); 43 | } 44 | 45 | public function getStreamCollectionSize(): int 46 | { 47 | $this->checkStreamLibraryIdSet(); 48 | $this->checkStreamCollectionGuidSet(); 49 | return $this->APIcall('GET', "library/{$this->stream_library_id}/collections/" . $this->stream_collection_guid, [], 'STREAM')['totalSize']; 50 | } 51 | 52 | public function updateCollection(string $updated_collection_name): array 53 | { 54 | $this->checkStreamLibraryIdSet(); 55 | return $this->APIcall('POST', "library/{$this->stream_library_id}/collections/" . $this->stream_collection_guid, array("name" => $updated_collection_name), 'STREAM'); 56 | } 57 | 58 | public function deleteCollection(): array 59 | { 60 | $this->checkStreamLibraryIdSet(); 61 | $this->checkStreamCollectionGuidSet(); 62 | return $this->APIcall('DELETE', "library/{$this->stream_library_id}/collections/" . $this->stream_collection_guid, [], 'STREAM'); 63 | } 64 | 65 | public function createCollection(string $new_collection_name): array 66 | { 67 | $this->checkStreamLibraryIdSet(); 68 | return $this->APIcall('POST', "library/{$this->stream_library_id}/collections", array("name" => $new_collection_name), 'STREAM'); 69 | } 70 | 71 | public function listVideos(int $page = 1, int $items_pp = 100, string $order_by = 'date'): array 72 | { 73 | $this->checkStreamLibraryIdSet(); 74 | return $this->APIcall('GET', "library/{$this->stream_library_id}/videos?page=$page&itemsPerPage=$items_pp&orderBy=$order_by", [], 'STREAM'); 75 | } 76 | 77 | public function listVideosForCollectionId(int $page = 1, int $items_pp = 100, string $order_by = 'date'): array 78 | { 79 | $this->checkStreamLibraryIdSet(); 80 | $this->checkStreamCollectionGuidSet(); 81 | return $this->APIcall('GET', "library/{$this->stream_library_id}/videos?collection={$this->stream_collection_guid}&page=$page&itemsPerPage=$items_pp&orderBy=$order_by", [], 'STREAM'); 82 | } 83 | 84 | public function getVideoStatistics(): array 85 | { 86 | $this->checkStreamLibraryIdSet(); 87 | return $this->APIcall('GET', "library/{$this->stream_library_id}/statistics", [], 'STREAM'); 88 | } 89 | 90 | public function getVideoHeatmap(string $video_guid): array 91 | { 92 | $this->checkStreamLibraryIdSet(); 93 | return $this->APIcall('GET', "library/{$this->stream_library_id}/videos/$video_guid/heatmap", [], 'STREAM'); 94 | } 95 | 96 | public function getVideo(string $video_guid): array 97 | { 98 | $this->checkStreamLibraryIdSet(); 99 | return $this->APIcall('GET', "library/{$this->stream_library_id}/videos/$video_guid", [], 'STREAM'); 100 | } 101 | 102 | public function deleteVideo(string $video_guid): array 103 | { 104 | $this->checkStreamLibraryIdSet(); 105 | return $this->APIcall('DELETE', "library/{$this->stream_library_id}/videos/$video_guid", [], 'STREAM'); 106 | } 107 | 108 | public function createVideo(string $video_title): array 109 | {//Returns array containing a GUID which is needed to PUT the video file 110 | $this->checkStreamLibraryIdSet(); 111 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos", array("title" => $video_title), 'STREAM'); 112 | } 113 | 114 | public function createVideoForCollection(string $video_title): array 115 | {//Returns array containing a GUID which is needed to PUT the video file 116 | $this->checkStreamLibraryIdSet(); 117 | $this->checkStreamCollectionGuidSet(); 118 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos", array("title" => $video_title, "collectionId" => $this->stream_collection_guid), 'STREAM'); 119 | } 120 | 121 | public function uploadVideo(string $video_guid, string $video_to_upload): array 122 | { 123 | //Need to use createVideo() first to get video guid 124 | $this->checkStreamLibraryIdSet(); 125 | return $this->APIcall('PUT', "library/{$this->stream_library_id}/videos/" . $video_guid, array('file' => $video_to_upload), 'STREAM'); 126 | 127 | } 128 | 129 | public function setThumbnail(string $video_guid, string $thumbnail_url): array 130 | { 131 | $this->checkStreamLibraryIdSet(); 132 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos/$video_guid/thumbnail?$thumbnail_url", [], 'STREAM'); 133 | 134 | } 135 | 136 | public function addCaptions(string $video_guid, string $srclang, string $label, string $captions_file): array 137 | { 138 | $this->checkStreamLibraryIdSet(); 139 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos/$video_guid/captions/$srclang?label=$label&captionsFile=$captions_file", [], 'STREAM'); 140 | } 141 | 142 | public function reEncodeVideo(string $video_guid): array 143 | { 144 | $this->checkStreamLibraryIdSet(); 145 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos/$video_guid/reencode", [], 'STREAM'); 146 | 147 | } 148 | 149 | public function fetchVideo(string $video_url, string $collection_id = null): array 150 | {//Downloads a video from a URL into stream library/collection 151 | $this->checkStreamLibraryIdSet(); 152 | (!is_null($collection_id)) ? $append = "?collectionId=$collection_id" : $append = ""; 153 | return $this->APIcall('POST', "library/{$this->stream_library_id}/videos/fetch{$append}", ['url' => $video_url], 'STREAM'); 154 | 155 | } 156 | 157 | public function deleteCaptions(string $video_guid, string $srclang): array 158 | { 159 | $this->checkStreamLibraryIdSet(); 160 | return $this->APIcall('DELETE', "library/{$this->stream_library_id}/videos/$video_guid/captions/$srclang", [], 'STREAM'); 161 | } 162 | 163 | public function videoResolutionsArray(string $video_guid): array 164 | { 165 | $this->checkStreamLibraryIdSet(); 166 | $data = $this->APIcall('GET', "library/{$this->stream_library_id}/videos/$video_guid", [], 'STREAM'); 167 | return explode(",", $data['availableResolutions']); 168 | } 169 | 170 | public function videoSize(string $video_guid, string $size_type = 'MB', bool $format = false, float $decimals = 2): float 171 | { 172 | $this->checkStreamLibraryIdSet(); 173 | $data = $this->APIcall('GET', "library/{$this->stream_library_id}/videos/$video_guid", [], false, true); 174 | return $this->convertBytes($data['storageSize'], $size_type, $format, $decimals); 175 | } 176 | 177 | private function checkStreamLibraryIdSet(): void 178 | { 179 | try { 180 | if (!isset($this->stream_library_id)) { 181 | throw new BunnyAPIException("You must set the stream library id first. Use setStreamLibraryId()"); 182 | } 183 | } catch (BunnyAPIException $e) {//display error message 184 | echo $e->errorMessage(); 185 | exit; 186 | } 187 | } 188 | 189 | private function checkStreamCollectionGuidSet(): void 190 | { 191 | try { 192 | if (!isset($this->stream_collection_guid)) { 193 | throw new BunnyAPIException("You must set the stream collection guid first. Use setStreamCollectionGuid()"); 194 | } 195 | } catch (BunnyAPIException $e) {//display error message 196 | echo $e->errorMessage(); 197 | exit; 198 | } 199 | } 200 | } --------------------------------------------------------------------------------