Skip to content

Commit 9a4a0a8

Browse files
committed
docs: Add Barta package development guidelines and update README to include SMS NOC as a supported gateway.
1 parent 51629ab commit 9a4a0a8

File tree

2 files changed

+292
-0
lines changed

2 files changed

+292
-0
lines changed

GEMINI.md

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# Barta Package Development Guidelines
2+
3+
These guidelines ensure consistency across the Barta SMS package codebase.
4+
5+
## PHP Code Style
6+
7+
### General Rules
8+
9+
- Always use `declare(strict_types=1);` at the top of every PHP file
10+
- Use PHP 8.4+ features (constructor promotion, named arguments, readonly, etc.)
11+
- Follow PSR-12 coding standards (enforced by Laravel Pint)
12+
- Run `composer format` before committing
13+
14+
### Class Structure
15+
16+
```php
17+
<?php
18+
19+
declare(strict_types=1);
20+
21+
namespace Larament\Barta\FeatureName;
22+
23+
// Imports grouped: PHP core, Laravel, Package internal
24+
use Exception;
25+
use Illuminate\Support\Facades\Http;
26+
use Larament\Barta\Data\ResponseData;
27+
28+
final class ClassName
29+
{
30+
// 1. Properties (with type hints)
31+
// 2. Constructor
32+
// 3. Public methods
33+
// 4. Protected methods
34+
// 5. Private methods
35+
}
36+
```
37+
38+
### Naming Conventions
39+
40+
| Element | Convention | Example |
41+
| ----------- | ---------------------------- | ------------------------------- |
42+
| Classes | PascalCase, singular | `EsmsDriver`, `SendSmsJob` |
43+
| Methods | camelCase, verb-first | `send()`, `formatPhoneNumber()` |
44+
| Properties | camelCase | `$recipients`, `$baseUrl` |
45+
| Config keys | snake_case | `api_token`, `sender_id` |
46+
| Env vars | UPPER_SNAKE_CASE with prefix | `BARTA_ESMS_TOKEN` |
47+
48+
### Class Modifiers
49+
50+
- Use `final` for concrete implementations (drivers, jobs)
51+
- Use `abstract` for base classes meant to be extended
52+
- Use `readonly` for immutable data objects
53+
- Combine traits on single line: `use Trait1, Trait2, Trait3;`
54+
55+
---
56+
57+
## Driver Development
58+
59+
### Creating a New Driver
60+
61+
1. Extend `AbstractDriver`
62+
2. Mark as `final class`
63+
3. Implement `send(): ResponseData`
64+
4. Override `validate()` to check driver-specific config
65+
5. Use `$this->recipients` (array) and `$this->message` (string)
66+
67+
### Driver Template
68+
69+
```php
70+
<?php
71+
72+
declare(strict_types=1);
73+
74+
namespace Larament\Barta\Drivers;
75+
76+
use Illuminate\Support\Facades\Http;
77+
use Larament\Barta\Data\ResponseData;
78+
use Larament\Barta\Exceptions\BartaException;
79+
80+
final class NewGatewayDriver extends AbstractDriver
81+
{
82+
private string $baseUrl = 'https://api.gateway.com';
83+
84+
public function send(): ResponseData
85+
{
86+
$this->validate();
87+
88+
$response = Http::baseUrl($this->baseUrl)
89+
->withToken($this->config['api_token'])
90+
->timeout($this->timeout)
91+
->retry($this->retry, $this->retryDelay)
92+
->acceptJson()
93+
->post('/sms/send', [
94+
'to' => implode(',', $this->recipients),
95+
'message' => $this->message,
96+
'sender' => $this->config['sender_id'],
97+
])
98+
->json();
99+
100+
if ($response['status'] !== 'success') {
101+
throw new BartaException($response['error']);
102+
}
103+
104+
return new ResponseData(
105+
success: true,
106+
data: $response,
107+
);
108+
}
109+
110+
protected function validate(): void
111+
{
112+
parent::validate();
113+
114+
if (! $this->config['api_token']) {
115+
throw new BartaException('Please set api_token for NewGateway in config/barta.php.');
116+
}
117+
118+
if (! $this->config['sender_id']) {
119+
throw new BartaException('Please set sender_id for NewGateway in config/barta.php.');
120+
}
121+
}
122+
}
123+
```
124+
125+
### Driver Checklist
126+
127+
- [ ] Extends `AbstractDriver`
128+
- [ ] Uses `final class`
129+
- [ ] Calls `$this->validate()` first in `send()`
130+
- [ ] Uses `implode(',', $this->recipients)` for bulk support
131+
- [ ] Uses `$this->timeout`, `$this->retry`, `$this->retryDelay`
132+
- [ ] Returns `ResponseData` object
133+
- [ ] Throws `BartaException` on API errors
134+
- [ ] Validates required config in `validate()`
135+
- [ ] Registered in `BartaManager`
136+
- [ ] Config added to `config/barta.php`
137+
- [ ] Has comprehensive tests
138+
139+
---
140+
141+
## Testing Guidelines
142+
143+
### Test File Structure
144+
145+
- Location: `tests/` mirrors `src/` structure
146+
- Naming: `{ClassName}Test.php`
147+
- Use Pest PHP (not PHPUnit classes)
148+
149+
### Test Patterns
150+
151+
```php
152+
<?php
153+
154+
declare(strict_types=1);
155+
156+
use Illuminate\Support\Facades\Http;
157+
use Larament\Barta\Drivers\NewDriver;
158+
use Larament\Barta\Exceptions\BartaException;
159+
160+
beforeEach(function () {
161+
// Set up config for each test
162+
config()->set('barta.drivers.new.api_token', 'test_token');
163+
config()->set('barta.drivers.new.sender_id', 'test_sender');
164+
});
165+
166+
it('can instantiate the driver', function () {
167+
$driver = new NewDriver(config('barta.drivers.new'));
168+
expect($driver)->toBeInstanceOf(NewDriver::class);
169+
});
170+
171+
it('sends sms successfully', function () {
172+
Http::fake([
173+
'https://api.gateway.com/*' => Http::response(['status' => 'success'], 200),
174+
]);
175+
176+
$driver = new NewDriver(config('barta.drivers.new'));
177+
$response = $driver->to('8801700000000')->message('Test')->send();
178+
179+
expect($response->success)->toBeTrue();
180+
181+
Http::assertSent(function ($request) {
182+
return str_contains($request->url(), 'gateway.com') &&
183+
$request['message'] === 'Test';
184+
});
185+
});
186+
187+
it('throws exception on api error', function () {
188+
Http::fake([
189+
'*' => Http::response(['status' => 'error', 'error' => 'Failed'], 200),
190+
]);
191+
192+
$driver = new NewDriver(config('barta.drivers.new'));
193+
$driver->to('8801700000000')->message('Test')->send();
194+
})->throws(BartaException::class);
195+
196+
it('throws exception if config missing', function () {
197+
config()->set('barta.drivers.new.api_token', null);
198+
199+
$driver = new NewDriver(config('barta.drivers.new'));
200+
$driver->to('8801700000000')->message('Test')->send();
201+
})->throws(BartaException::class, 'Please set api_token');
202+
```
203+
204+
### Test Coverage Requirements
205+
206+
- Every driver: instantiation, success, bulk, error, config validation
207+
- Every public method must have at least one test
208+
- Use `Http::fake()` for API calls
209+
- Use `Bus::fake()` for queue tests
210+
- Use `Log::shouldReceive()` for log assertions
211+
212+
### Test Commands
213+
214+
```bash
215+
// turbo-all
216+
composer test # Run all tests
217+
composer test-coverage # Run with coverage report
218+
composer analyse # Run PHPStan
219+
```
220+
221+
---
222+
223+
## Exception Handling
224+
225+
### Use Package Exception
226+
227+
Always throw `BartaException` for package-related errors:
228+
229+
```php
230+
use Larament\Barta\Exceptions\BartaException;
231+
232+
// API errors
233+
throw new BartaException($response['error']);
234+
235+
// Config errors (use descriptive message with config path)
236+
throw new BartaException('Please set api_token for ESMS in config/barta.php.');
237+
238+
// Use static factory methods when available
239+
throw BartaException::invalidNumber($number);
240+
throw BartaException::missingRecipient();
241+
throw BartaException::missingMessage();
242+
```
243+
244+
---
245+
246+
## Configuration
247+
248+
### Config File Pattern
249+
250+
```php
251+
'drivers' => [
252+
'drivername' => [
253+
'api_token' => env('BARTA_DRIVERNAME_TOKEN'),
254+
'api_key' => env('BARTA_DRIVERNAME_API_KEY'),
255+
'sender_id' => env('BARTA_DRIVERNAME_SENDER_ID'),
256+
],
257+
],
258+
```
259+
260+
### Env Variable Naming
261+
262+
- Prefix: `BARTA_`
263+
- Driver name in uppercase: `ESMS`, `MIMSMS`
264+
- Config key in uppercase: `TOKEN`, `SENDER_ID`
265+
- Full pattern: `BARTA_{DRIVER}_{KEY}`
266+
267+
---
268+
269+
## ResponseData Contract
270+
271+
Always return `ResponseData` from driver's `send()`:
272+
273+
```php
274+
return new ResponseData(
275+
success: true, // bool: whether operation succeeded
276+
data: $response, // array: raw API response
277+
errors: [], // array: error messages (optional)
278+
);
279+
```
280+
281+
---
282+
283+
## Quality Assurance Checklist
284+
285+
Before committing:
286+
287+
- [ ] `composer format` - Code formatted with Pint
288+
- [ ] `composer test` - All tests pass
289+
- [ ] `composer analyse` - PHPStan passes (level max)
290+
- [ ] README updated if adding features
291+
- [ ] CHANGELOG.md updated for releases

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Barta is a clean, expressive Laravel package designed to integrate popular Bangl
4848
| [GreenWeb](https://greenweb.com.bd) | `greenweb` | ✅ Supported |
4949
| [BulkSMS BD](https://bulksmsbd.net) | `bulksms` | ✅ Supported |
5050
| [ElitBuzz](https://elitbuzz.com) | `elitbuzz` | ✅ Supported |
51+
| [SMS NOC](https://smsnoc.com) | `smsnoc` | ✅ Supported |
5152

5253
> **Want more gateways?** [Request a gateway](https://github.com/iRaziul/barta/issues) or [contribute a driver](#-creating-custom-drivers).
5354

0 commit comments

Comments
 (0)