ReportingCloud

PHP

Topic

PHP applications reach ReportingCloud through the Composer package textcontrol/textcontrol-reportingcloud, the only SDK with a release after 2019. Its ReportingCloud class wraps the endpoints of the Web API in methods that take PHP arrays and file names and return binary strings or arrays. What follows covers the package and its PHP version, the options of the class, a merge example, the methods, the error handling, the demo scripts and the module for Laminas applications.

PHP in Getting Started builds a first project with the package step by step.

Package and Requirements

PackageVersionReleasedPHPDependencies
textcontrol/textcontrol-reportingcloud4.0.5June 27, 20248.3 or a later 8.x version, with the extensions dom, json and libxmlguzzlehttp/guzzle 7, ctw/ctw-http 4, psr/container 1 or 2

The PHP version is the requirement in the package's composer.json, which Composer enforces; the README of version 4.0.5 still names PHP 8.1 and 8.2. Requirements lists the releases for older PHP versions. Install the package with Composer in the folder of your project, and load Composer's autoloader in your scripts:

composer require textcontrol/textcontrol-reportingcloud:^4.0

Installing an SDK has the details and a first call that checks the installation.

Older Packages and Namespaces

Until the current package's release 4.0.0 of September 2023, the SDK was published as textcontrol/txtextcontrol-reportingcloud, whose last releases on Packagist, 4.0.0 to 4.0.6, are dated July 7, 2022. Packagist marks that package as abandoned in favor of textcontrol/textcontrol-reportingcloud, and its repository, TextControl/txtextcontrol-reportingcloud-php, is archived. The old package has its classes in the namespace TxTextControl\ReportingCloud, the current one in TextControl\ReportingCloud: samples that import TxTextControl\ReportingCloud\ReportingCloud were written for the old package and need the new namespace.

Create an Instance

The constructor of ReportingCloud takes an array of options. Each option also has a setter method:

OptionSetterDefaultDescription
api_keysetApiKeynoneThe API key, sent as ReportingCloud-APIKey with every request
username, passwordsetUsername, setPasswordnoneCredentials for Basic authentication, used when no API key is set; deprecated since version 3.0
base_urisetBaseUrihttps://api.reporting.cloudThe base URL of the Web API
versionsetVersionv1The version part of every endpoint path
timeoutsetTimeout120The timeout of a request in seconds
testsetTestfalseAdds test=true to every request: the documents carry a "TEST MODE" watermark, and the runs don't count against the document quota, except merge and find and replace on a trial account
debugsetDebugfalseTurns on the debug output of the HTTP client

The class creates its HTTP client with the credentials, base_uri, timeout and debug at the first request and keeps it: set these options before the first request, because a setter called later has no effect. setTest and setVersion apply to every request. Without an API key, user name and password, the first request throws an InvalidArgumentException. When base_uri isn't set, the class reads the base URL from the PHP constant or environment variable REPORTING_CLOUD_BASE_URI and accepts it only if its host ends with api.reporting.cloud. A Free account can't use the test parameter; see Test Mode. API Keys shows how to create a key, and Authentication explains both kinds of credentials.

Merge a Template

The following script merges sample_invoice.tx, the demo template of every trial account, with one invoice record and saves invoice.pdf. It reads the API key from the environment variable REPORTINGCLOUD_API_KEY. Save it as merge.php in the folder where you ran composer require:

<?php

declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

use TextControl\ReportingCloud\Exception\RuntimeException;
use TextControl\ReportingCloud\ReportingCloud;

// Send the API key with every request
$reportingCloud = new ReportingCloud([
    'api_key' => (string) getenv('REPORTINGCLOUD_API_KEY'),
]);

// One record with the fields and the item block of sample_invoice.tx
$mergeData = [
    [
        'invoice_no'         => '778723',
        'billto_name'        => 'Joey Montana',
        'billto_companyname' => 'Montana, LLC',
        'item'               => [
            ['qty' => '1', 'item_no' => '1', 'item_description' => 'Item description 1', 'item_total' => '2130.40'],
            ['qty' => '1', 'item_no' => '2', 'item_description' => 'Item description 2', 'item_total' => '5543'],
        ],
        'total'              => '8210.538',
    ],
];

try {
    // Merge the stored template and return the documents as binary strings
    $documents = $reportingCloud->mergeDocument(
        $mergeData,
        ReportingCloud::FILE_FORMAT_PDF,
        templateName: 'sample_invoice.tx',
        mergeSettings: ['document_title' => 'Invoice 778723'],
    );

    file_put_contents('invoice.pdf', $documents[0]);
    echo 'invoice.pdf has been written.', PHP_EOL;
} catch (RuntimeException $exception) {
    // The code is the HTTP status code of the failed request
    echo $exception->getCode(), ': ', $exception->getMessage(), PHP_EOL;
}

Run it with php merge.php. The code works as follows:

  • $mergeData is a list of records. Each record is an associative array whose keys are the merge field names, and a nested list such as item fills a merge block. Merge Data describes the structure.
  • mergeDocument sends the request to POST /v1/document/merge. Its parameters are $mergeData, $returnFormat, $templateName, $templateFilename, the path of a local template to send instead of a stored one, $append and $mergeSettings. The named arguments skip the parameters the example doesn't need.
  • The method decodes the Base64 strings of the response and returns an array of binary strings, one for each created document. $append is false by default, and the method sends the parameter only when it is true. The service appends the records of a request without it, so the array holds one document whatever $append is; to get one per record, call mergeDocument once per record.
  • The return format is one of the class constants FILE_FORMAT_PDF, FILE_FORMAT_PDFA, FILE_FORMAT_DOCX, FILE_FORMAT_DOC, FILE_FORMAT_RTF, FILE_FORMAT_HTML, FILE_FORMAT_TX and FILE_FORMAT_TXT.

