Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ build
vendor
phpcs.xml
.phpunit.result.cache
*/.DS_Store
*/.DS_Store
src/assets/regions.json
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Changelog
## [1.2.1](https://github.com/contentstack/contentstack-utils-php/tree/v1.2.1) (2024-03-02)
- Support for the fragment tag in nested list
## [1.3.0](https://github.com/contentstack/contentstack-utils-php/tree/v1.3.0) (2026-06-03)
- Added `Endpoint::getContentstackEndpoint()` for dynamic region-aware URL resolution
- Added `Utils::getContentstackEndpoint()` proxy for backward-compatible access
- Bundled `regions.json` is now downloaded at `composer install` / `composer update` via `post-install-cmd`; the file is not committed to the repository
- Added runtime fallback in `Endpoint::loadRegions()` — downloads `regions.json` on first use when the file is absent (e.g. when the package is installed as a dependency)
- Added `composer refresh-regions` script to manually pull the latest regions from Contentstack
- Supports 7 regions (AWS NA/EU/AU, Azure NA/EU, GCP NA/EU) and 18 service endpoint keys

## [1.2.0](https://github.com/contentstack/contentstack-utils-php/tree/v1.2.0) (2023-06-27)
- Support for the br tag and support for nested assets in the the image
## [1.1.0](https://github.com/contentstack/contentstack-utils-php/tree/v1.1.0) (2021-07-16)
Expand Down
239 changes: 239 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,243 @@ use Contentstack\Utils\Model\Option;
...
$render_html_text = GQL::jsonToHtml($entry->rich_text_content,, new Option());
...
```

---

## Endpoint Resolution

The SDK ships with a built-in endpoint resolver that returns the correct Contentstack API URL for any region and any service — no hardcoded URLs needed.

### How `regions.json` is provisioned

`regions.json` is **not committed** to your project. It is downloaded automatically:

| When | How |
|---|---|
| `composer install` or `composer update` | `post-install-cmd` runs `scripts/download-regions.php` |
| First call to `getContentstackEndpoint()` when file is missing | Runtime fallback downloads and caches the file |
| Manual refresh | `composer refresh-regions` |

```sh
# Refresh when Contentstack adds new regions or services
composer refresh-regions
```

---

### `getContentstackEndpoint()`

Available on both `Endpoint` and `Utils` (identical behaviour):

```php
use Contentstack\Utils\Endpoint;
use Contentstack\Utils\Utils;

Endpoint::getContentstackEndpoint(string $region, string $service, bool $omitHttps): string|array
Utils::getContentstackEndpoint(string $region, string $service, bool $omitHttps): string|array
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `$region` | `string` | `'us'` | Region ID or any accepted alias (see table below) |
| `$service` | `string` | `''` | Service key. When empty, all endpoints for the region are returned as an array |
| `$omitHttps` | `bool` | `false` | When `true`, strips `https://` from the returned URL(s) |

---

### Supported Regions

| Region | Canonical ID | Accepted Aliases |
|---|---|---|
| AWS North America | `na` | `us`, `aws-na`, `aws_na`, `NA`, `US`, `AWS-NA`, `AWS_NA` |
| AWS Europe | `eu` | `aws-eu`, `aws_eu`, `EU`, `AWS-EU`, `AWS_EU` |
| AWS Australia | `au` | `aws-au`, `aws_au`, `AU`, `AWS-AU`, `AWS_AU` |
| Azure North America | `azure-na` | `azure_na`, `AZURE-NA`, `AZURE_NA` |
| Azure Europe | `azure-eu` | `azure_eu`, `AZURE-EU`, `AZURE_EU` |
| GCP North America | `gcp-na` | `gcp_na`, `GCP-NA`, `GCP_NA` |
| GCP Europe | `gcp-eu` | `gcp_eu`, `GCP-EU`, `GCP_EU` |

Alias matching is **case-insensitive** and accepts both `-` and `_` separators.

---

### Available Service Keys

| Key | Description |
|---|---|
| `contentDelivery` | Content Delivery API (CDN) — for fetching published entries and assets |
| `contentManagement` | Content Management API — for creating and updating content |
| `graphqlDelivery` | GraphQL Delivery API |
| `graphqlPreview` | GraphQL Live Preview |
| `preview` | REST Live Preview |
| `auth` | Authentication API |
| `application` | Contentstack web application URL |
| `images` | Image Delivery |
| `assets` | Asset Delivery |
| `automate` | Workflow Automation API |
| `launch` | Contentstack Launch API |
| `developerHub` | Developer Hub API |
| `brandKit` | Brand Kit API |
| `genAI` | Generative AI / Knowledge Vault |
| `personalizeManagement` | Personalization Management API |
| `personalizeEdge` | Personalization Edge API |
| `composableStudio` | Composable Studio API |
| `assetManagement` | Asset Management API |

---

### Examples

#### Get a single service URL

