├── .env.example ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .php-cs-fixer.dist.php ├── .travis.yml ├── CHANGELOG.md ├── LICENCE.txt ├── README.md ├── VERSION.txt ├── composer.json ├── phpunit.xml ├── phpunit.xml.bak ├── src ├── Facades │ └── HubSpot.php ├── HubSpotServiceProvider.php └── config │ └── hubspot.php └── tests ├── API └── ContactsTest.php ├── TestCase.php └── Unit ├── Facades └── HubspotFacadeTest.php └── ServiceProviderTest.php /.env.example: -------------------------------------------------------------------------------- 1 | # Loads in during testing as we require an API key 2 | HUBSPOT_ACCESS_TOKEN="" 3 | 4 | # Learn how to get a key here https://knowledge.hubspot.com/articles/kcs_article/integrations/how-do-i-get-my-hubspot-api-key 5 | HUBSPOT_DEVELOPER_KEY="" -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | 2 | name: tests 3 | 4 | on: 5 | push: 6 | pull_request: 7 | 8 | jobs: 9 | tests: 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | php: [8.2, 8.1, 8.0] 15 | os: [ubuntu-latest] 16 | 17 | name: PHP${{ matrix.php }} on ${{ matrix.os }} 18 | 19 | steps: 20 | - name: Checkout repository and submodules 21 | uses: actions/checkout@v2 22 | with: 23 | submodules: recursive 24 | 25 | - name: Cache dependencies 26 | uses: actions/cache@v1 27 | with: 28 | path: ~/.composer/cache/files 29 | key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} 30 | 31 | - name: Setup PHP 32 | uses: shivammathur/setup-php@v2 33 | with: 34 | php-version: ${{ matrix.php }} 35 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, mysqli, pdo_mysql, bcmath, intl, gd, exif, iconv, imagick 36 | coverage: none 37 | 38 | - name: Install dependencies 39 | run: | 40 | composer update --prefer-stable --prefer-dist --no-interaction --no-suggest 41 | - name: Execute CS check 42 | env: 43 | PHP_CS_FIXER_IGNORE_ENV: 1 44 | run: composer lint 45 | - name: Execute tests 46 | env: 47 | HUBSPOT_ACCESS_TOKEN: ${{secrets.HUBSPOT_PRIVATE_APP_KEY}} 48 | run: vendor/bin/phpunit -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.lock 3 | .DS_Store 4 | .env 5 | .phpunit.result.cache 6 | .php_cs.cache 7 | .idea 8 | .php-cs-fixer.cache -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | exclude('vendor') 5 | ->in(__DIR__); 6 | 7 | return (new PhpCsFixer\Config) 8 | ->setRules([ 9 | '@Symfony' => true, 10 | '@PSR2' => true, 11 | 'array_syntax' => ['syntax' => 'short'], 12 | 'php_unit_method_casing' => ['case' => 'snake_case'], 13 | ]) 14 | ->setIndent("\t") 15 | ->setLineEnding("\r\n") 16 | ->setFinder($finder); -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '7.1' 4 | - '7.2' 5 | - '7.3' 6 | install: 7 | - 'composer install' 8 | script: 9 | - 'vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --dry-run --stop-on-violation --using-cache=no' 10 | - 'vendor/bin/phpunit' -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [6.0.0] - 2023-06-23 10 | 11 | - Updated to use the new [Hubspot PHP API Client](https://github.com/HubSpot/hubspot-api-php). 12 | 13 | ## [5.0.0] - 2022-11-12 14 | 15 | - Updated Hubspot package to v5 16 | - Added support for private apps ([#34](https://github.com/rossjcooper/laravel-hubspot/pull/34)) 17 | - Updated workfloe tests to support PHP 8.0 and 8.1 18 | 19 | ## [4.0.0] - 2020-10-15 20 | 21 | - Updated [Hubspot PHP package to v3](https://github.com/HubSpot/hubspot-php/compare/v2.0.6...v3.0.0), adding Guzzle 7 support 22 | 23 | ## [3.0.0] - 2020-02-09 24 | 25 | ### Changed 26 | - Update HubSpot composer dependency. Allows use of current / future API V3 calls. [#22] 27 | 28 | ## [2.0.0] - 2020-01-07 29 | 30 | - Updated HubSpot base package to official package. [#19] 31 | 32 | 33 | 34 | [Unreleased]:https://github.com/rossjcooper/laravel-hubspot/compare/v2.0.0...HEAD 35 | [2.0.0]:https://github.com/rossjcooper/laravel-hubspot/compare/2.0.0...1.3.0 36 | [3.0.0]:https://github.com/rossjcooper/laravel-hubspot/compare/3.0.0...2.0.0 37 | [4.0.0]:https://github.com/rossjcooper/laravel-hubspot/compare/4.0.0...3.0.0 38 | [5.0.0]:https://github.com/rossjcooper/laravel-hubspot/compare/5.0.0...4.0.0 39 | 40 | [#19]: https://github.com/rossjcooper/laravel-hubspot/pull/19 41 | [#22]: https://github.com/rossjcooper/laravel-hubspot/pull/22 -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ross Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HubSpot PHP API Client Wrapper for Laravel 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/rossjcooper/laravel-hubspot/v/stable)](https://packagist.org/packages/rossjcooper/laravel-hubspot) [![Total Downloads](https://poser.pugx.org/rossjcooper/laravel-hubspot/downloads)](https://packagist.org/packages/rossjcooper/laravel-hubspot) 4 | 5 | This is a wrapper for the [Hubspot/hubspot-api-php](https://github.com/HubSpot/hubspot-api-php) package and gives the user a Service Container binding and facade of the `HubSpot\Discovery\Discovery` class. 6 | 7 | ## Installation 8 | 1. `composer require rossjcooper/laravel-hubspot` 9 | 2. Get a HubSpot API Key from the Intergrations page of your HubSpot account. 10 | 3. Laravel 5.4 or earlier, in your `config/app.php` file: 11 | - Add `Rossjcooper\LaravelHubSpot\HubSpotServiceProvider::class` to your providers array. 12 | - Add `'HubSpot' => Rossjcooper\LaravelHubSpot\Facades\HubSpot::class` to your aliases array. 13 | 4. `php artisan vendor:publish --provider="Rossjcooper\LaravelHubSpot\HubSpotServiceProvider" --tag="config"` will create a `config/hubspot.php` file. 14 | 5. Add your HubSpot API key and private app access token into the `.env` file: `HUBSPOT_ACCESS_TOKEN=yourApiKey` 15 | 6. If you use the private app access token, you should alo add `HUBSPOT_USE_OAUTH2=true` to your `.env` file 16 | 17 | ## Usage 18 | You can use either the facade or inject the HubSpot class as a dependency: 19 | ### Facade 20 | ```php 21 | // Echo all contacts first and last names 22 | $response = HubSpot::crm()->contacts()->basicApi()->getPage(); 23 | foreach ($response->getResults() as $contact) { 24 | echo sprintf( 25 | "Contact name is %s %s." . PHP_EOL, 26 | $contact->getProperties()['firstname'], 27 | $contact->getProperties()['lastname'] 28 | ); 29 | } 30 | ``` 31 | ```php 32 | Route::get('/', function (HubSpot\Discovery\Discovery $hubspot) { 33 | $response = $hubspot->crm()->contacts()->basicApi()->getPage(); 34 | foreach ($response->getResults() as $contact) { 35 | echo sprintf( 36 | "Contact name is %s %s." . PHP_EOL, 37 | $contact->getProperties()['firstname'], 38 | $contact->getProperties()['lastname'] 39 | ); 40 | } 41 | }); 42 | ``` 43 | 44 | ```php 45 | // Create a new contact 46 | $contactInput = new \HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectInputForCreate(); 47 | $contactInput->setProperties([ 48 | 'email' => 'example@example.com' 49 | ]); 50 | 51 | $contact = $hubspot->crm()->contacts()->basicApi()->create($contactInput); 52 | ``` 53 | 54 | 55 | For more info on using the actual API see the main repo [Hubspot/hubspot-api-php](https://github.com/HubSpot/hubspot-api-php) 56 | 57 | ## Testing 58 | 59 | We're using the brilliant [Orchestra Testbench](https://github.com/orchestral/testbench) to run unit tests in a Laravel based environment. If you wish to run tests be sure to have a HubSpot API key inside your `.env` file and run `composer run test` 60 | 61 | Current unit test access the HubSpot API and expect to see the demo contacts/leads that HubSpot provides to its developer accounts. 62 | 63 | ## Issues 64 | Please only report issues relating to the Laravel side of things here, main API issues should be reported [here](https://github.com/HubSpot/hubspot-api-php/issues) 65 | -------------------------------------------------------------------------------- /VERSION.txt: -------------------------------------------------------------------------------- 1 | 6.0.0 -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rossjcooper/laravel-hubspot", 3 | "type": "library", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Ross Cooper", 8 | "email": "therossjcooper@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "illuminate/support": ">=5.3", 13 | "hubspot/api-client": "^10.0", 14 | "php": ">=8.0" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Rossjcooper\\LaravelHubSpot\\": "src/", 19 | "Tests\\": "tests/" 20 | } 21 | }, 22 | "extra": { 23 | "laravel": { 24 | "providers": [ 25 | "Rossjcooper\\LaravelHubSpot\\HubSpotServiceProvider" 26 | ], 27 | "aliases": { 28 | "HubSpot": "Rossjcooper\\LaravelHubSpot\\Facades\\HubSpot" 29 | } 30 | } 31 | }, 32 | "description": "Adds a Laravel specific wrapper for the Hubspot client package", 33 | "keywords": [ 34 | "laravel", 35 | "hubspot", 36 | "api", 37 | "service" 38 | ], 39 | "require-dev": { 40 | "orchestra/testbench": ">=3.4", 41 | "friendsofphp/php-cs-fixer": "^v3.19" 42 | }, 43 | "scripts": { 44 | "test": "./vendor/bin/phpunit", 45 | "lint": "./vendor/bin/php-cs-fixer fix -v --dry-run", 46 | "fix": "./vendor/bin/php-cs-fixer fix" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./tests/Unit/ 7 | 8 | 9 | ./tests/API/ 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | src/ 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /phpunit.xml.bak: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/Unit/ 14 | 15 | 16 | ./tests/API/ 17 | 18 | 19 | 20 | 21 | src/ 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Facades/HubSpot.php: -------------------------------------------------------------------------------- 1 | includeConfig(); 15 | 16 | $this->app->bind(Discovery::class, function ($app) { 17 | $this->includeConfig(); 18 | 19 | $this->mergeConfigFrom( 20 | __DIR__.'/config/hubspot.php', 21 | 'hubspot' 22 | ); 23 | 24 | $handlerStack = \GuzzleHttp\HandlerStack::create(); 25 | 26 | if (config('hubspot.enable_constant_delay')) { 27 | $handlerStack->push( 28 | \HubSpot\RetryMiddlewareFactory::createRateLimitMiddleware( 29 | \HubSpot\Delay::getConstantDelayFunction() 30 | ) 31 | ); 32 | } 33 | 34 | if ($exponentialDelay = config('hubspot.exponential_delay')) { 35 | $handlerStack->push( 36 | \HubSpot\RetryMiddlewareFactory::createRateLimitMiddleware( 37 | \HubSpot\Delay::getExponentialDelayFunction($exponentialDelay) 38 | ) 39 | ); 40 | } 41 | 42 | $client = new Client(array_merge( 43 | config('hubspot.client_options'), 44 | [ 45 | 'handler' => $handlerStack, 46 | ] 47 | )); 48 | 49 | if ($accessToken = config('hubspot.access_token')) { 50 | return Factory::createWithAccessToken( 51 | $accessToken, 52 | $client, 53 | ); 54 | } 55 | 56 | return Factory::createWithDeveloperApiKey( 57 | config('hubspot.developer_key'), 58 | $client, 59 | ); 60 | }); 61 | } 62 | 63 | /** 64 | * Perform post-registration booting of services. 65 | */ 66 | public function boot() 67 | { 68 | // config 69 | $this->publishes([ 70 | __DIR__.'/config/hubspot.php' => config_path('hubspot.php'), 71 | ], 'config'); 72 | } 73 | 74 | protected function includeConfig(): void 75 | { 76 | $this->mergeConfigFrom( 77 | __DIR__.'/config/hubspot.php', 78 | 'hubspot' 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/config/hubspot.php: -------------------------------------------------------------------------------- 1 | env('HUBSPOT_ACCESS_TOKEN'), 8 | 9 | /* 10 | * Connect to the Hubspot API using a Developer API Key 11 | */ 12 | 'developer_key' => env('HUBSPOT_DEVELOPER_KEY'), 13 | 14 | /* 15 | * Options to enable built in middlewares to handle rate limiting 16 | * 17 | * @see https://github.com/HubSpot/hubspot-api-php#api-client-comes-with-middleware-for-implementation-of-rate-and-concurrent-limiting 18 | */ 19 | 'enable_constant_delay' => false, 20 | 'exponential_delay' => null, 21 | 22 | /* 23 | * Guzzle Client options that are user for Hubspot API requests 24 | * 25 | * @see https://docs.guzzlephp.org/en/stable/request-options.html 26 | */ 27 | 'client_options' => [ 28 | 'http_errors' => true, 29 | ], 30 | ]; 31 | -------------------------------------------------------------------------------- /tests/API/ContactsTest.php: -------------------------------------------------------------------------------- 1 | crm()->contacts()->basicApi()->getPage(); 17 | 18 | $this->assertIsArray($response->getResults()); 19 | 20 | // Test we have the default test contact 21 | /** @var SimplePublicObjectWithAssociations $contact */ 22 | $contact = $response->getResults()[0]; 23 | $this->assertEquals('Maria', $contact->getProperties()['firstname']); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | useEnvironmentPath(__DIR__.'/..'); 26 | $app->bootstrapWith([LoadEnvironmentVariables::class]); 27 | $app->bootstrapWith([LoadConfiguration::class]); 28 | parent::getEnvironmentSetUp($app); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Unit/Facades/HubspotFacadeTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Discovery::class, HubSpot::getFacadeRoot()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/Unit/ServiceProviderTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Discovery::class, $hubspot); 16 | } 17 | 18 | /** @test */ 19 | public function private_app_access_token_is_set_correctly() 20 | { 21 | $apiKey = 'MySecretKey'; 22 | 23 | Config::set('hubspot.access_token', $apiKey); 24 | 25 | /** @var Discovery $hubspot */ 26 | $hubspot = app(Discovery::class); 27 | 28 | /* 29 | * Use reflection API to access private/protected properties 30 | */ 31 | $config = (new \ReflectionObject($hubspot))->getParentClass()->getProperty('config'); 32 | $config->setAccessible(true); 33 | 34 | $accessToken = (new \ReflectionObject($config->getValue($hubspot)))->getProperty('accessToken'); 35 | $accessToken->setAccessible(true); 36 | 37 | $this->assertEquals($apiKey, $accessToken->getValue($config->getValue($hubspot))); 38 | } 39 | 40 | /** @test */ 41 | public function developer_key_is_set_correctly() 42 | { 43 | $devKey = 'MySecretKey'; 44 | 45 | Config::set('hubspot.access_token', null); 46 | Config::set('hubspot.developer_key', $devKey); 47 | 48 | $hubspot = app(Discovery::class); 49 | 50 | $config = (new \ReflectionObject($hubspot))->getParentClass()->getProperty('config'); 51 | $config->setAccessible(true); 52 | 53 | $accessToken = (new \ReflectionObject($config->getValue($hubspot)))->getProperty('developerApiKey'); 54 | $accessToken->setAccessible(true); 55 | 56 | $this->assertEquals($devKey, $accessToken->getValue($config->getValue($hubspot))); 57 | } 58 | } 59 | --------------------------------------------------------------------------------