diff --git a/.cursor/rules/cloudinary.mdc b/.cursor/rules/cloudinary.mdc new file mode 100644 index 00000000..8a952f2d --- /dev/null +++ b/.cursor/rules/cloudinary.mdc @@ -0,0 +1,8 @@ +--- +description: Cloudinary cloudinary_php — agent guide +alwaysApply: true +--- + +Read and follow `AGENTS.md` in the repository root. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..e07d589e --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,5 @@ +# Cloudinary cloudinary_php — instructions for AI coding agents + +Read `AGENTS.md` in the repository root and follow it. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..020efc85 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,64 @@ +# AGENTS.md — cloudinary_php + +## What this package is (one line) +Official Cloudinary **PHP server-side SDK**: upload assets, build transformation/delivery URLs and HTML tags, and call the Admin API from your backend — the package that holds your `API_SECRET`. + +## When to use this / when NOT to use this +- **Use this when:** code runs on a **server** (Laravel, Symfony, plain PHP, a CLI worker) and needs signed/preset uploads, asset administration (search, rename, tag, delete, folders), or signed delivery URLs and tags where the `API_SECRET` must stay private. +- **Do NOT use this when:** you are building **browser-side** delivery URLs — use [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) in the frontend, never a PHP package; or you want the autonomous/no-code path — use the [Cloudinary MCP server](https://github.com/cloudinary/mcp-servers). +- **Sibling packages:** this SDK already **bundles** the lower-level transformation builder [`php-transformation-builder-sdk`](https://github.com/cloudinary/php-transformation-builder-sdk) (Composer dep `cloudinary/transformation-builder-sdk: ^2`) — prefer this package over depending on it directly. A separate [`php-url-builder`](https://github.com/cloudinary/php-url-builder) exists as a low-level helper but is **not** a dependency of this SDK. Rule of thumb: server → this package; browser → `@cloudinary/url-gen`. + +## Setup +```bash +composer require "cloudinary/cloudinary_php" +``` +Required configuration / credentials (the SDK reads `CLOUDINARY_URL` automatically): +```bash +export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME +``` + +## Minimal runnable example +```php +use Cloudinary\Cloudinary; +use Cloudinary\Transformation\Resize; +use Cloudinary\Transformation\Format; + +$cloudinary = new Cloudinary(); // reads CLOUDINARY_URL from env + +// Upload a local file (server-side, signed) +$cloudinary->uploadApi()->upload('my_image.jpg'); + +// Build a delivery URL for an uploaded asset +echo $cloudinary->image('sample.jpg') + ->resize(Resize::fill()->width(100)->height(150)) + ->format(Format::auto()); +``` + +## Build / test commands (run these after editing) +Requires PHP 8.0+ and Composer. There is **no** `scripts` block in `composer.json`; invoke the dev binaries in `vendor/bin/` directly. **Only `simple-phpunit` runs in CI** (`.github/workflows/test.yaml`); `phpcs`/`php-cs-fixer` are local-only dev tools, not wired into any workflow. +```bash +composer install # or `composer update -n` as CI does +vendor/bin/simple-phpunit # the test suite (symfony/phpunit-bridge) — this is what CI runs; run after any change to src/ +vendor/bin/phpcs # local lint against the committed phpcs.xml (squizlabs/php_codesniffer) +``` +Tests hit a real cloud: CI sets `CLOUDINARY_URL` before running (`tools/get_test_cloud.sh`); locally export your own `CLOUDINARY_URL` first or the integration tests will fail. + +## Conventions & gotchas +- **Formatter/linter (local only, not in CI):** a PSR-style ruleset is committed as `phpcs.xml` (PHP_CodeSniffer). `friendsofphp/php-cs-fixer` is also a dev dep, but **no `.php-cs-fixer` config is committed at the repo root**, so it runs with its defaults. +- **Autoload:** `src/` is classmap-autoloaded; tests are PSR-4 under `Cloudinary\Test\` → `tests/`. Public namespace root is `Cloudinary\`. +- **`API_SECRET` stays on the server.** That is the entire reason this SDK exists — never ship it to a browser bundle. Signed uploads and signed URLs are server-only. +- **Version support:** current release line is **3.x**, requires **PHP 8.0–8.4** (CI matrix: 8.0, 8.1, 8.2, 8.3, 8.4). 1.x lives on the `support/1.x` branch; see the version table in `README.md`. + +## Canonical docs (leave the repo for depth) +- PHP SDK guide: https://cloudinary.com/documentation/php_integration +- Upload: https://cloudinary.com/documentation/php_image_and_video_upload — Admin/asset admin: https://cloudinary.com/documentation/php_asset_administration +- Migration to 2.x/3.x: https://cloudinary.com/documentation/php2_migration +- API & transformation reference: https://cloudinary.com/documentation/cloudinary_references +- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers + +## Agent / MCP note +If the capability you need is also exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for code generation. See cloudinary/mcp-servers. + +## Commit / PR conventions +- Ensure tests run locally before opening a PR, and ensure CI (`Tests` workflow, PHP 8.0–8.4 matrix) passes. +- Issues: https://github.com/cloudinary/cloudinary_php/issues. Released under the MIT license. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..72d1388a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,32 @@ +@AGENTS.md + +# CLAUDE.md — cloudinary_php + +## What this repo is + +Official Cloudinary PHP server-side SDK (`cloudinary/cloudinary_php`, 3.x). Handles signed/preset uploads, Admin API calls, asset search, and server-generated transformation URLs and HTML tags — the package that holds your `API_SECRET`. + +## Key constraints / gotchas + +- **API surfaces are methods, not properties.** Call `$cloudinary->uploadApi()->upload(...)`, not `$cloudinary->uploadApi->upload(...)` — the latter throws. +- **`API_SECRET` stays on the server.** Never ship it in a browser bundle. Use `ApiUtils::signParameters()` to produce a signature the browser posts directly to Cloudinary. +- **`CLOUDINARY_URL` must be in the running process env.** The SDK does not parse `.env` files itself — if you use phpdotenv/Laravel/Symfony, load it before `new Cloudinary()`. +- **No `scripts` block in `composer.json`** — invoke dev tools via `vendor/bin/` directly (see Build commands below). +- **Only `simple-phpunit` runs in CI** (`.github/workflows/test.yaml`). `phpcs` and `php-cs-fixer` are local-only dev deps, not wired into any workflow. +- **No `.php-cs-fixer` config at repo root** — it runs with defaults; the committed ruleset is `phpcs.xml` (PHP_CodeSniffer). +- **Transformation builder is bundled.** `cloudinary/transformation-builder-sdk` is a Composer dep — do not add it separately. Classes live in `Cloudinary\Transformation\`. +- **PHP 8.0+ required** for 3.x. CI matrix: 8.0, 8.1, 8.2, 8.3, 8.4. Legacy 1.x is on the `support/1.x` branch. +- **Integration tests hit a real cloud.** Export `CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME` before running the suite locally, or tests will fail. + +## Verified build commands + +```bash +composer install # install deps (CI uses `composer update -n`) +vendor/bin/simple-phpunit # test suite (symfony/phpunit-bridge) — what CI runs +vendor/bin/phpcs # lint against phpcs.xml (local only) +``` + +## Autoload layout + +- `src/` — classmap-autoloaded; public namespace root `Cloudinary\` +- `tests/` — PSR-4 under `Cloudinary\Test\` diff --git a/README.md b/README.md index 85bfb5b2..e1b5cb58 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,129 @@ +# Cloudinary PHP SDK + [![Tests](https://github.com/cloudinary/cloudinary_php/actions/workflows/test.yaml/badge.svg)](https://github.com/cloudinary/cloudinary_php/actions/workflows/test.yaml) -[![license](https://img.shields.io/github/license/cloudinary/cloudinary_php.svg?maxAge=2592000)](https://github.com/cloudinary/cloudinary_php/blob/master/LICENSE) -[![Packagist](https://img.shields.io/packagist/v/cloudinary/cloudinary_php.svg?maxAge=2592000)](https://packagist.org/packages/cloudinary/cloudinary_php) -[![Packagist](https://img.shields.io/packagist/dt/cloudinary/cloudinary_php.svg?maxAge=2592000)](https://packagist.org/packages/cloudinary/cloudinary_php/stats) +[![license](https://img.shields.io/github/license/cloudinary/cloudinary_php.svg)](https://github.com/cloudinary/cloudinary_php/blob/master/LICENSE) +[![Packagist](https://img.shields.io/packagist/v/cloudinary/cloudinary_php.svg)](https://packagist.org/packages/cloudinary/cloudinary_php) -Cloudinary PHP SDK -================== +The `cloudinary/cloudinary_php` package is the server-side Cloudinary SDK for PHP. Use it on a server or in a build step to upload assets, build transformation and delivery URLs, and call the Admin API. It holds the API secret, so it handles the operations that can't run in a browser: signed uploads, signed delivery URLs, and asset administration. The current release (3.x) requires PHP 8.0 or later. -## About +## Installation -The Cloudinary PHP SDK allows you to quickly and easily integrate your application with Cloudinary. -Effortlessly optimize, transform, upload and manage your cloud's assets. +```bash +composer require "cloudinary/cloudinary_php" +``` -#### Note +This pulls in the bundled transformation builder (`cloudinary/transformation-builder-sdk`) automatically. -This Readme provides basic installation and usage information. -For the complete documentation, see the [PHP SDK Guide](https://cloudinary.com/documentation/php_integration). +## Configuration -## Table of Contents +Construct a `Cloudinary` instance with no arguments and it reads credentials from the `CLOUDINARY_URL` environment variable: -- [Key Features](#key-features) -- [Version Support](#Version-Support) -- [Installation](#installation) -- [Usage](#usage) - - [Setup](#Setup) - - [Transform and Optimize Assets](#Transform-and-Optimize-Assets) +```bash +CLOUDINARY_URL=cloudinary://:@ +``` -## Key Features +```php +require 'vendor/autoload.php'; -- [Transform](https://cloudinary.com/documentation/php_video_manipulation#video_transformation_examples) and - [optimize](https://cloudinary.com/documentation/php_image_manipulation#image_optimizations) assets. -- Generate [image](https://cloudinary.com/documentation/php_image_manipulation#deliver_and_transform_images) and - [video](https://cloudinary.com/documentation/php_video_manipulation#php_video_transformation_code_examples) tags. -- [Asset Management](https://cloudinary.com/documentation/php_asset_administration). -- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks). +use Cloudinary\Cloudinary; -## Version Support +$cloudinary = new Cloudinary(); // credentials come from CLOUDINARY_URL in the environment +``` -| SDK Version | PHP 5.4 | PHP 5.5 | PHP 5.6 | PHP 7.x | PHP 8.0 - 8.3 | PHP 8.4 | -|-------------|---------|---------|---------|---------|---------------|---------| -| 3.x | ✘ | ✘ | ✘ | ✘ | ✔ | ✔ | -| 2.x | ✘ | ✘ | ✔ | ✔ | ✔ | ✘ * | -| 1.x | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ | +To set them in code instead, pass a configuration array: -\* Deprecation warnings +```php +require 'vendor/autoload.php'; -## Installation +use Cloudinary\Cloudinary; -```bash -composer require "cloudinary/cloudinary_php" +$cloudinary = new Cloudinary([ + 'cloud' => [ + 'cloud_name' => 'my_cloud_name', + 'api_key' => 'my_key', + 'api_secret' => 'my_secret', + ], +]); ``` -# Usage - -### Migration +Keep the API secret on the server. Don't put it in client-side code or commit it to version control. -See the [Cloudinary PHP SDK Migration guide](https://cloudinary.com/documentation/php2_migration) for more information -on migrating to this version of the PHP SDK. +## Quick examples -The previous (1.x) version of the SDK is located [here](https://github.com/cloudinary/cloudinary_php/tree/support/1.x). +### Upload a file -### Setup +`uploadApi()->upload()` takes a local path, a remote HTTP/HTTPS URL, raw data, or a base64 data URI as its first argument. It returns an array-accessible `ApiResponse` that includes `public_id` and `secure_url`: ```php +require 'vendor/autoload.php'; + use Cloudinary\Cloudinary; -$cloudinary = new Cloudinary(); +$cloudinary = new Cloudinary(); // credentials come from CLOUDINARY_URL in the environment + +$result = $cloudinary->uploadApi()->upload('my_image.jpg', [ + 'public_id' => 'cms/hero', // optional: where the asset lives in your media library +]); + +echo $result['public_id'], ' ', $result['secure_url']; ``` -### Transform and Optimize Assets +### Transform and optimize a delivery URL -- [See full documentation](https://cloudinary.com/documentation/php_image_manipulation). +`image()` returns a builder you can cast to a string — no network call. This resizes to a 100x150 fill crop and lets Cloudinary pick the format and quality for the requesting browser (`f_auto`, `q_auto`): ```php -$cloudinary->image('sample.jpg')->resize(Resize::fill()->width(100)->height(150))->format(Format::auto()); -``` +require 'vendor/autoload.php'; -### Upload +use Cloudinary\Cloudinary; +use Cloudinary\Transformation\Resize; +use Cloudinary\Transformation\Format; +use Cloudinary\Transformation\Quality; -- [See full documentation](https://cloudinary.com/documentation/php_image_and_video_upload). -- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets). +$cloudinary = new Cloudinary(); -```php -$cloudinary->uploadApi->upload('my_image.jpg'); +echo $cloudinary->image('sample.jpg') + ->resize(Resize::fill()->width(100)->height(150)) + ->format(Format::auto()) + ->quality(Quality::auto()); +// https://res.cloudinary.com/demo/image/upload/c_fill,h_150,w_100/f_auto/q_auto/sample.jpg ``` -### Security options +### Retrieve asset details -- [See full documentation](https://cloudinary.com/documentation/solution_overview#security). +`adminApi()->asset()` takes a public ID and returns the asset's metadata, including its format, dimensions, and `secure_url`: -## Contributions +```php +require 'vendor/autoload.php'; -- Ensure tests run locally -- Open a PR and ensure Travis tests pass +use Cloudinary\Cloudinary; -## Get Help +$cloudinary = new Cloudinary(); // credentials come from CLOUDINARY_URL in the environment -If you run into an issue or have a question, you can either: +$asset = $cloudinary->adminApi()->asset('sample'); -- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/cloudinary_php/issues). -- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact) +echo $asset['format'], ' ', $asset['width'], 'x', $asset['height'], ' ', $asset['secure_url']; +``` -## About Cloudinary +## For AI agents -Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently -manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive -and personalized visual-media experiences—irrespective of the viewing device. +`cloudinary/cloudinary_php` is the PHP server-side SDK. Choose it for backend upload, asset administration, search, and signed URL or tag generation, where the API secret stays private. The API surfaces are methods, not properties: call `$cloudinary->uploadApi()->upload(...)`, not `$cloudinary->uploadApi->upload(...)`. For other Cloudinary tasks, choose a different package: -## Additional Resources +| Task | Package | +|---|---| +| Build transformations at a lower level (already bundled here) | [`cloudinary/transformation-builder-sdk`](https://github.com/cloudinary/php-transformation-builder-sdk) | +| Build delivery URLs with a low-level PHP helper | [`php-url-builder`](https://github.com/cloudinary/php-url-builder) | +| Build delivery URLs in the browser | [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) | +| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) | -- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): - Comprehensive references, including syntax and examples for all SDKs. -- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers -- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on - YouTube. -- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and - on-site courses. -- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop - for all code explorers, Postman collections, and feature demos found in the docs. -- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should - develop next. -- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to - other Cloudinary developers. -- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration. -- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and - more. +## Links -## Licence +- [PHP SDK guide](https://cloudinary.com/documentation/php_integration) +- [Upload](https://cloudinary.com/documentation/php_image_and_video_upload) +- [Asset administration (Admin API)](https://cloudinary.com/documentation/php_asset_administration) +- [Search API](https://cloudinary.com/documentation/search_api) +- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references) +- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt) +- [Package on Packagist](https://packagist.org/packages/cloudinary/cloudinary_php) Released under the MIT license.