NAV
php

Overview

In my last two tutorial posts I was talking about a basic way to integrate EDMdesigner into an arbitrary web-based system. This time, you will learn about how to configure the gallery to make it work. It won’t take long, I promise.

Also, it’s possible to disable our built-in gallery so you can use your own. I will write about that soon!

If you want to learn more about our old gallery handling, please read the related parts in our docs.

Gallery hook configuration

We do not store the images of our partners on our server side. If someone uploads an image to our gallery, we immediately upload it to our partner’s server. It means that there has to be an upload hook to be given on our side. There are two ways to configure it. The first option happens on the dashboard, but you can do it programmatically through our API as well.

On the screenshot above you can see the part of our dashboard on which you can configure the hooks and some other things as well. The two most important ones are the upload and the delete hooks. Without them, the gallery cannot be functional. If you want to implement copy functionality, then you should set up a copy hook as well. There are three other things that you can set up here. The first two are messages that will appear if someone reached the limit what you can set up in their groups, so I will talk about those in a separate post. The last option is that you can forbid your users to set urls of the images from anywhere. This way you can force your users to use only those pictures which are hosted by you. It can be useful if you don’t want your email to be spammy. (If there are lot of different domains referenced in your email, that is generally bad for your spam score.)

You might want to configure your gallery programatically. It is useful when you create a system or plugin or whatever that you want to set up on different domains. If you include gallery setup in your install script, that will save you a lot of time. You can do it via our API. You need to generate an admin token on your server side and you can call the gallery config routes.

Upload hook

<?php
//ini_set('display_errors',1);
//ini_set('display_startup_errors',1);
//error_reporting(-1);
require_once dirname(__FILE__) . "/../../includes/config.php";
require_once dirname(__FILE__) . "/utils.php";
header("Content-type: application/json;charset=utf-8");
function printError($msg) {
    print "{\"err\": \"" . $msg . "\"}";
    exit;
}
if (!isset($_FILES["file"])) {
    printError("File input is needed.");
}
//security check
$hash = $_REQUEST["hash"];
$time = $_REQUEST["time"];
if (!checkHookSecurity($hash, $time)) {
    printError("Security error.");
}
if ($_FILES["file"]["size"] > 5000000) {
    printError("File size is too large.");
}
if ($_FILES["file"]["error"] > 0) {
    printError("Upload error, error code: " . $_FILES["file"]["error"]);
}
if (file_exists("upload/" . $_FILES["file"]["name"])) {
    printError("File already exists.");
}
//$contentType = mime_content_type($_FILES["file"]);
//$finfo = new finfo(FILEINFO_MIME_TYPE);
$extension = "";
if(getImageType($_FILES["file"]["tmp_name"])) {
    $extension = "." . getImageType($_FILES["file"]["tmp_name"]);
}
$userId = null;
if($_GET["userId"] === "templater") {
    $userId = "templater";
} else {
    $userId = explode(" - ", $_GET["userId"]);
    $userId = $userId[1];
}
$dirName = dirname(dirname(dirname(__FILE__))) . "/temp/user/" . $userId;
if (!file_exists($dirName)) {
    mkdir($dirName, 0755, true);
}
$savedFileName = "img_" . rand(1,100000000);
move_uploaded_file($_FILES["file"]["tmp_name"], $dirName . "/" . $savedFileName . $extension);
echo "{\"url\": \"" . SENDSTUDIO_APPLICATION_URL . "/admin/temp/user/" . $userId . "/" . $savedFileName . $extension . "\"}";
?>

The example on the right hand side is a real life example from our addon for Interspire Email Marketer (IEM). I think it’s quite self explanatory if you take a look at the code, but let me emphasise two things:

Check the original file from our IEM addon.

Delete hook

<?php
//ini_set('display_errors',1);
//ini_set('display_startup_errors',1);
//error_reporting(-1);
require_once dirname(__FILE__) . "/../../includes/config.php";
require_once dirname(__FILE__) . "/utils.php";
header("Content-type: application/json;charset=utf-8");
function printError($err) {
    print '{"err": ' . $err . '}';
    exit(1);
}
$json = file_get_contents("php://input");
$values = json_decode($json, true);
if($values == null) {
    printError("Null " . $json);
}
if (!isset($values["url"]) || !isset($values["userId"])) {
    printError("Could not delete resource. 0");
}
$hash = $values["hash"];
$time = $values["time"];
if (!checkHookSecurity($hash, $time)) {
    printError("Security error.");
}
$count = 0;
$path = str_replace(SENDSTUDIO_APPLICATION_URL . "/admin", "", $values["url"], $count);
$path = dirname(__FILE__) . "/../../" . $path;
if ($count == 1) {
    if (unlink($path)) {
        echo "{\"success\": true}";
    } else {
        printError("Could not delete resource. 1");
    }
} else {
    http_response_code(404);
}
?>

The rules that you have to follow are almost the same as in the case of the upload hook.

Check the original file from our IEM addon.

Gallery hook security

//utils.php
//check out the checkHookSecurity calls in the previous examples!
<?php
function checkHookSecurity($hash, $time) {
    $magic = getApiKeyAndMagic();
    $magic = $magic["EDMdesignerMagic"];
    return strcmp(md5($time . $magic), $hash) == 0;
}
?>

When we send requests to the hooks that you provided, we send a userId, a hash and a timestamp. The hash is the md5 hash of the concatenation of your magic word and the timestamp we send. This way you can make sure that we sent the request and you can send back 403 or an error message if someone is trying with some nasty things.

Check the original file from our IEM addon.

If you want to learn more about our gallery handling, please read the related parts in our docs.

Tutorials

Tutorial Description
The Basics In this tutorial you will learn about our dashboard, the access token generation and the very basic functionalities, like creating and opening projects.
Admin Functionalities The biggest take away of this tutorial that you will see how to create new users in our system, so you will be able to associate one user for each of users in your system.
Old Built-in Gallery Configuration In this tutorial you will learn about how to set up the gallery properly, how to implement the hooks on your side and you will also learn about the security of these hooks.

Other documentations

Document Description
Basics This documentation covers the very basics of the integration, like:
  • generating an access token
  • making API calls
  • managing and opening projects
  • managing users
  • gallery handling
Advanced This documentation covers more advanced topics. Probably you will only need some of these functionalities.
  • Group handling
  • String placeholders
  • Dynamic data
  • Favorite elements’ management
  • Working with custom data
  • Advanced project handling
  • API key management
postMessage API By reading this documentation you can learn about how to manipulate the editor itself from the client side. Basically this client side API is based on the postMessage function with which you can send messages between frames from different domains.
  • Basic messages and responses (eg. manual save)
  • Hooking on editor events (eg. using your own gallery instead of the built-in one)
  • Dynamic data
  • Setting elements’ properties
Element descriptors A detailed description of our element types used in projects and favorite elements. We generate all of our outputs based on these JSON descriptors.
Old built-in gallery Don’t use it. Use the new postMessage based solution.
Migrating to the CDN based editor In this article you will learn about how to migrate from the good old version of the editor to the superfast and robust CDN based version.

Example implementations

Our PHP examples are very well maintained, but the others are probably not up-to-date. Still, they can be a good starting point, but you might want to take a look at the PHP examples as well in the meanwhile.

If you have another example implementation, please let us know, we will fork it and will put a link here.

php