Skip to content

Commit 44ee41e

Browse files
committed
first release
1 parent 2bbe9db commit 44ee41e

27 files changed

Lines changed: 1183 additions & 2 deletions

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "composer"
9+
directory: "/"
10+
schedule:
11+
interval: "monthly"

.github/workflows/publish.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Publish Package
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
jobs:
9+
publish:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: shivammathur/setup-php@v2
14+
with:
15+
php-version: '8.1'
16+
- run: composer install --no-dev --prefer-dist
17+
18+
- uses: packagist/action@v1
19+
with:
20+
package_name: screenshotmax/sdk
21+
api_token: ${{ secrets.PACKAGIST_TOKEN }}

.github/workflows/test.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
php:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: shivammathur/setup-php@v2
15+
with:
16+
php-version: '8.1'
17+
tools: phpunit
18+
- run: composer install --no-interaction --working-dir=.
19+
- run: phpunit -c phpunit.xml

README.md

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,102 @@
1-
# php-sdk
2-
Official PHP SDK for the ScreenshotMAX.com API
1+
# ScreenshotMAX PHP SDK
2+
3+
[![test](https://github.com/screenshotmax/php-sdk/actions/workflows/test.yml/badge.svg)](https://github.com/screenshotmax/php-sdk/actions/workflows/test.yml)
4+
5+
This is the official PHP SDK for the [ScreenshotMAX API](https://screenshotmax.com/).
6+
7+
It allows you to easily capture high-quality screenshots of any URL directly from your applications.
8+
The SDK handles authentication, request signing, and provides a simple interface to integrate ScreenshotMAX’s powerful screenshot services into your Python projects.
9+
10+
Get started in minutes. Just [sign up](https://screenshotmax.com) to receive your access and secret keys, import the client, and you’re ready to capture screenshots.”
11+
12+
The SDK client is synchronized with the latest [ScreenshotMAX API options](https://docs.screenshotmax.com/guides/start/introduction).
13+
14+
## Installation
15+
```bash
16+
composer require screenshotmax/sdk
17+
```
18+
19+
## Usage
20+
21+
Use the SDK to generate signed or unsigned URLs for screenshots, PDFs, web scraping, or animated screenshot—without executing the request. Or fetch and download the result directly. You have full control over when and how each capture runs.
22+
23+
### Screenshot example
24+
```php
25+
use ScreenshotMax\SDK;
26+
use ScreenshotMax\Options\ScreenshotOptions;
27+
28+
$sdk = new SDK('<ACCESS_KEY>', '<SECRET_KEY>');
29+
30+
$opts = new ScreenshotOptions();
31+
$opts->url = 'https://example.com';
32+
$opts->format = 'png';
33+
34+
$sdk->screenshot->setOptions($opts);
35+
36+
$url = $sdk->screenshot->getUrl();
37+
$result = $sdk->screenshot->fetch();
38+
file_put_contents('screenshot.png', $result['data']);
39+
```
40+
41+
### Web scraping example
42+
```php
43+
use ScreenshotMax\SDK;
44+
use ScreenshotMax\Options\ScrapeOptions;
45+
46+
$sdk = new SDK('<ACCESS_KEY>', '<SECRET_KEY>');
47+
48+
$opts = new ScrapeOptions();
49+
$opts->url = 'https://example.com';
50+
$opts->format = 'html';
51+
52+
$sdk->scrape->setOptions($opts);
53+
54+
$url = $sdk->scrape->getUrl();
55+
$result = $sdk->scrape->fetch();
56+
file_put_contents('scrape.html', $result['data']);
57+
```
58+
59+
### PDF generation example
60+
```php
61+
use ScreenshotMax\SDK;
62+
use ScreenshotMax\Options\PDFOptions;
63+
64+
$sdk = new SDK('<ACCESS_KEY>', '<SECRET_KEY>');
65+
66+
$opts = new PDFOptions();
67+
$opts->url = 'https://example.com';
68+
$opts->pdf_paper_format = 'a4';
69+
70+
$sdk->pdf->setOptions($opts);
71+
72+
$url = $sdk->pdf->getUrl();
73+
$result = $sdk->pdf->fetch();
74+
file_put_contents('pdf.pdf', $result['data']);
75+
```
76+
77+
### Scheduled task example
78+
```php
79+
use ScreenshotMax\SDK;
80+
81+
$sdk = new SDK('<ACCESS_KEY>', '<SECRET_KEY>');
82+
83+
# get all tasks from account
84+
$tasks = $sdk->task->get_tasks()
85+
# {"tasks":[{
86+
# "id":5678133109850112,
87+
# "name":"Test CRON",
88+
# "api":"screenshot",
89+
# "query":
90+
# "url=https%3A%2F%2Fexample.com",
91+
# "frequency":"every_day",
92+
# "crontab":"25 13 * * *",
93+
# "timezone":"Etc/UTC",
94+
# "enabled":true,
95+
# "created":1747229104,
96+
# "last_run":1748611516,
97+
# "runs":18}]}
98+
```
99+
100+
## License
101+
102+
`screenshotmax/sdk` is released under [the MIT license](LICENSE).

composer.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "screenshotmax/sdk",
3+
"description": "Official PHP SDK for the ScreenshotMAX API",
4+
"type": "library",
5+
"require": {
6+
"php": ">=8.0"
7+
},
8+
"autoload": {
9+
"psr-4": {
10+
"ScreenshotMax\\": "src/"
11+
}
12+
}
13+
}

phpunit.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit colors="true" bootstrap="vendor/autoload.php">
3+
<testsuites>
4+
<testsuite name="SDK Tests">
5+
<directory>tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
</phpunit>

src/ApiClient.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
namespace ScreenshotMax;
3+
4+
class ApiClient
5+
{
6+
private string $baseUrl = 'https://api.screenshotmax.com';
7+
private string $accessKey;
8+
private string $secretKey;
9+
10+
public function __construct(string $accessKey, string $secretKey)
11+
{
12+
if (empty($accessKey) || empty($secretKey)) {
13+
throw new \InvalidArgumentException('Access and secret keys must both be provided and non-empty.');
14+
}
15+
$this->accessKey = $accessKey;
16+
$this->secretKey = $secretKey;
17+
}
18+
19+
private function signRequest(string $str): string
20+
{
21+
return hash_hmac('sha256', $str, $this->secretKey);
22+
}
23+
24+
private function computeQuery(array $obj): string
25+
{
26+
$filtered = array_filter($obj, fn($v) => $v !== null);
27+
return http_build_query($filtered);
28+
}
29+
30+
public function generateUrl(string $path, array $params = []): string
31+
{
32+
$query = $this->computeQuery(array_merge($params, ['access_key' => $this->accessKey]));
33+
return $this->baseUrl . $path . '?' . $query;
34+
}
35+
36+
public function generateSignedUrl(string $path, array $params = []): string
37+
{
38+
$query = $this->computeQuery(array_merge($params, ['access_key' => $this->accessKey]));
39+
$signature = $this->signRequest($query);
40+
return $this->baseUrl . $path . '?' . $query . '&signature=' . $signature;
41+
}
42+
43+
private function exec(string $method, string $url, array $options = [], array $headers = []): array
44+
{
45+
$ch = curl_init($url);
46+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
47+
curl_setopt($ch, CURLOPT_HEADER, true);
48+
49+
if ($method === 'POST') {
50+
curl_setopt($ch, CURLOPT_POST, true);
51+
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options));
52+
} elseif ($method === 'PATCH' || $method === 'DELETE') {
53+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
54+
if ($method === 'PATCH') {
55+
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options));
56+
}
57+
}
58+
59+
if ($headers) {
60+
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
61+
}
62+
63+
$response = curl_exec($ch);
64+
if ($response === false) {
65+
$err = curl_error($ch);
66+
curl_close($ch);
67+
throw new \RuntimeException($err);
68+
}
69+
70+
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
71+
$headerString = substr($response, 0, $headerSize);
72+
$body = substr($response, $headerSize);
73+
$parsedHeaders = [];
74+
foreach (explode("\r\n", trim($headerString)) as $line) {
75+
if (strpos($line, ':') !== false) {
76+
[$k, $v] = explode(':', $line, 2);
77+
$parsedHeaders[trim($k)] = trim($v);
78+
}
79+
}
80+
curl_close($ch);
81+
82+
return ['data' => $body, 'headers' => $parsedHeaders];
83+
}
84+
85+
public function get(string $path, array $options = [], bool $signed = false): array
86+
{
87+
$url = $signed ? $this->generateSignedUrl($path, $options) : $this->generateUrl($path, $options);
88+
return $this->exec('GET', $url);
89+
}
90+
91+
public function post(string $path, array $options = []): array
92+
{
93+
$url = $this->baseUrl . $path;
94+
return $this->exec('POST', $url, $options, [
95+
'Content-Type: application/json',
96+
'X-Access-Key: ' . $this->accessKey,
97+
]);
98+
}
99+
100+
public function delete(string $path): void
101+
{
102+
$url = $this->baseUrl . $path;
103+
$this->exec('DELETE', $url, [], [
104+
'X-Access-Key: ' . $this->accessKey,
105+
]);
106+
}
107+
108+
public function patch(string $path, array $options = []): array
109+
{
110+
$url = $this->baseUrl . $path;
111+
return $this->exec('PATCH', $url, $options, [
112+
'Content-Type: application/json',
113+
'X-Access-Key: ' . $this->accessKey,
114+
]);
115+
}
116+
}

src/Options/PDFOptions.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
namespace ScreenshotMax\Options;
3+
4+
class PDFOptions extends ScreenshotOptions
5+
{
6+
public ?string $pdf_paper_format = null;
7+
public ?bool $pdf_landscape = null;
8+
public ?bool $pdf_print_background = null;
9+
}

src/Options/ScrapeOptions.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace ScreenshotMax\Options;
3+
4+
class ScrapeOptions extends ScreenshotOptions
5+
{
6+
}

src/Options/ScreencastOptions.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
namespace ScreenshotMax\Options;
3+
4+
class ScreencastOptions extends ScreenshotOptions
5+
{
6+
public ?int $duration = null;
7+
public ?string $scenario = null;
8+
public ?int $scroll_by_amount = null;
9+
public ?int $scroll_by_delay = null;
10+
public ?int $scroll_by_duration = null;
11+
public ?bool $scroll_back = null;
12+
public ?int $scroll_back_delay = null;
13+
public ?string $scroll_easing = null;
14+
}

0 commit comments

Comments
 (0)