« Tilbake

Programando contenidos en Liferay 6

¿Qué es un contenido?

Un contenido será cualquier entidad que podemos etiquetar o categorizar. Liferay los identifica con el término asset y proporciona un framework para su gestión. Los tipos de contenido que Liferay maneja por defecto son:

  • Contenidos web (Web Content).
  • Imágenes de la galería de Imágenes (Image Gallery Image).
  • Entradas de blog (Blog Entry).
  • Documentos de la biblioteca de documentos (Document Library Document).
  • Marcador (Bookmark).
  • Mensaje en un foro (Message Board message).
  • Página en una Wiki (Wiki page).
  • Evento de calendario (Calendar Event).

La API para manejar Assets

Para trabajar con asset se debe manejar dos conceptos, su modelo y su servicio asociados.

La interface AssetEntry representa el concepto de asset y su tabla asociada en la base de datos de Liferay se llama assetentry. Sus campos más importantes son:

  • entryId: identificador único del asset.
  • userId: identificador del usuario que crea el contenido.
  • groupId: identifica el alcance en el que ha sido creado.
  • classNameId: identifica el tipo de contenido. Es el identificador de la clase asociado al contenido, se encuentra representado mediante la entidad ClassName y la tabla classname_.
  • classPK: identifica el contenido específico asociado al asset. Suele ser la clave primaria de la tabla donde se almacena el contenido.

El concepto asset se encuentra estrechamente relacionado con el concepto de categoría y etiqueta. Efectivamente, en la base de datos de Liferay se encuentran dos tablas que definen esa relación:

  • assetentries_assetcategories.
  • assetentries_assettags.

La clase AssetEntryLocalServiceUtil proporciona los métodos que nos permitirán manejar estos contenidos, recuperándolos, editándolos, etc.

El ejemplo que se muestra a continuación ilustra lo anteriormente comentado:

int total = AssetEntryLocalServiceUtil.getAssetEntriesCount();

int total = AssetEntryLocalServiceUtil.getAssetEntriesCount();

List contenidos = AssetEntryLocalServiceUtil.getAssetEntries(0,total);

for(int i=0;i<contenidos.size();i++){

AssetEntry c = contenidos.get(i);

...
}

Una vez definidos AssetEntry y de AssetEntryLocalServiceUtil, se pasa a describir uno de los tipos de contenidos más utilizados, los contenidos web.

Contenidos web

Introducción

Los contenidos web en Liferay son manejados mediante un conjunto de servicios y modelos y son almacenados en la base de datos en la tabla journalarticle. Sus campos más significativos son:

  • Identificador del contenido: articleId.
  • Título: title.
  • Descripción: description.
  • Identificador de la estructura asociada al contenido: structureId.
  • Identificador de la plantilla asociada al contenido: templateId.
  • Identificador de grupo: groupId.
  • Identificador de usuario: userId.
  • Información del contenido: content.

Un contenido web en Liferay es un objeto que implementa la interface JournalArticle que se encuentra en el paquete com.liferay.portlet.journal.model:

Son manejados mediante la clase JournalArticleLocalServiceUtil.

