Skip to content

Commit 20d7df4

Browse files
author
Michael Lundbøl
committed
Initial commit
0 parents  commit 20d7df4

28 files changed

+2074
-0
lines changed

.gitattributes

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.gitattributes export-ignore
6+
/.gitignore export-ignore
7+
/.travis.yml export-ignore
8+
/phpunit.xml export-ignore
9+
/tests export-ignore
10+
/.editorconfig export-ignore
11+
/phpunit.gitlab.xml export-ignore
12+
/gitlab-test-mysql.sh export-ignore
13+
/.gitlab-ci.yml export-ignore

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/vendor
2+
/.idea
3+
/.vagrant
4+
.php_cs.cache
5+
_ide_helper.php
6+
.phpstorm.meta.php
7+
coverage
8+
coverage.xml
9+
phpunit.local.xml
10+
composer.lock
11+
/tests/_output

.php_cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->exclude('tests')
5+
->exclude('vendor')
6+
->in(__DIR__)
7+
;
8+
9+
return PhpCsFixer\Config::create()
10+
->setUsingCache(true)
11+
->setRiskyAllowed(true)
12+
->setFinder($finder)
13+
->setRules([
14+
'psr4' => true,
15+
'concat_space' => ['spacing' => 'one'],
16+
'no_empty_statement' => true,
17+
'elseif' => true,
18+
'no_extra_consecutive_blank_lines' => true,
19+
'line_ending' => true,
20+
'ordered_imports' => true,
21+
'no_spaces_inside_parenthesis' => true,
22+
'no_leading_import_slash' => true,
23+
'no_extra_consecutive_blank_lines' => ['use'],
24+
'blank_line_before_return' => true,
25+
'full_opening_tag' => true,
26+
'array_syntax' => ['syntax' => 'short'],
27+
'trim_array_spaces' => true,
28+
'no_trailing_whitespace' => true,
29+
'unary_operator_spaces' => true,
30+
'no_unused_imports' => true,
31+
'no_whitespace_in_blank_line' => true,
32+
]);

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
language: php
2+
php:
3+
- '5.5'
4+
before_script:
5+
- travis_retry composer self-update
6+
- travis_retry composer install --prefer-source --no-interaction
7+
notifications:
8+
email: false

CONTRIBUTING.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Contributing to the Library
2+
3+
4+
## Issues
5+
Contributions are always welcome, if you have found a bug or want to report a problem please open an issue and provide as much detail as you can.
6+
7+
8+
## Code
9+
If you want to contribute a code change such as a fix or feature enhancement you can do this through a pull request, please ensure any new code comes with full test coverage.
10+
11+
If your interested in adding a big feature please raise an issue first to ensure that it doesn't go against what we are trying to achieve here.
12+
13+
### Code Standards
14+
This library adheres to the PSR-1 and PSR-2 standards and any new code must do the same.

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) <2015> <E-Crunch Ltd>
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
13+
all 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
21+
THE SOFTWARE.

