Starting with version 2.7.x, plugin multimedia adds 4 new content types:

  • Audio document (org.ametys.plugins.multimedia.Content.audio)
  • Video document (org.ametys.plugins.multimedia.Content.video)
  • Photo document (org.ametys.plugins.multimedia.Content.photo)
  • Document (org.ametys.plugins.multimedia.Content.document)

These 4 content types inherit from the same Media abstract type. (org.ametys.plugins.multimedia.Content.abstractMedia)

Each type of content is linked to a new creation right: create an audio document, create a video document, create a photo document and create a document.

plugin offers a default rendering for each of these contents, with a multimedia player based on the mediaelement.js library for audio and video documents.

If you have similar content types in your application

You can choose to exclude these new types in your charter (content-types-default files.xml) to avoid duplication and new graphic integration.

Or you can choose to migrate your existing content types to the new ones (see Data migration below) and use the existing graphic integration for the new types (see Graphic migration below).

Data migration

Run the following script . script migrates the content types and any search services set to the old types.
Please note that script is an example of content types to be migrated whose identifiers would be "plugin.single-media-contents.**". Adapt this script if your identifiers differ.

let logger = Ametys.getLogger("org.ametys.plugins.multimedia.migration.logger", {"filename": "migration-multimedia", "level": "info"});

logger.info("[BEGIN] Migration of single media");

convertContentType("plugin.single-media-contents.video", "org.ametys.plugins.multimedia.Content.video");
convertContentType("plugin.single-media-contents.audio", "org.ametys.plugins.multimedia.Content.audio");
convertContentType("plugin.single-media-contents.document", "org.ametys.plugins.multimedia.Content.document");

convertSearchService("plugin.single-media-contents.item-content", "org.ametys.plugins.multimedia.Content.abstractMedia");
convertSearchService("plugin.single-media-contents.video", "org.ametys.plugins.multimedia.Content.video");
convertSearchService("plugin.single-media-contents.audio", "org.ametys.plugins.multimedia.Content.audio");
convertSearchService("plugin.single-media-contents.document", "org.ametys.plugins.multimedia.Content.document");

logger.info("[END] Migration of single media");

function convertContentType(oldType, newType)
{
    let count = 0;
    let contents = Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = '" + oldType + "']");
    contents.forEach(
        content =>
        {
            Content.migrate(
                content,
                _migrateContent.bind(null, newType), 
                true, 
                false, 
                false, 
                true
            );
            count++;
        }
    );
    logger.info(`${count} contents of type '${oldType}' have been migrated to content type '${newType}'`);
}
  
function convertSearchService(oldType, newType)
{
    _convertSearchServiceInWorkspace(oldType, newType, Repository.session);
    _convertSearchServiceInWorkspace(oldType, newType, Repository.liveSession);
}

function _convertSearchServiceInWorkspace(oldType, newType, currentSession)
{
    let count = 0;
    const paramsNodes = Repository.query("//element(*, ametys:zoneItem)[@ametys-internal:service='org.ametys.web.service.SearchService']/ametys:service_parameters[@ametys:contentTypes='" + oldType + "']", false, currentSession);
    while (paramsNodes.hasNext())
    {
        let paramsNode = paramsNodes.next();
        _migrateService(paramsNode, oldType, newType);
        count++;
    }
    if (count > 0)
    {
        currentSession.save();
    }

    let sessionName = currentSession.getWorkspace().getName();
    logger.info(`[${sessionName}] ${count} search services have been migrated for type '${oldType}'`);
}

function _migrateContent(newType, content)
{
    content.setTypes([newType]);
  
    let node = content.getNode();

    // Migrate attachment (attached to the content)
    if (node.hasNode("ametys:attachment"))
    {
        node.getSession().move(node.getNode('ametys:attachment').getPath(), node.getPath() + "/ametys:file");
    }

    // Migrate attachment (from resource explorer)
  if (node.hasProperty("ametys:attachment"))
    {
        let oldProperty = node.getProperty("ametys:attachment");
        node.setProperty("ametys:file", oldProperty.getValue());
        oldProperty.remove();
    }
}

function _migrateService(paramsNode, oldType, newType, service)
{
    let newCTypes = []; 
    let ctypes = paramsNode.getProperty("ametys:contentTypes").getValues();  
    for (let i=0; i < ctypes.length; i++)  
    {
        let currentCType = ctypes[i].getString();
        newCTypes.push(currentCType == oldType ? newType : currentCType);
    }
    Repository.helper.setProperty(paramsNode, "ametys:contentTypes", newCTypes);
}

Graphics migration

Move the XSL renderings of your old content types to :

  • skins/[SKIN]/stylesheets/content/audio/audio**.xsl
  • skins/[SKIN]/stylesheets/content/video/video**.xsl
  • skins/[SKIN]/stylesheets/content/document/document**.xsl

The field bearing the file (document, audio or video) is named "file". If, in your old template, the field has a different name (e.g. attachment), search for this name in your XSL renderings and replace it with "file".

If you don't have similar content types in your application

You can choose to exclude these new types in your charter (content-types-default files.xml) if this is not desirable or to avoid a new graphic integration.

Or you can choose to propose these new types. If you don't like the default rendering, you'll need to integrate the 4 new types graphically.

Back to top

Multimedia