List<JournalArticle> lista = JournalArticleLocalServiceUtil.getArticles(scopeGroupId); for(int i=0;i<lista.size();i++){
JournalArticle journalArticle = lista.get(i);
...

Esta clase proporciona métodos para recuperar, actualizar, borrar y buscar contenidos web, de la misma forma en la que lo hacen todos los servicios de Liferay. A continuación, pasamos a describir alguna de las operaciones más habituales.

Mostrando contenidos

¿La entidad JournalArticle tiene acceso a la información del contenido web? ¿El método getContent() me permite recuperar el contenido del contenido web? ¿Esto tiene que ver con estructuras y plantillas?

Vamos a intentar aclarar estas preguntas a continuación.

Trabajando con plantillas y estructuras

Cuando se crea un contenido web con una estructura y una plantilla específicas, el proceso para mostrar el contenido web es algo diferente.
El método getContent() de la interface JournalArticle NO es válido.
Para mostrar el contenido generado como resultado de la aplicación de una estructura y una plantilla específicas aparece la entidad JournalArticleDisplay.

La interface JournalArticleDisplay y su método getContent() muestra el contenido web tras la aplicación de su estructura y plantilla asociada.

// Paso 1: Se recuperan todos los contenidos web
// que se encuentran en la comunidad donde se ha
// desplegado el portlet.
List<JournalArticle> lista = JournalArticleLocalServiceUtil.getArticles(scopeGroupId);
for(int i=0;i<lista.size();i++){
// Paso 2: Se recupera el articulo que se desea mostrar.
JournalArticle journalArticle = lista.get(i);
// Paso 3: Se recupera el idioma utilizado.
String languageId = LanguageUtil.getLanguageId(request);
// Paso 4: Se recupera el objeto JournalArticleDisplay
JournalArticleDisplay articleDisplay = JournalArticleLocalServiceUtil.getArticleDisplay(
journalArticle, null, null, languageId, 1, null, themeDisplay);

Una vez recuperado el objeto de tipo JournalArticleDisplay asociado a un determinado artículo, se podrá mostrar en cualquier página, tal que así:

...
<div>
<%= articleDisplay.getContent() %>
</div>
...

Extracción de campos específicos

¿Cómo se pueden recuperar campos específicos de un contenido web para procesarlos de forma independiente?


¿JournalArticle o JournalArticleDisplay?

Como se ha visto en el ejemplo anterior, la información asociada a un contenido web puede recuperarse a través del objeto de tipo JournalArticleDisplay, pero cuando necesito manejar parte de la información almacenada en el contenido, ¿qué puedo hacer? A continuación, se muestra una solución a este problema:

/*
* En este ejemplo se supone que el contenido
* esta asociado a una <strong>plantilla</strong> o <strong>estructura</strong> con un
* campo llamado title.
*/

String contenidoArticulo = journalArticle.
getContentByLocale(themeDisplay.getLanguageId());
Document documento = null;
String title=null;
String summary = null;
try{
documento = SAXReaderUtil.read(
new StringReader(contenidoArticulo));

Node node1 = documento.selectSingleNode(
<strong>"/root/dynamic-element[@name='title']/dynamic- content");</strong>

if (node1!=null && node1.getText().length() > 0) {
title = node1.getText();
}
...

¿Para qué trabajar con Assets?

Cuando trabajamos con contenidos web, ¿necesitamos incorporar el concepto Asset en algún momento? ¿Por qué existe esta entidad? Debe haber alguna razón. La respuesta es clara: categorías y etiquetas.
Es IMPORTANTE tener claro que la gestión de assets nos permite relacionar cualquier tipo de contenido con categorías y etiquetas, de cualquier otra forma sería imposible.

Gestión de assets

Para manejar assets se trabaja con las clases utility AssetEntryLocalServiceUtil y AssetEntryServiceUtil. Nos proporcionan los métodos habituales para manejar este tipo de entidades: add, create, delete, update, get, ...
Los procesos de búsqueda pueden llevarse a cabo de forma específica mediante el método getEntries:

public static List<AssetEntry>getEntries(AssetEntryQuery entryQuery)
                                               throws SystemException

Por ejemplo:

int total = AssetEntryLocalServiceUtil.getAssetEntriesCount();
List <AssetEntry> contenidos = AssetEntryLocalServiceUtil.getAssetEntries(0,total);

for(int i=0;i<contenidos.size();i++){
AssetEntry c = contenidos.get(i);
}

Consultas sobre Assets

El método getEntries asociado al servicio AssetEntryLocalServiceUtil es de vital importancia a la hora de llevar a cabo consultas:

public static List<AssetEntry> getEntries(AssetEntryQuery entryQuery)
throws SystemException

Recibe como parámetro una consulta y devuelve como valor de retorno una lista de contenido que cumple dicha consulta. Ahora bien, ¿cómo se construye ésta?

La clase AssetEntryQuery nos permite realizar consultas avanzadas sobre los diferentes assets almacenados en la instalación. Los métodos set nos permiten definir los criterios de búsqueda, por ejemplo:

  • public void setGroupIds(long[] groupIds): comunidades donde se han creado los contenidos.
  • public void setClassName(String className): tipo de contenido.
  • public void setAllCategoryIds(long[] allCategoryIds): contenidos con las siguientes categorías.
  • public void setAllTagIds(long[] allTagIds): contenidos con todas las etiquetas.
  • ...

Para ilustrar esta funcionalidad, se muestra a continuación el siguiente trozo de código:

  ...
// Paso 1: Se construye la consulta gracias a la clase // AssetEntryQuery.
AssetEntryQuery <strong>consulta</strong> = new AssetEntryQuery();

// Paso 2: Se inicializa la consulta.
// Paso 2.1: Comunidades donde se quiere realizar la // busqueda.

// Nota: idsComunidades es un array de tipo long
// que ha sido creado previamente con los identificadores
// de cada comunidad
consulta.setGroupIds(idsComunidades);

// Paso 2.2: Rango de documentos.
consulta.setStart(0);
consulta.setEnd(numNoticias);

// Paso 2.3: Tipo de contenido que se quiere modificar: // Contenido web.

// Se obtiene el <strong>identificador unico</strong> del className
// asociado al tipo contenido web.
ClassName nombre = ClassNameLocalServiceUtil.getClassName(
"com.liferay.portlet.journal.model.JournalArticle");
long classNameIdJournal = nombre.getClassNameId();

long[] tipos = {classNameIdJournal};

// El metodo setClassNameIds nos permite indicar los
// tipos de contenidos que quiere manejar.
consulta.setClassNameIds(tipos);

// Paso 2.4: <strong>Categorias asocidas</strong> a los contenidos web // que se quieren recuperar
// Nota: categoryIds es un array de tipo long creado
// previamente donde se almacenan los ids de las
// categorias a partir de las cuales se realiza
// la busqueda.
consulta.setAllCategoryIds(categoryIds);

// Paso 3: Una vez creada la query, gracias al metodo
// getEntries se ejecuta la consulta de busqueda.
List<AssetEntry> resultados =
AssetEntryLocalServiceUtil.getEntries(consulta);...
// Paso 1: Se construye la consulta gracias a la clase // AssetEntryQuery.
AssetEntryQuery <strong>consulta</strong> = new AssetEntryQuery();

// Paso 2: Se inicializa la consulta.
// Paso 2.1: Comunidades donde se quiere realizar la // busqueda.

// Nota: idsComunidades es un array de tipo long
// que ha sido creado previamente con los identificadores
// de cada comunidad
consulta.setGroupIds(idsComunidades);

// Paso 2.2: Rango de documentos.
consulta.setStart(0);
consulta.setEnd(numNoticias);

// Paso 2.3: Tipo de contenido que se quiere modificar: // Contenido web.

// Se obtiene el <strong>identificador unico</strong> del className
// asociado al tipo contenido web.
ClassName nombre = ClassNameLocalServiceUtil.getClassName(
"com.liferay.portlet.journal.model.JournalArticle");
long classNameIdJournal = nombre.getClassNameId();

long[] tipos = {classNameIdJournal};

// El metodo setClassNameIds nos permite indicar los
// tipos de contenidos que quiere manejar.
consulta.setClassNameIds(tipos);

// Paso 2.4: <strong>Categorias asocidas</strong> a los contenidos web // que se quieren recuperar
// Nota: categoryIds es un array de tipo long creado
// previamente donde se almacenan los ids de las
// categorias a partir de las cuales se realiza
// la busqueda.
consulta.setAllCategoryIds(categoryIds);

// Paso 3: Una vez creada la query, gracias al metodo
// getEntries se ejecuta la consulta de busqueda.
List<AssetEntry> resultados =
AssetEntryLocalServiceUtil.getEntries(consulta);

AssetEntry vs JournalArticle

Una vez que se recuperan los assets asociados a una consulta ...
¿Cómo recupero los contenidos web asociados?

La relacion entre JournalArticle y AssetEntry se define mediante una entidad llamada JournalArticleResource:

La entidad AssetEntry tiene un campo llamado classPK. Este campo permite relacionar ambas entidades mediante el método getArticleResource():

...
AssetEntry e = ...;
JournalArticleResource recurso = JournalArticleResourceLocalServiceUtil.
getArticleResource(e.getClassPK()); JournalArticle articulo =
JournalArticleLocalServiceUtil.getArticle(
e.getGroupId(), recurso.getArticleId());

Conclusión

Si el programador es capaz de manejar los conceptos tratados en este artículo, no tendrá ningún problema a la hora de extender los portlets del core Liferay que se encargan de manejar contenidos, por ejemplo:

  • Asset Publisher.
  • Display Content.
  • ...

Lógicamente, también podrá crear nuevos portlets que trabajen con cualquier tipo de contenido.

Kommentarer
Trackback URL:

comments powered by Disqus