Upload Hooks

Today a media object not only consist of the picture or the file. In digital pictures additional meta data like the camera producer, the camera model or the photographer are saved in the exchangeable image file format (Exif). In FirstSpirit you can save these information automatically when you upload a file. Wouldn’t it be nice to manage project specific meta data also automatically when you upload a media? Especially when you have to upload more than one media and for each media you have to add a lot of meta data! Or you have to do some further jobs like saving the media in the database for a media gallery or want to check if the media is placed at the right spot (folder). For this, an automatism would be an great as well! All this is possible with FirstSpirit!

Exif Data – How does it work

FirstSpirit gives you the potential to save Exif-Data automatically in the metadata tab of a media when you upload a media file. All you have to do is to create an input component for each exif-data you want to save. The important specification is the identifier (name parameter) of the input component. For these input components, the identifier used must be the corresponding tags as hexadecimal value, which are defined by the Exif standard (see http://www.exif.org/Exif2-2.PDF). Each hexadecimal value must also be assigned the prefix FS_ for processing by FirstSpirit. E.g. for the camera manufactor the hexadecimal value is 0x010F, so the identifier for the input component must be FS_0x010F.

<CMS_MODULE>
<CMS_INPUT_TEXT name="FS_0x010F" hFill="yes" singleLine="yes" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="Camera manufacturer (FS_0x010F)"/>
<LANGINFO lang="DE" label="Kamerahersteller (FS_0x010F)"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
</CMS_MODULE>

Upload Hooks - The API

The Implementation behind the Exif data based on an interface which is also available in the FirstSpirit Access API, so you can use this interface for your own implementation of media meta data.

You have four different methods for uploading your project spefic meta data of a media file. The two “preProcess” methods are called before the media file is transmitted to the FirstSpirit-Repository, the two “postProcess” methods are called afterwards. For each of these groups of methods you have one method for pictures (parameter “Picture picture”) and one for other files (parameter “File file”) like pdf oder word documents.The last method you find in the interface you should use when the upload of a media is aborted.

Example 1 – Expire Date

In the first example you want to upload a media which should be used on your website only for two weeks after you have uploaded it. So the goal is to fill two dates in the meta data automatically. The first one is the current date (begin of the license) and the second date should be two weeks in the future because every picture should only licensed for two weeks until the date of the update.

Take the “postProcess” method for media for this example. You have your media object already in the parameter list. Just get the formdata object for the meta data of this media and set the date information like you do in the “normal” way to fill a formdata:

FormData metaForm = media.getMetaFormData();
FormField<?> dateNowFF = metaForm.get(lang, "md_date_now");
Date dateNow = new Date();
dateNowFF.set(dateNow);
FormField<?> dateExpireFF = metaForm.get(lang, "md_date_expire");
Calendar cal = new GregorianCalendar();
cal.setTime(dateNow);
cal.add(Calendar.DAY_OF_MONTH, 14);
Date dateExpire = cal.getTime();
dateExpireFF.set(dateExpire);

Attention: When you do changes to a formdata object, you have to check that all rules are fullfilled to get no error when you want to save the object!

Example 2 – Check for the right folder

Sometimes media should only be uploaded in a special folder. So in the second example it should be checked, if the media you want to upload are placed in a correct folder. To do this, you should use the preProcess method (it is also possible to use postProcess). There you can check if the reference name of the folder you want to import the media is the correct one:

MediaFolder folder = (MediaFolder) media.getParent();
if(!folder.getUid().equals(CORRECT_UID)) {
OperationAgent operationAgent = baseContext.requireSpecialist(OperationAgent.TYPE);
RequestOperation requestOperation = operationAgent.getOperation(RequestOperation.TYPE);
requestOperation.setKind(RequestOperation.Kind.INFO);
requestOperation.perform("not the correct folder");
media.delete();
}

Here we just delete the media directly, but it is your choise what you want to do with the media you want to upload.

Example 3 – Media Gallery in a database

In the last example we want to reference the media automatically in a database for a media gallery. Therefore you just need to access the gallery media table in the data sources and create a new entry:

Language lang = baseContext.requireSpecialist(LanguageAgent.TYPE).getMasterLanguage();
Content2 cs = (Content2) baseContext.requireSpecialist(StoreElementAgent.TYPE).loadStoreElement("gallerymedia", IDProvider.UidType.CONTENTSTORE, false);
Session session = cs.getSchema().getSession();
Entity entity = session.createEntity(cs.getEntityType().getName());

For the new entry/entity you fill the input components, like the reference to new uploaded media and e.g. a name or a description of the media:

cs.lock(entity);
Dataset dataset = cs.getDataset(entity);
FormData formData = dataset.getFormData();
FormField<TargetReference> mediaFormField = (FormField<TargetReference>) formData.get(lang, "cs_picture");
TargetReference tr = TargetReference.TargetReferences.newInstance(lang, media, null);
mediaFormField.set(tr);
FormField<String> nameFormField = (FormField<String>) formData.get(lang, "cs_name");
nameFormField.set(media.getFilename());
dataset.setFormData(formData);
dataset.save();
cs.unlock(entity);

Of course you can combine the different examples in one hook. So, if you have a media gallery with media from a special folder and the media should only be visible for a set of dates, the only thing an editor has to do, is to upload the media to the (correct) folder!

Make it project specific!

When you build your module for your UploadHook, you normally just have to add a library which contains your implementation. But this means that the Hook will be available in every project on the server! But sometimes you don’t want to use it in every project or even worse you get errors or can’t upload your media files (e.g. example 3: if the database does not exist in the project)! So what you can do here is a “trick” to configure in which project you want to use the UploadHook. You have to do two things:

1. Create a project app: Add a class to your implementation that implements the “ProjectApp” interface from the FirstSpirit API:

public class UploadHookProjectApp implements ProjectApp

It is not necessary to implement the methods!

The next step is to configure a project app component in your module.xml:
<project-app><name>UploadHookProjectApp</name><class>com.espirit.ps.uploadhook.UploadHookProjectApp</class></project-app>

If you did this you can configure in the project configuration in the server manager where to use the Hook. Therefore you have to add the project app in the “Project components” of the project configuration.

2. In your implementation of the UploadHook you can than check if the project app was added to your project and only if this is the case you will perform your implementation:

Create a method, where you check the project components:

 public boolean isVisible() {
final long projectId = _context.requireSpecialist(ProjectAgent.TYPE).getId();
final Collection<Project> projects =_context.requestSpecialist(ModuleAdminAgent.TYPE).getProjectAppUsages(MODULE_NAME,PROJECT_APP_NAME);
for (final Project project : projects) {
if (project.getId() == projectId) {
return true;
}
}
return false;
}

Call this method before you execute your code in each method (here we use example 1 code):

if(isVisible()) {
FormData metaForm = media.getMetaFormData();
FormField<?> dateNowFF = metaForm.get(lang, "md_date_now");
Date dateNow = new Date();
dateNowFF.set(dateNow);
...
}

Because this is not an UploadHook-specific implementation, you can use this “trick” as well for other components as well (e.g. Reports)!