```php
use Contentstack\Utils\Endpoint;

// AWS North America — Content Delivery
$url = Endpoint::getContentstackEndpoint('na', 'contentDelivery');
// → "https://cdn.contentstack.io"

// AWS Europe — Content Management
$url = Endpoint::getContentstackEndpoint('eu', 'contentManagement');
// → "https://eu-api.contentstack.com"

// Azure North America — GraphQL Delivery
$url = Endpoint::getContentstackEndpoint('azure-na', 'graphqlDelivery');
// → "https://azure-na-graphql.contentstack.com"

// GCP Europe — Auth
$url = Endpoint::getContentstackEndpoint('gcp-eu', 'auth');
// → "https://gcp-eu-auth-api.contentstack.com"
```

#### Use an alias instead of the canonical ID

```php
// All of these return the same NA content delivery URL
Endpoint::getContentstackEndpoint('us', 'contentDelivery'); // → https://cdn.contentstack.io
Endpoint::getContentstackEndpoint('na', 'contentDelivery'); // → https://cdn.contentstack.io
Endpoint::getContentstackEndpoint('aws-na', 'contentDelivery'); // → https://cdn.contentstack.io
Endpoint::getContentstackEndpoint('AWS_NA', 'contentDelivery'); // → https://cdn.contentstack.io
```

#### Get a URL without the `https://` scheme

Pass `true` as the third argument when you need just the hostname (e.g. for `Stack::setHost()`):

```php
$host = Endpoint::getContentstackEndpoint('eu', 'contentDelivery', true);
// → "eu-cdn.contentstack.com"
```

#### Get all endpoints for a region

Omit the `$service` argument to receive the full associative array:

```php
$endpoints = Endpoint::getContentstackEndpoint('au');
// → [
// 'contentDelivery' => 'https://au-cdn.contentstack.com',
// 'contentManagement' => 'https://au-api.contentstack.com',
// 'graphqlDelivery' => 'https://au-graphql.contentstack.com',
// 'auth' => 'https://au-auth-api.contentstack.com',
// ...17 more keys
// ]

// With omitHttps
$hosts = Endpoint::getContentstackEndpoint('au', '', true);
// → [
// 'contentDelivery' => 'au-cdn.contentstack.com',
// 'contentManagement' => 'au-api.contentstack.com',
// ...
// ]
```

#### Via `Utils` (same result, no import change needed)

```php
use Contentstack\Utils\Utils;

$url = Utils::getContentstackEndpoint('gcp-na', 'contentDelivery');
// → "https://gcp-na-cdn.contentstack.com"
```

---

### Integration with the PHP Delivery SDK

Use `getContentstackEndpoint()` to resolve the host dynamically, then pass it to `Stack::setHost()`:

```php
use Contentstack\Contentstack;
use Contentstack\Utils\Endpoint;

$region = 'eu'; // change this one value to switch regions

// Resolve the content delivery host for the chosen region
$host = Endpoint::getContentstackEndpoint($region, 'contentDelivery', true);
// → "eu-cdn.contentstack.com"

// Initialise the delivery SDK
$stack = Contentstack::Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>');
$stack->setHost($host);

// Fetch entries — all requests now go to the EU CDN
$result = $stack->ContentType('<CONTENT_TYPE_UID>')->Query()->toJSON()->find();
```

#### Switching regions without changing any other code

```php
$regions = ['na', 'eu', 'au', 'azure-na', 'azure-eu', 'gcp-na', 'gcp-eu'];

foreach ($regions as $region) {
$host = Endpoint::getContentstackEndpoint($region, 'contentDelivery', true);
$stack = Contentstack::Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>');
$stack->setHost($host);

$result = $stack->ContentType('<CONTENT_TYPE_UID>')->Query()->toJSON()->find();
echo "{$region}: " . count($result[0]) . " entries\n";
}
```

---

### Error Handling

```php
use Contentstack\Utils\Endpoint;

// Empty region
try {
Endpoint::getContentstackEndpoint('');
} catch (\InvalidArgumentException $e) {
echo $e->getMessage();
// → "Empty region provided. Please put valid region."
}

// Unknown region
try {
Endpoint::getContentstackEndpoint('unknown-region', 'contentDelivery');
} catch (\InvalidArgumentException $e) {
echo $e->getMessage();
// → "Invalid region: unknown-region"
}

// Unknown service
try {
Endpoint::getContentstackEndpoint('na', 'unknownService');
} catch (\InvalidArgumentException $e) {
echo $e->getMessage();
// → "Service "unknownService" not found for region "na""
}

// regions.json missing and no network access
try {
Endpoint::getContentstackEndpoint('na', 'contentDelivery');
} catch (\RuntimeException $e) {
echo $e->getMessage();
// → "contentstack/utils: regions.json not found and could not be downloaded.
// Run "composer install" or "composer refresh-regions" and ensure network access."
}
```
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@
}
},
"scripts": {
"post-install-cmd": ["@php scripts/download-regions.php"],
"post-update-cmd": ["@php scripts/download-regions.php"],
"test": "phpunit",
"check-style": "phpcs src tests",
"fix-style": "phpcbf src tests"
"fix-style": "phpcbf src tests",
"refresh-regions": "@php scripts/download-regions.php"
},
"extra": {
"branch-alias": {
Expand Down
Loading
Loading