README.md

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
[![Current Version](https://img.shields.io/packagist/v/crunch-accounting/salesforce-api.svg?style=flat-square)](https://packagist.org/packages/crunch-accounting/salesforce-api)
2+
[![License](https://img.shields.io/packagist/l/crunch-accounting/salesforce-api.svg?style=flat-square)](https://packagist.org/packages/crunch-accounting/salesforce-api)
3+
[![Scrutinizer](https://img.shields.io/scrutinizer/g/crunch-accounting/salesforce-api-php-wrapper.svg?style=flat-square)](https://scrutinizer-ci.com/g/crunch-accounting/salesforce-api-php-wrapper/)
4+
[![Travis](https://img.shields.io/travis/crunch-accounting/salesforce-api-php-wrapper.svg?style=flat-square)](https://travis-ci.org/crunch-accounting/salesforce-api-php-wrapper)
5+
6+
# Salesforce PHP Library
7+
8+
A simple library for interacting with the Salesforce REST API.
9+
10+
Methods for setting up a connection, requesting an access token, refreshing the access token, saving the access token, and making calls against the API.
11+
12+
13+
## Getting started
14+
15+
__Installation:__
16+
The package should be installed through composer and locked to a major version
17+
```
18+
composer require napp/salesforce-api:~1.0
19+
```
20+
21+
__Getting an OAuth Token:__
22+
23+
___With User interaction:___
24+
You need to fetch an access token for a user, all followup requests will be performed against this user.
25+
26+
```php
27+
$sfClient = \Crunch\Salesforce\Client::create('https://test.salesforce.com/', 'clientid', 'clientsecret', 'v37.0');
28+
29+
if ( ! isset($_GET['code'])) {
30+
31+
$url = $sfClient->getLoginUrl('http://example.com/sf-login');
32+
header('Location: '.$url);
33+
exit();
34+
35+
} else {
36+
37+
$token = $sfClient->authorizeConfirm($_GET['code'], 'http://example.com/sf-login');
38+
39+
}
40+
41+
```
42+
43+
___When having the username and password:___
44+
To use this method you also need the security token to be appended to the password.
45+
Keep in mind this method is to be used as a replacement for the old API Key workflow.
46+
47+
```php
48+
$sfClient = \Crunch\Salesforce\Client::create('https://test.salesforce.com/', 'clientid', 'clientsecret');
49+
$sfClient->login('username', 'passwordAndSecurityTokenAppended');
50+
51+
```
52+
53+
54+
__Performing an action:__
55+
Once you have an access token you can perform requests against the API.
56+
57+
```php
58+
$sfClient = \Crunch\Salesforce\Client::create('https://test.salesforce.com/', 'clientid', 'clientsecret');
59+
$tokenGenerator = new \Crunch\Salesforce\AccessTokenGenerator();
60+
$accessToken = $tokenGenerator->createFromJson($_SESSION['accessToken']);
61+
$sfClient->setAccessToken($accessToken);
62+
63+
$results = $sfClient->search('SELECT Name, Email FROM Lead Limit 10');
64+
print_r($results);
65+
66+
```
67+
68+
The token will expire after an hour so you should make sure you're checking the expiry time and refreshing accordingly.
69+
70+
## Setting up the Salesforce client
71+
72+
The client can be configured in two ways, you can call the static create method above passing in the login url and oauth
73+
details or you can use a configuration object as in the example below. This is useful when you need to resolve
74+
the client out of an ioc container.
75+
76+
The configuration data for the client is passed in through a config file which must implement `\Crunch\Salesforce\ClientConfigInterface`
77+
78+
For example
79+
80+
```php
81+
class SalesforceConfig implements \Crunch\Salesforce\ClientConfigInterface {
82+
83+
/**
84+
* @return string
85+
*/
86+
public function getLoginUrl()
87+
{
88+
return 'https://test.salesforce.com/';
89+
}
90+
91+
/**
92+
* @return string
93+
*/
94+
public function getClientId()
95+
{
96+
return 'clientid';
97+
}
98+
99+
/**
100+
* @return string
101+
*/
102+
public function getClientSecret()
103+
{
104+
return 'clientsecret';
105+
}
106+
107+
/**
108+
* Version of the API you wish to use
109+
* @return string
110+
*/
111+
public function getVersion()
112+
{
113+
return 'v37.0';
114+
}
115+
}
116+
117+
```
118+
119+
A config class is provided and can be used if needed. `\Crunch\Salesforce\ClientConfig`
120+
121+
122+
The Salesforce client can then be instantiated with the config object and an instance of the Guzzle v4 client.
123+
124+
```php
125+
$sfConfig = new SalesforceConfig();
126+
$sfClient = new \Crunch\Salesforce\Client($sfConfig, new GuzzleHttp\Client());
127+
128+
```
129+
130+
## Authentication
131+
Authentication happens via oauth2 and the login url can be generated using the `getLoginUrl` method, you should pass this your return url for the send stage of the oauth process.
132+
133+
```php
134+
$url = $sfClient->getLoginUrl('http://exmaple.com/sf-login');
135+
136+
```
137+
138+
You should redirect the user to this returned url, on completion they will be redirected back with a code in the query string.
139+
140+
The second stage of the authentication can then be completed.
141+
142+
```php
143+
$token = $sfClient->authorizeConfirm($_GET['code'], 'http://exmaple.com/sf-login');
144+
145+
```
146+
147+
The token returned from here is the raw data and can be passed to the access token generator to make an `AccessToken`.
148+
149+
150+
```php
151+
$tokenGenerator = new \Crunch\Salesforce\AccessTokenGenerator();
152+
$accessToken = $tokenGenerator->createFromSalesforceResponse($token);
153+
154+
```
155+
156+
### Storing the access token
157+
This access token should be stored. A method to store this on the file system is provided but this isn't required.
158+
159+
The example above uses the php session to achieve the same result.
160+
161+
The `LocalFileStore` object needs to be instantiated with access to the token generator and a config class which implements `\Crunch\Salesforce\TokenStore\LocalFileConfigInterface`
162+
163+
```php
164+
class SFLocalFileStoreConfig implements \Crunch\Salesforce\TokenStore\LocalFileConfigInterface {
165+
166+
/**
167+
* The path where the file will be stored, no trailing slash, must be writable
168+
*
169+
* @return string
170+
*/
171+
public function getFilePath()
172+
{
173+
return __DIR__;
174+
}
175+
}
176+
177+
```
178+
179+
The token store can then be created and used to save the access token to the local file system as well as fetching a previously saved token.
180+
181+
```php
182+
$tokenStore = new \Crunch\Salesforce\TokenStore\LocalFile(new \Crunch\Salesforce\AccessTokenGenerator, new SFLocalFileStoreConfig);
183+
184+
//Save a token
185+
$tokenStore->saveAccessToken($accessToken);
186+
187+
//Fetch a token
188+
$accessToken = $tokenStore->fetchAccessToken();
189+
190+
```
191+
192+
### Refreshing the token
193+
The access token only lasts 1 hour before expiring so you should regularly check its status and refresh it accordingly.
194+
195+
```php
196+
$accessToken = $tokenStore->fetchAccessToken();
197+
198+
if ($accessToken->needsRefresh()) {
199+
200+
$accessToken = $sfClient->refreshToken();
201+
202+
$tokenStore->saveAccessToken($accessToken);
203+
}
204+
205+
```
206+
207+
## Making requests
208+
209+
Before making a request you should instantiate the client as above and then assign the access token to it.
210+
211+
```php
212+
$sfConfig = new SalesforceConfig();
213+
$sfClient = new \Crunch\Salesforce\Client($sfConfig, new \GuzzleHttp\Client());
214+
215+
$sfClient->setAccessToken($accessToken);
216+
217+
```
218+
219+
### Performing an SOQL Query
220+
This is a powerful option for performing general queries against your salesforce data.
221+
Simply pass a valid query to the search method and the resulting data will be returned.
222+
223+
```php
224+
$data = $sfClient->search('SELECT Email, Name FROM Lead LIMIT 10');
225+
226+
```
227+
228+
### Fetching a single record
229+
If you know the id and type of a record you can fetch a set of fields from it.
230+
231+
```php
232+
$data = $sfClient->getRecord('Lead', '00WL0000008wVl1MDE', ['name', 'email', 'phone']);
233+
234+
```
235+
236+
### Creating and updating records
237+
The process for creating and updating records is very similar and can be performed as follows.
238+
The createRecord method will return the id of the newly created record.
239+
240+
```php
241+
$data = $sfClient->createRecord('Lead', ['email' => '[email protected]', 'Company' => 'New test', 'lastName' => 'John Doe']);
242+
243+
$sfClient->updateRecord('Lead', '00WL0000008wVl1MDE', ['lastName' => 'Steve Jobs']);
244+
// or with the above freshly created client
245+
$sfClient->updateRecord('Lead', $data, ['lastName' => 'Steve Jobs']);
246+
247+
```
248+
249+
### Deleting records
250+
Records can be deleted based on their id and type.
251+
252+
```php
253+
$sfClient->deleteRecord('Lead', '00WL0000008wVl1MDE');
254+
255+
```
256+
257+
## Errors
258+
If something goes wrong the library will throw an exception.
259+
260+
If its an authentication exception such as an expired token this will be as `Crunch\Salesforce\Exceptions\AuthenticationException`,
261+
you can get the exact details using the methods `getMessage` and `getErrorCode`.
262+
263+
All other errors will be `Crunch\Salesforce\Exceptions\RequestException`, the salesforce error will be in the message
264+
265+
266+
```php
267+
try {
268+
269+
$results = $sfClient->search('SELECT Name, Email FROM Lead Limit 10');
270+
print_r($results);
271+
272+
} catch (\Crunch\Salesforce\Exceptions\RequestException $e) {
273+
274+
echo $e->getMessage();
275+
echo $e->getErrorCode();
276+
277+
} catch (\Crunch\Salesforce\Exceptions\AuthenticationException $e) {
278+
279+
echo $e->getErrorCode();
280+
281+
}
282+
283+
```

0 commit comments

Comments
 (0)