Merge Settings

$mergeSettings, and $documentSettings of appendDocument, take snake-case keys that the SDK renames for the Web API: author, creation_date, creator_application, culture, document_subject, document_title, last_modification_date, merge_html, remove_empty_blocks, remove_empty_fields, remove_empty_images, remove_trailing_whitespace and user_password. $documentSettings uses only the seven keys that set document properties, author, the two dates, creator_application, document_subject, document_title and user_password, and ignores the others. The two dates are Unix timestamps, such as the result of time(). culture must be one of the culture names in the SDK's data/cultures.php, such as de-DE. The SDK has no key for removeEmptyLines. Merge Settings explains what each setting does.

ReportingCloud Methods

Most methods that send a document read it from a local file, and the methods that return documents or images return binary strings. Arrays in the results have snake-case keys, such as template_name.

MethodWeb API endpointReturns
mergeDocumentPOST /v1/document/mergeAn array of documents
appendDocumentPOST /v1/document/appendOne document combined from files, each given as filename and divider (a DOCUMENT_DIVIDER_* constant)
convertDocumentPOST /v1/document/convertThe document in the return format
findAndReplaceDocumentPOST /v1/document/findandreplaceThe document with the text replaced
getDocumentThumbnailsPOST /v1/document/thumbnailsAn array of images, one per page
uploadTemplate, uploadTemplateFromBase64POST /v1/templates/uploadtrue; the first takes a file name and stores the file under its name
getTemplateListGET /v1/templates/listThe templates with template_name, modified and size
getTemplateCountGET /v1/templates/countAn integer
templateExistsGET /v1/templates/existsA Boolean
getTemplateInfoGET /v1/templates/infoThe merge fields and merge blocks of the template
getTemplatePageCountGET /v1/templates/pagecountAn integer
getTemplateThumbnailsGET /v1/templates/thumbnailsAn array of images, one per page
downloadTemplateGET /v1/templates/downloadThe template
deleteTemplateDELETE /v1/templates/deletetrue
getAccountSettingsGET /v1/account/settingsThe quotas, their usage and the serial number
getApiKeys, createApiKey, deleteApiKeyGET /v1/account/apikeys, PUT and DELETE /v1/account/apikeyThe keys, the new key or true
getFontListGET /v1/fonts/listThe font names
proofingCheckGET /v1/proofing/checkThe misspelled words
getAvailableDictionariesGET /v1/proofing/availabledictionariesThe dictionary names
getProofingSuggestionsGET /v1/proofing/suggestionsSuggestions for a word, 10 at most by default
getTrackedChangesPOST /v1/processing/review/trackedchangesThe tracked changes of a document
removeTrackedChangePOST /v1/processing/review/removetrackedchangeThe document with the change accepted or rejected

The SDK has no method for GET /v1/document/share. The ReportingCloud PHP SDK API documentation lists the parameters of every method.

Errors

The exceptions of the SDK implement TextControl\ReportingCloud\Exception\ExceptionInterface:

  • InvalidArgumentException is thrown before a request is sent, when an argument fails a check: a template name with a path or an unsupported file extension, a return format or culture the SDK doesn't know, a zoom factor out of range, a file that doesn't exist or missing credentials.
  • RuntimeException is thrown when the request fails. Its code is the HTTP status code, or 0 when the server can't be reached, and its message names the request and contains the response body, cut off after 120 characters.

Errors and Status Codes lists the status codes and their causes, and its section Handle Errors in the SDKs tells the causes apart in code.

Demo Scripts

The package contains a demo folder with a script for each task, such as merge-document-basic.php, merge-document-image.php, append-document-basic.php, convert-document-docx-to-pdf.php, template-management.php, manage-api-keys.php and tracked-changes.php. The scripts read the API key from the PHP constant or environment variable REPORTING_CLOUD_API_KEY, use the sample files of the package's resource folder and write their results to its output folder. Six of them, merge-document-basic.php among them, set the test option, so their documents carry the "TEST MODE" watermark, and they fail with a Free account, which can't use it. manage-api-keys.php deletes every API key of the account except the one it runs with. instantiation.php shows how to create and configure an instance with an API key, through the constructor options or the setter methods.

Laminas Module

For Laminas MVC applications, the package textcontrol/textcontrol-laminas-reportingcloud, version 5.0.6 of June 27, 2024, registers the SDK in the service manager. It needs PHP 8.3 or 8.4 and version 3.3 or a later version 3 of laminas/laminas-mvc: the module allows any PHP 8 version from 8.3, but 3.8.0, the newest release of laminas/laminas-mvc, supports PHP 8.4 at most, so Composer can't install the module on PHP 8.5. It requires the PHP SDK as ^2.0, so Composer installs release 2.0.0 of textcontrol/textcontrol-reportingcloud, which Packagist lists with the same source commit as 4.0.4.

  1. Install the module with Composer:

    composer require textcontrol/textcontrol-laminas-reportingcloud
    
  2. Copy vendor/textcontrol/textcontrol-laminas-reportingcloud/config/reportingcloud.local.php.dist to config/autoload/reportingcloud.local.php and enter your API key:

    <?php
    
    return [
        'reportingcloud' => [
            'credentials' => [
                'api_key' => '<API key>',
            ],
        ],
    ];
    
  3. Add 'TextControl\Laminas\ReportingCloud' to the module list in config/modules.config.php.

The module registers the service ReportingCloud in the service manager, which your factories get with $container->get('ReportingCloud'), and a controller plugin and a view helper, both called with $this->reportingCloud(). Each returns a TextControl\ReportingCloud\ReportingCloud instance.

API Documentation and Source