In your search templates (the XML files under WEB-INF/param/search), replace occurrences of IndexingStringFieldAggregatorSearchUICriterion by IndexingFieldAggregatorSearchUICriterion
Configuration files ($AMETYS_HOME/config)
Connection via email
The FormsCredentialProvider configuration options have been modified:
the security level has been "split" into 2 options: allow cookie and captcha protection
a new parameter allows you to authorize the connection usingemail as the identifier
The file $AMETYS _HOME/config/user-population .xml must be modified manually. Replace :
Oops!
Copy to clipboard failed. Open the code and copy it manually.
The "results sorting" parameter has been brought up from the "Directory LDAP" type populations directly in the data source, in particular so that it can also be used by group directories. In your files $AMETYS_HOME/config/user-populations .xml, delete all occurrences of the following parameter, if present:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
And in your files $AMETYS_HOME/config/datasources- ldap.xml, add the following parameter to each data source:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
<serverSideSorting>true</serverSideSorting>
<serverSideSorting>true</serverSideSorting>
<serverSideSorting>true</serverSideSorting>
The default value is "true". However, if you had unchecked "Sort results", i.e. you had set "runtime.users.ldap.serverSideSorting" to false in your directory population(s) LDAP for performance reasons, then set the value to "false" instead of "true" in the $AMETYS _HOME/config/datasources- ldap.xml to the corresponding data sources.
Workflow files
The WEB-INF/param/workflows.xml file is now optional. Available workflows are automatically read from the WEB-INF/param/workflows folder.
Create a new WEB-INF/param/workflows folder.
Open the file WEB-INF/param/workflows.xml.
For each line, move the file indicated in the"location" attribute to the new folder
Rename this file with the contents of the"name" attribute, to which you add the extension ".xml".
Delete the file WEB-INF/param/workflows.xml.
In general, all you need to do is remove the "workflow-" prefix in front of the file name, but beware of a few pitfalls... for example, "worfklow.xml" becomes "content.xml"; or "workflow-coursepart.xml" becomes "course-part.xml". Pay particular attention to the "name" attribute in the workflows file.xml
Reference table workflow
Dans le fichier workflows/reference-table.xml pour les tables de référence, rajoutez l'action suivante dans les <common-actions> :
Oops!
Copy to clipboard failed. Open the code and copy it manually.
On all workflows used in synchronization (i.e. using action 800), add to synchronization action 800 the post-function org.ametys.cms.workflow.ExtractOutgoingReferencesFunction :
Oops!
Copy to clipboard failed. Open the code and copy it manually.
To simplify the installation of certain plugins functions, there is now an extension point for the 'after registration' and 'after validation' functions.
Places where you used to have the workflow functions of plugin forms or plugin translation-flagging will be replaced by generic functions.
For example, the function: org.ametys.plugins.forms.workflow.FormEditionFunction becomes
Oops!
Copy to clipboard failed. Open the code and copy it manually.
Tokens used to be for infinite or single use. Now they can have a limited number of uses, be renewable and have a context of use.
Migration scripts SQL need to be run to update table formats (depending on your database type).
Oops!
Copy to clipboard failed. Open the code and copy it manually.
#Derby
ALTER TABLE APP.Authentication_Token ADD nb_uses_left int;
ALTER TABLE APP.Authentication_Token ADD auto_renew_duration bigint;
ALTER TABLE APP.Authentication_Token ADD context VARCHAR(200);
UPDATE APP.Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
RENAME COLUMN APP.Authentication_Token.comment TO token_comment;
#HsqlDb
ALTER TABLE Authentication_Token ADD nb_uses_left INTEGER NULL BEFORE context;
ALTER TABLE Authentication_Token ADD auto_renew_duration NUMERIC(13) NULL BEFORE context;
ALTER TABLE Authentication_Token ADD context VARCHAR(200) NULL BEFORE context;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token ALTER COLUMN comment RENAME TO token_comment;
#MySQL
ALTER TABLE Authentication_Token
ADD nb_uses_left INT NULL AFTER last_update_date,
ADD auto_renew_duration BIGINT NULL AFTER nb_uses_left,
ADD context VARCHAR(200) NULL AFTER auto_renew_duration;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token CHANGE comment token_comment LONGBLOB;
#Oracle
ALTER TABLE Authentication_Token ADD
(
nb_uses_left NUMBER,
auto_renew_duration NUMBER(13),
context VARCHAR(200)
);
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
#PostgreSql
ALTER TABLE Authentication_Token
ADD nb_uses_left INTEGER NULL,
ADD auto_renew_duration BIGINT NULL,
ADD context VARCHAR(200) NULL;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
#Derby
ALTER TABLE APP.Authentication_Token ADD nb_uses_left int;
ALTER TABLE APP.Authentication_Token ADD auto_renew_duration bigint;
ALTER TABLE APP.Authentication_Token ADD context VARCHAR(200);
UPDATE APP.Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
RENAME COLUMN APP.Authentication_Token.comment TO token_comment;
#HsqlDb
ALTER TABLE Authentication_Token ADD nb_uses_left INTEGER NULL BEFORE context;
ALTER TABLE Authentication_Token ADD auto_renew_duration NUMERIC(13) NULL BEFORE context;
ALTER TABLE Authentication_Token ADD context VARCHAR(200) NULL BEFORE context;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token ALTER COLUMN comment RENAME TO token_comment;
#MySQL
ALTER TABLE Authentication_Token
ADD nb_uses_left INT NULL AFTER last_update_date,
ADD auto_renew_duration BIGINT NULL AFTER nb_uses_left,
ADD context VARCHAR(200) NULL AFTER auto_renew_duration;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token CHANGE comment token_comment LONGBLOB;
#Oracle
ALTER TABLE Authentication_Token ADD
(
nb_uses_left NUMBER,
auto_renew_duration NUMBER(13),
context VARCHAR(200)
);
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
#PostgreSql
ALTER TABLE Authentication_Token
ADD nb_uses_left INTEGER NULL,
ADD auto_renew_duration BIGINT NULL,
ADD context VARCHAR(200) NULL;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
#Derby
ALTER TABLE APP.Authentication_Token ADD nb_uses_left int;
ALTER TABLE APP.Authentication_Token ADD auto_renew_duration bigint;
ALTER TABLE APP.Authentication_Token ADD context VARCHAR(200);
UPDATE APP.Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
RENAME COLUMN APP.Authentication_Token.comment TO token_comment;
#HsqlDb
ALTER TABLE Authentication_Token ADD nb_uses_left INTEGER NULL BEFORE context;
ALTER TABLE Authentication_Token ADD auto_renew_duration NUMERIC(13) NULL BEFORE context;
ALTER TABLE Authentication_Token ADD context VARCHAR(200) NULL BEFORE context;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token ALTER COLUMN comment RENAME TO token_comment;
#MySQL
ALTER TABLE Authentication_Token
ADD nb_uses_left INT NULL AFTER last_update_date,
ADD auto_renew_duration BIGINT NULL AFTER nb_uses_left,
ADD context VARCHAR(200) NULL AFTER auto_renew_duration;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token CHANGE comment token_comment LONGBLOB;
#Oracle
ALTER TABLE Authentication_Token ADD
(
nb_uses_left NUMBER,
auto_renew_duration NUMBER(13),
context VARCHAR(200)
);
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
#PostgreSql
ALTER TABLE Authentication_Token
ADD nb_uses_left INTEGER NULL,
ADD auto_renew_duration BIGINT NULL,
ADD context VARCHAR(200) NULL;
UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL;
ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
FO user registration
The account creation request no longer asks for first and last names (which will be requested later).
Run the following scripts on your database:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
alter table Users_Temp drop lastname;
alter table Users_Temp drop firstname;
alter table Users_Temp drop lastname;
alter table Users_Temp drop firstname;
alter table Users_Temp drop lastname;
alter table Users_Temp drop firstname;
Modification ofAPI
Ribbon buttons
In your files java and plugin.xml, find and replace the occurrences in the 1st column of the table by their equivalent in the 2nd column:
The management of service parameters has been completely modified. When migrating a project to 4.2, if this project contains specific services or overloads kernel services (unless it only overloads rendering), this migration may require code modifications.
Setting PDF (custom fonts)
Dans certains projets (principalement ODF) les pipelines faisant appel à des PDF ont été modifiés pour intégrer des fonts personnalisées. Les pipelines personnalisés dans ce but ne sont donc plus utiles, il faut supprimer leurs appels et leurs déclarations. Vous pouvez les détecter en cherchant les serializers (sitemap.xmap) org.ametys.core.cocoon.FOPNGSerializer ayant une balise <user-config>. Les pipelines noyaux font désormais correctement l'appel à la configuration personnalisée.
Vérifier qu'il n'existe pas d'autres serializers spécifique au projet en cherchant <map:serialize type="fo2pdf"/>.
However, you may need to modify your project if the file is not positioned correctly. Please refer to the page Putting a custom font in a PDF for further information.
Configuration parameters
Url back office
In the general configuration parameters, CMS 'surl can no longer end with / or /index.html. If this is the case, you need to change this parameter.
Data migration
With the server off, start by deleting the file $AMETYS_HOME/data/repository/repository/custom_nodetypes.xml then restart.
From the management console, run the following scripts:
Label migration
Oops!
Copy to clipboard failed. Open the code and copy it manually.
function copyTagNode(originalNode, newNode)
{
setPropertyFromNode(originalNode, newNode, "ametys-internal:target");
setPropertyFromNode(originalNode, newNode, "ametys-internal:description");
setPropertyFromNode(originalNode, newNode, "ametys-internal:visibility");
setPropertyFromNode(originalNode, newNode, "ametys-internal:title");
}
function setPropertyFromNode(originalNode, newNode, propertyName)
{
if (originalNode.hasProperty(propertyName))
{
newNode.setProperty(propertyName, originalNode.getProperty(propertyName).getString());
}
}
function createNodesFromNode(rootNode, sourceNode)
{
var nbTag = 0;
var childNodes = sourceNode.getNodes();
while (childNodes.hasNext())
{
var childNode = childNodes.next();
var createdNode = rootNode.addNode(childNode.getName(), "ametys:cmstag");
copyTagNode(childNode, createdNode);
nbTag++;
nbTag += createNodesFromNode(createdNode, childNode);
}
return nbTag;
}
var totalNbTag = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:tags)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var tagsNode = nodes.next();
if (!tagsNode.getParent().hasNode("cmstags"))
{
tagsNode.getParent().addNode("cmstags", "ametys:cmstags");
}
var newTagsNode = tagsNode.getParent().getNode("cmstags");
totalNbTag += createNodesFromNode(newTagsNode, tagsNode);
tagsNode.remove();
}
session.save();
print(totalNbTag + " tag(s) have been migrated");
function copyTagNode(originalNode, newNode)
{
setPropertyFromNode(originalNode, newNode, "ametys-internal:target");
setPropertyFromNode(originalNode, newNode, "ametys-internal:description");
setPropertyFromNode(originalNode, newNode, "ametys-internal:visibility");
setPropertyFromNode(originalNode, newNode, "ametys-internal:title");
}
function setPropertyFromNode(originalNode, newNode, propertyName)
{
if (originalNode.hasProperty(propertyName))
{
newNode.setProperty(propertyName, originalNode.getProperty(propertyName).getString());
}
}
function createNodesFromNode(rootNode, sourceNode)
{
var nbTag = 0;
var childNodes = sourceNode.getNodes();
while (childNodes.hasNext())
{
var childNode = childNodes.next();
var createdNode = rootNode.addNode(childNode.getName(), "ametys:cmstag");
copyTagNode(childNode, createdNode);
nbTag++;
nbTag += createNodesFromNode(createdNode, childNode);
}
return nbTag;
}
var totalNbTag = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:tags)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var tagsNode = nodes.next();
if (!tagsNode.getParent().hasNode("cmstags"))
{
tagsNode.getParent().addNode("cmstags", "ametys:cmstags");
}
var newTagsNode = tagsNode.getParent().getNode("cmstags");
totalNbTag += createNodesFromNode(newTagsNode, tagsNode);
tagsNode.remove();
}
session.save();
print(totalNbTag + " tag(s) have been migrated");
function copyTagNode(originalNode, newNode)
{
setPropertyFromNode(originalNode, newNode, "ametys-internal:target");
setPropertyFromNode(originalNode, newNode, "ametys-internal:description");
setPropertyFromNode(originalNode, newNode, "ametys-internal:visibility");
setPropertyFromNode(originalNode, newNode, "ametys-internal:title");
}
function setPropertyFromNode(originalNode, newNode, propertyName)
{
if (originalNode.hasProperty(propertyName))
{
newNode.setProperty(propertyName, originalNode.getProperty(propertyName).getString());
}
}
function createNodesFromNode(rootNode, sourceNode)
{
var nbTag = 0;
var childNodes = sourceNode.getNodes();
while (childNodes.hasNext())
{
var childNode = childNodes.next();
var createdNode = rootNode.addNode(childNode.getName(), "ametys:cmstag");
copyTagNode(childNode, createdNode);
nbTag++;
nbTag += createNodesFromNode(createdNode, childNode);
}
return nbTag;
}
var totalNbTag = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:tags)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var tagsNode = nodes.next();
if (!tagsNode.getParent().hasNode("cmstags"))
{
tagsNode.getParent().addNode("cmstags", "ametys:cmstags");
}
var newTagsNode = tagsNode.getParent().getNode("cmstags");
totalNbTag += createNodesFromNode(newTagsNode, tagsNode);
tagsNode.remove();
}
session.save();
print(totalNbTag + " tag(s) have been migrated");
User registration service
The service parameters have been modified:
The choice of UGC display mode becomes a drop-down list: never / link to a page / insert content
The choice of behavior at the end of account creation: standard message / standard message and link to a page / content insertion
Run the following script JCR to modify existing services:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
var count = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.web.service.UserSignup']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
var page = node.getParent().getParent().getParent().getParent();
var sitemap = page.getProperty("ametys:sitemap").getString();
print("Found a signup service for language " + sitemap + " at path " + page.getPath());
count++;
var params = node.getNode("ametys:service_parameters");
if (params.hasProperty("ametys:terms-of-service-page"))
{
var pageId = params.getProperty("ametys:terms-of-service-page").getString();
if (pageId != '')
{
params.setProperty("ametys:terms-of-service-mode", "PAGE");
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:tags = 'USER_PREFS_MAIN' and @ametys:sitemap= " + sitemap + "]", javax.jcr.query.Query.XPATH);
var pages = query.execute().getNodes();
if (pages.hasNext())
{
var successPage = pages.next();
params.setProperty("ametys:success-page", "page://" + successPage.getUUID());
params.setProperty("ametys:success-mode", "PAGE");
}
// TO UNCOMMENT ONLY IF YOU USE USER-DIRECTORY PLUGIN
// params.setProperty("ametys:xslt", pages/services/user-signup/signup.xsl);
}
session.save();
print(count + " signup services have been migrated");
var count = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.web.service.UserSignup']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
var page = node.getParent().getParent().getParent().getParent();
var sitemap = page.getProperty("ametys:sitemap").getString();
print("Found a signup service for language " + sitemap + " at path " + page.getPath());
count++;
var params = node.getNode("ametys:service_parameters");
if (params.hasProperty("ametys:terms-of-service-page"))
{
var pageId = params.getProperty("ametys:terms-of-service-page").getString();
if (pageId != '')
{
params.setProperty("ametys:terms-of-service-mode", "PAGE");
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:tags = 'USER_PREFS_MAIN' and @ametys:sitemap= " + sitemap + "]", javax.jcr.query.Query.XPATH);
var pages = query.execute().getNodes();
if (pages.hasNext())
{
var successPage = pages.next();
params.setProperty("ametys:success-page", "page://" + successPage.getUUID());
params.setProperty("ametys:success-mode", "PAGE");
}
// TO UNCOMMENT ONLY IF YOU USE USER-DIRECTORY PLUGIN
// params.setProperty("ametys:xslt", pages/services/user-signup/signup.xsl);
}
session.save();
print(count + " signup services have been migrated");
var count = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.web.service.UserSignup']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
var page = node.getParent().getParent().getParent().getParent();
var sitemap = page.getProperty("ametys:sitemap").getString();
print("Found a signup service for language " + sitemap + " at path " + page.getPath());
count++;
var params = node.getNode("ametys:service_parameters");
if (params.hasProperty("ametys:terms-of-service-page"))
{
var pageId = params.getProperty("ametys:terms-of-service-page").getString();
if (pageId != '')
{
params.setProperty("ametys:terms-of-service-mode", "PAGE");
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:tags = 'USER_PREFS_MAIN' and @ametys:sitemap= " + sitemap + "]", javax.jcr.query.Query.XPATH);
var pages = query.execute().getNodes();
if (pages.hasNext())
{
var successPage = pages.next();
params.setProperty("ametys:success-page", "page://" + successPage.getUUID());
params.setProperty("ametys:success-mode", "PAGE");
}
// TO UNCOMMENT ONLY IF YOU USE USER-DIRECTORY PLUGIN
// params.setProperty("ametys:xslt", pages/services/user-signup/signup.xsl);
}
session.save();
print(count + " signup services have been migrated");
Change of storage format for multilingual data
Oops!
Copy to clipboard failed. Open the code and copy it manually.
var fieldsByContent = new java.util.HashMap();
fillFieldsToMigrateMap();
var migratedFields = 0;
var migratedContents = 0;
// Migrate the multilingual nodes content by content
fieldsByContent.forEach(
function(contentId)
{
var content = ametysResolver.resolveById("content://" + contentId);
migrateContent(content,
[renameMultilingualString],
true /* old versions have to be marked incompatible */,
null /* tag new versions */,
false /* not verbose - DO NOT ACTIVATE IN THIS CASE !! */
);
}
);
print(migratedFields + " multilingual fields have been migrated in " + migratedContents + " contents.");
// Get all the multilingual nodes
function fillFieldsToMigrateMap()
{
var fieldsToMigrate = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:multilingualString)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
// Get the path of the multilingual metadata to migrate
var metadataPath = "";
var contentNode = node;
while (!contentNode.getPrimaryNodeType().isNodeType("ametys:content"))
{
metadataPath += node.getName() + "/";
contentNode = node.getParent();
}
metadataPath = metadataPath.slice(0, -1);
// Store the metadataPath to migrate by content ID
var contentId = contentNode.getIdentifier();
var fields = fieldsByContent.getOrDefault(contentId, new java.util.HashSet());
fields.add(metadataPath);
fieldsByContent.put(contentId, fields);
fieldsToMigrate++;
}
print(fieldsToMigrate + " multilingual fields to migrate potentially in " + fieldsByContent.keySet().size() + " contents.");
}
// Migrate the multilingual strings of the content and increment the global counter
function renameMultilingualString(content)
{
var migratedContent = false;
var contentId = content.getNode().getIdentifier();
// Get all metadata to migrate for the current content
var fields = fieldsByContent.get(contentId);
fields.forEach(
function(fieldName)
{
var migratedField = false;
var fieldNode = content.getNode().getNode(fieldName);
var properties = fieldNode.getProperties();
while (properties.hasNext())
{
var property = properties.nextProperty();
// If the current property name doesn't starts with "ametys:" ...
var propertyName = property.getName();
if (propertyName.indexOf(":") == -1)
{
// ... move it to "ametys:[propertyName]"
fieldNode.setProperty("ametys:" + propertyName, property.getValue());
property.remove();
migratedField = true;
}
}
if (migratedField)
{
migratedFields++;
migratedContent = true;
}
}
);
if (migratedContent)
{
migratedContents++;
}
}
var fieldsByContent = new java.util.HashMap();
fillFieldsToMigrateMap();
var migratedFields = 0;
var migratedContents = 0;
// Migrate the multilingual nodes content by content
fieldsByContent.forEach(
function(contentId)
{
var content = ametysResolver.resolveById("content://" + contentId);
migrateContent(content,
[renameMultilingualString],
true /* old versions have to be marked incompatible */,
null /* tag new versions */,
false /* not verbose - DO NOT ACTIVATE IN THIS CASE !! */
);
}
);
print(migratedFields + " multilingual fields have been migrated in " + migratedContents + " contents.");
// Get all the multilingual nodes
function fillFieldsToMigrateMap()
{
var fieldsToMigrate = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:multilingualString)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
// Get the path of the multilingual metadata to migrate
var metadataPath = "";
var contentNode = node;
while (!contentNode.getPrimaryNodeType().isNodeType("ametys:content"))
{
metadataPath += node.getName() + "/";
contentNode = node.getParent();
}
metadataPath = metadataPath.slice(0, -1);
// Store the metadataPath to migrate by content ID
var contentId = contentNode.getIdentifier();
var fields = fieldsByContent.getOrDefault(contentId, new java.util.HashSet());
fields.add(metadataPath);
fieldsByContent.put(contentId, fields);
fieldsToMigrate++;
}
print(fieldsToMigrate + " multilingual fields to migrate potentially in " + fieldsByContent.keySet().size() + " contents.");
}
// Migrate the multilingual strings of the content and increment the global counter
function renameMultilingualString(content)
{
var migratedContent = false;
var contentId = content.getNode().getIdentifier();
// Get all metadata to migrate for the current content
var fields = fieldsByContent.get(contentId);
fields.forEach(
function(fieldName)
{
var migratedField = false;
var fieldNode = content.getNode().getNode(fieldName);
var properties = fieldNode.getProperties();
while (properties.hasNext())
{
var property = properties.nextProperty();
// If the current property name doesn't starts with "ametys:" ...
var propertyName = property.getName();
if (propertyName.indexOf(":") == -1)
{
// ... move it to "ametys:[propertyName]"
fieldNode.setProperty("ametys:" + propertyName, property.getValue());
property.remove();
migratedField = true;
}
}
if (migratedField)
{
migratedFields++;
migratedContent = true;
}
}
);
if (migratedContent)
{
migratedContents++;
}
}
var fieldsByContent = new java.util.HashMap();
fillFieldsToMigrateMap();
var migratedFields = 0;
var migratedContents = 0;
// Migrate the multilingual nodes content by content
fieldsByContent.forEach(
function(contentId)
{
var content = ametysResolver.resolveById("content://" + contentId);
migrateContent(content,
[renameMultilingualString],
true /* old versions have to be marked incompatible */,
null /* tag new versions */,
false /* not verbose - DO NOT ACTIVATE IN THIS CASE !! */
);
}
);
print(migratedFields + " multilingual fields have been migrated in " + migratedContents + " contents.");
// Get all the multilingual nodes
function fillFieldsToMigrateMap()
{
var fieldsToMigrate = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:multilingualString)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
// Get the path of the multilingual metadata to migrate
var metadataPath = "";
var contentNode = node;
while (!contentNode.getPrimaryNodeType().isNodeType("ametys:content"))
{
metadataPath += node.getName() + "/";
contentNode = node.getParent();
}
metadataPath = metadataPath.slice(0, -1);
// Store the metadataPath to migrate by content ID
var contentId = contentNode.getIdentifier();
var fields = fieldsByContent.getOrDefault(contentId, new java.util.HashSet());
fields.add(metadataPath);
fieldsByContent.put(contentId, fields);
fieldsToMigrate++;
}
print(fieldsToMigrate + " multilingual fields to migrate potentially in " + fieldsByContent.keySet().size() + " contents.");
}
// Migrate the multilingual strings of the content and increment the global counter
function renameMultilingualString(content)
{
var migratedContent = false;
var contentId = content.getNode().getIdentifier();
// Get all metadata to migrate for the current content
var fields = fieldsByContent.get(contentId);
fields.forEach(
function(fieldName)
{
var migratedField = false;
var fieldNode = content.getNode().getNode(fieldName);
var properties = fieldNode.getProperties();
while (properties.hasNext())
{
var property = properties.nextProperty();
// If the current property name doesn't starts with "ametys:" ...
var propertyName = property.getName();
if (propertyName.indexOf(":") == -1)
{
// ... move it to "ametys:[propertyName]"
fieldNode.setProperty("ametys:" + propertyName, property.getValue());
property.remove();
migratedField = true;
}
}
if (migratedField)
{
migratedFields++;
migratedContent = true;
}
}
);
if (migratedContent)
{
migratedContents++;
}
}
Former research department
The main search engine service has been renamed "Page Search".
The associatedurl service has been changed from "service/search.html" to "service/search-pages.html". Check your XSL to make sure you didn't have this url .
The service class has changed. If the search engine has been duplicated, search your project's xml files and replace "org.ametys.web.frontoffice.SearchService" with "org.ametys.web.frontoffice.SearchPagesService".
The location of the service's XSL has changed(see graphic migration), so you need to run the following script (and rebuild live if there are any changes):
Oops!
Copy to clipboard failed. Open the code and copy it manually.
var count = 0;
var done = 0;
jcrXPathQuery("//element(*, ametys:zoneItem)[@ametys-internal:service='org.ametys.web.service.FrontSearchService']").forEach(function(zi) {
print("Found " + zi.getPath());
var parameters = zi.getServiceParameters();
var xsltParam = parameters.getValue("xslt");
print(" " + xsltParam);
count++;
var toReplace = "pages/services/search/";
if (xsltParam.startsWith(toReplace))
{
var newValue = "pages/services/search-pages/" + xsltParam.substring(toReplace.length);
print(" => " + newValue)
parameters.setValue("xslt", newValue);
zi.saveChanges();
done++;
}
else
{
print(" => ok")
}
})
print("...");
print(done + " services modifiés sur " + count)
if (done > 0)
{
print("PENSEZ A RECONSTRUIRE LE LIVE")
}
var count = 0;
var done = 0;
jcrXPathQuery("//element(*, ametys:zoneItem)[@ametys-internal:service='org.ametys.web.service.FrontSearchService']").forEach(function(zi) {
print("Found " + zi.getPath());
var parameters = zi.getServiceParameters();
var xsltParam = parameters.getValue("xslt");
print(" " + xsltParam);
count++;
var toReplace = "pages/services/search/";
if (xsltParam.startsWith(toReplace))
{
var newValue = "pages/services/search-pages/" + xsltParam.substring(toReplace.length);
print(" => " + newValue)
parameters.setValue("xslt", newValue);
zi.saveChanges();
done++;
}
else
{
print(" => ok")
}
})
print("...");
print(done + " services modifiés sur " + count)
if (done > 0)
{
print("PENSEZ A RECONSTRUIRE LE LIVE")
}
var count = 0;
var done = 0;
jcrXPathQuery("//element(*, ametys:zoneItem)[@ametys-internal:service='org.ametys.web.service.FrontSearchService']").forEach(function(zi) {
print("Found " + zi.getPath());
var parameters = zi.getServiceParameters();
var xsltParam = parameters.getValue("xslt");
print(" " + xsltParam);
count++;
var toReplace = "pages/services/search/";
if (xsltParam.startsWith(toReplace))
{
var newValue = "pages/services/search-pages/" + xsltParam.substring(toReplace.length);
print(" => " + newValue)
parameters.setValue("xslt", newValue);
zi.saveChanges();
done++;
}
else
{
print(" => ok")
}
})
print("...");
print(done + " services modifiés sur " + count)
if (done > 0)
{
print("PENSEZ A RECONSTRUIRE LE LIVE")
}
Do not keep the old indexed data (delete all the contents of "solr home" (except the logs folder, if any), by default it is located in solr/server/solr, then copy and paste the default data from the delivery of ametys-solr-config-*.zip).
After restarting the server Solr then Ametys, run a full indexing operation.