├── .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 | [](https://packagist.org/packages/rossjcooper/laravel-hubspot) [](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 |
--------------------------------------------------------------------------------