Wednesday, August 1, 2018

Demystifying Liferay categories: leftCategoryId / rightCategoryId

Liferay allows site administrators to define a "vocabulary" containing categories such as:

  • Cheese
  • Bread
  • Butter

Web content can then be classified using these categories, for instance a news article about canapé would be assigned the categories "Cheese" and "Bread".

Create a Liferay page, put a "Category Navigation" application and an "Asset Publisher" on it, link them and voilà! You have a nice page where relevant articles appear depending on the category you clicked.

Categories can have sub-categories:



Left and right


When you click on a category, you will notice this parameter in the URL: categoryId=21434

You can inspect this category by putting it in the "parentCategoryId" field of this Liferay API page:
https://yourserver/api/jsonws?signature=%2Fassetcategory%2Fget-child-categories-1-parentCategoryId#serviceResults

You will notice that each category has a "leftCategoryId" and a "rightCategoryId" field. What are those!?

They help Liferay easily display items in the category navigation widget. Here is how they are stored in database:

mysql> SELECT leftCategoryId, rightCategoryId, name FROM AssetCategory WHERE vocabularyId=21431 ORDER BY leftCategoryId;
+----------------+-----------------+-----------+
| leftCategoryId | rightCategoryId | name      |
+----------------+-----------------+-----------+
|              2 |               7 | Cheese    |
|              3 |               4 | Camembert |
|              5 |               6 | Roquefort |
|              8 |               9 | Bread     |
|             34 |              35 | Butter    |
+----------------+-----------------+-----------+
5 rows in set (0.00 sec)

When you click on a category, for instance "Cheese", Liferay will use the category identifier to get the Cheese row, and get the left and right, here "2 and "7". Liferay will then use these identifiers in the following SQL request:

SELECT categoryId, name FROM AssetCategory WHERE (groupId = ___) AND (leftCategoryId BETWEEN ___ AND ___);

... where the first blank is the Liferay site identifier, and the second and third are the first and last categories of the vocabulary, in our example 2 and 7. Let's run it:

mysql> SELECT categoryId, name FROM AssetCategory WHERE (groupId = 20181) AND (leftCategoryId BETWEEN 2 AND 7);
+------------+-----------+
| categoryId | name      |
+------------+-----------+
|      21433 | Cheese    |
|      21703 | Camembert |
|      21704 | Roquefort |
+------------+-----------+
3 rows in set (0.01 sec)

Voilà! You get all of the categories whose articles should appear on the page when you click "Cheese".

You might ask: Why not just use parentId to get all categories whose parent is the Cheese categories, and then recursively their own sub-categories using the same technique?
Answer: It would not scale. For vocabularies with n levels of sub-categories, the recursion would trigger O(n!) SQL requests, whereas the left/right strategy uses O(1) SQL requests. This technique is called nested set model. Its drawback is that left/right information must be rebuilt every time an administrator moves or deletes a category.

Rouelle du Tarn, by Tangopaso - Wikimedia Commons, Public domain

Applicable to Liferay 6.2 and Liferay 7.0
Nicolas Raoul

Monday, May 21, 2018

Alfresco勉強会を終了します!


イージフの戸谷です。

唐突なエントリタイトルですが44回にわたり続けてきたAlfresco勉強会を終了することにしました。
次回勉強会の日程が設定されていない状態を続けるのも良くないので、ここで終了の理由を書いておきたいと思います。
心配される方もいらっしゃるかもしれないですが、イージフがAlfrescoを扱わなくなる、ということでは全くありませんのでご安心ください!

終了するに至った理由はいくつかあるのですが、その中で最も大きかったことは私を含めた弊社メンバが発表したいと考えていた内容と、参加される方が期待される内容にズレが生じていた、ということでした。弊社メンバはAlfrescoの技術的な(ともすればマニアックな)情報を発表したい。一方で参加される方のほとんどはAlfrescoでは何ができるのか、どういう使い方をするのか知りたいという方が多かったため、結果としてAlfrescoの使い方について毎回説明するセッションを設けつつ、技術的な発表についてはボリュームを少なくするなど調整しながら勉強会を実施していました。ただこれは発表者、参加者双方にフラストレーションを溜めやすい構造になっていたように思います。

そこで今後技術情報については全てこのLaboブログで発信します。そうすることで弊社メンバが伝えたい情報粒度で勉強会の場よりも自由に情報発信ができるようになると考えています。

一方でこれまで勉強会が実質的に担っていたAlfrescoの使い方を知っていただく場については、今後弊社主催のAlfrescoの無料ワークショップという型式で定期的に開催しようと考えています。内容や時期については現在準備中ですので詳細が決まったらLaboブログでも連絡いたします。弊社で取り扱っているOSSのポータルプロダクトであるliferayについても同様に技術情報はLaboブログで発信し、無料ワークショップの開催を検討しています。

型式は変わりますが今後もAlfrescoも技術情報は継続的に発信していきますので、ぜひLaboブログをよろしくおねがいします。

How to install Alfresco 6 on Linux

Hello, I am Nicolas! So, you want to try Alfresco on Linux? Alfresco used to provide a user-friendly wizard installer, but starting from Alfresco 6 they only provide a Docker image. It is not much more complicated, if you follow the instructions below. I have tested on Ubuntu Linux 2018.04, if the instructions are different for other distributions of Linux please write a comment, thanks!

Step 1: Install Docker

If you don't have Docker yet, install the package:

sudo apt install docker.io docker-compose

Then add your user to the docker group (replace "nico" with your username):

sudo usermod -aG docker nico

For this change to take effect, either log out and log in again, or just type this into your terminal, as your user:

newgrp docker

Step 2: Install Alfresco

If you don't have Git yet, install the package:

sudo apt install git

Then, as your normal Linux user, go to any folder that has 500 kilobytes of free space (yes that part is very small as it is a kind of installer rather Alfresco itself), for instance your home folder, and execute these commands one after the other:

git clone git@github.com:Alfresco/acs-community-deployment.git
cd acs-deployment/docker-compose
docker-compose up

That's it, your new Alfresco is now being downloaded and started! Go have a break.

Using your Alfresco 6

The Alfresco user interface (called Alfresco Share) is at http://localhost:8080/share

The CMIS and WebDAV URLs, as well as some administration tools such as the Node Browser and the WebScripts Home, can be found at http://localhost:8082/alfresco

Alfresco 6 uses Solr to index content, and the Solr console is available at http://localhost:8083/solr

To stop Alfresco, just press CTRL-C in ther terminal where you have launched "docker-compose up". This will not reset your changes nor lose your documents. To start Alfresco again, just launch the same "docker-compose up" command in the acs-community-deployment/docker-compose folder.

 


Going further

As you might have guessed, Alfresco is split into several Docker containers.
To see them all, type the following:

docker container ls

This shows you all of your containers. Have a look at the last column:

[...] NAMES
[...] dockercompose_share_1
[...] dockercompose_solr6_1
[...] dockercompose_alfresco_1
[...] dockercompose_postgres_1

The containers are listed in reverse startup order:
- Alfresco Share (the web interface)
- Alfresco Search Services (the Solr engine and database)
- Alfresco Content Repository (the repository)
- Postgres (the main database)

To see the logs for all containers in real-time, type this:
docker-compose logs --follow share alfresco solr6 postgres

Let's say you want to modify a configuration file or check memory consumption on the Postgres container. Copy the name of Postgres in the "NAMES" column (for instance mine is dockercompose_postgres_1) and paste it inside this command:

docker exec -it dockercompose_postgres_1 bash

That's it, now you have a terminal inside your container!

If you like Alfresco and want to install it on a production server, Alfresco recommends Kubernetes instead of Docker, more on this later!

Tuesday, May 8, 2018

Alfrescoノードブラウザ での検索


こんにちは。たなかです。
定期的に自分の中で編み物ブームが来るのですが、1ヶ月ほど前からまたブームが来ており最近は子供たちに夏用の帽子やバッグを編んでいます。
今編んでいる帽子の毛糸の素材が和紙なのですが、洗えるし軽いから風が吹いても飛ばないと店員さんに聞いて和紙の凄さを再認識しました。

さて、Alfrescoのノードブラウザで行う検索方法をいくつかピックアップしてご紹介したいと思います。
今回利用しているバージョンはAlfresco Community Edition 201707 GAです。

ノードブラウザ は、管理ツールなので管理者が利用することができます。
各ノードの情報を1ページで見ることができるため、タイプやプロパティ、アスペクト、権限情報などを一度に確認することが可能です。


ノードブラウザはShareの管理ツールとPlatformからのアクセスの2通りの方法があります。
Platformからはhttp://localhost:8080/alfresco/s/admin/からアクセスできます。
Platformのノードブラウザ ではノードやプロパティの削除ができたり、結果の最大表示件数の指定ができます。

今回はShareのノードブラウザ をご紹介したいと思います。

adminでログインし、管理ツールからノードブラウザ を開きます。

テキストエリアに検索クエリを入力して、言語を選択し検索ボタンを押すと結果がリストで表示されます。
条件をいくつか入れて絞り込みたい場合はANDを使って条件クエリを追加していきます。(ORの使用も可能です。)

この初期画面からノードを選択してツリー構造の任意のフォルダやコンテンツにたどり着くこともできるので少しだけ先にご紹介します。

ノードブラウザを選択後の初期画面(検索結果が出ている状態ですね)の名前が空になっている方のノード(参照列)を選択します。

次に子の名前がapp:company_homeのノードを選択します。

続いて子の名前がapp:sharedのノードを選択します。
app:sharedが共有フォルダになります。

さらに子の名前がcm:TestFolderInRepo(自分で作成したフォルダです)のノードを選択してみます。
フォルダかファイルかは、子のタイプがcm:folder(フォルダ)、cm:content(ファイル)かで判断できます。

各ノードのページにあるバージョン情報のプライマリパスが下でご紹介する検索のPATHで使える値になります。

◆FTS-Alfrescoによる検索



fts-alfrescoを検索言語に選んだ場合にどのような検索ができるかを紹介してみたいと思います。

●PATHの指定

まずはPATH検索で共有フォルダ配下を取得してみます。
 PATH:"/app:company_home/app:shared//*" と入力して検索!


共有フォルダ配下のフォルダやコンテンツが表示されています。
共有フォルダはよく使うので覚えておくと便利だと思います。

共有フォルダ下にあるフォルダ配下のコンテンツも表示されていますね。
/*とすると、指定ディレクトリ以下全て、という指定になります。

TestFolderInRepoフォルダ配下を指定したい場合は
 PATH:"/app:company_home/app:shared/cm:TestFolderInRepo//*" 
を入力します。
正しく取得されました。

名前

TestFolderInRepoフォルダを除外してみます。
 NOT cm:name:"TestFolderInRepo" クエリに追加します。


除外なのでNOTをつけましたが、NOTをとると・・・

指定フォルダだけ表示されました。


ワイルドカードの*(アスタリスク)を使うこともできるので、『コンテンツ』から始まるファイル名のファイルを取得してみます。
 cm:name:"コンテンツ*" 
指定フォルダ配下の『コンテンツ〜』という名前のファイルが全て表示されました。


作成日

次はフォルダやコンテンツの作成日で絞り込んでみます。
 cm:created:[MIN TO 2018-05-01] 
試しに2018-05-01までに作成されたもので絞り込みました。

MINだけでなくMAXやNOWなども使用可能です。

範囲指定ではなく日付指定の場合は
 cm:created:'2018-05-01'  のような記述で検索できます。

 

作成者

フォルダまたはコンテンツの作成者で指定してみます。
 cm:creator:"*collaborator" OR cm:creator:"*contributor" 
ANDばかりだったので、ORを使ってみました。

今回は*を検索ワードの前に使用してみました。
ここではcollaborator, contributorはもちろん、acontributorなども作成者のコンテンツが取得されました。

名前、作成日、作成者をご紹介しましたが、他にも
編集者(cm:modifier
編集日(cm:modified
タイトル(cm:title
説明(cm:description
なども利用可能です。
基本の構文を覚えてしまえば適宜変更するだけなので簡単です
 

タイプ

 TYPE:"cm:content" を入力すると、コンテンツタイプのものだけ取得できます。
cm:folderだとフォルダになります。

アスペクト

付与されたアスペクトで検索してみます。
 ASPECT:"cm:dublincore" 

noderefによる検索


検索言語にnoderefを指定して検索を行います。

フォルダやコンテンツを作成すると必ずNodeRefというものが作成されます。
そのNodeRefはユニークなのでそれがわかれば一発で目的のノードにたどり着くことができて便利です。

ちなみに、先に紹介したfts-alfrescoでもNodeRefを使って検索することができます。(私はnoderefを選択しているのでほぼ使わないですが・・・)
 ID:"workspace://SpacesStore/999xxx〜" 

Alfrescoで実行できる検索クエリはまだたくさん種類があるのですが、今回はその中から使う頻度が高いと思うものをご紹介させていただきました。

Wednesday, May 2, 2018

Alfrescoの権限と役割


こんにちは。たなかです。
小学生の子供がいるのですが、子供1人につき少なくとも1度はPTAの何かしらの委員をしなければいけないという学校で今年はじゃんけんで勝ち、無事に広報委員になることができました。
みなさん低学年のうちにやっておきたいようで、3年生でも希望者が多く競争率高いです。ちなみに去年はじゃんけんで最後の1枠の勝負で負けました。

さて、今回はAlfrescoの権限と役割についてご紹介したいと思います。
今回利用しているバージョンはAlfresco Community Edition 201707 GAです。

リポジトリのPermissionとRole


リポジトリでは以下のロールが提供されています。
  • Consumer:利用者
フォルダやコンテンツのRead権限を持ちます。
フォルダにアクセスしてファイルの閲覧、ダウンロードが可能です。
  • Editor:編集者
フォルダやコンテンツのReadとUpdate権限を持ちます。
フォルダにアクセスしてファイルの閲覧、ダウンロードに加えてプロパティの編集やコピーなどが可能です。
  • Contributor:投稿者
フォルダやコンテンツのRead、CreateとUpload権限を持ちます。
フォルダにアクセスしてファイルの閲覧、ダウンロード、ファイルやフォルダの作成、アップロードやコンテンツのコピーなどが可能です。
Update権限は持たないため、ファイルの編集やプロパティの編集などはできません。
  • Collaborator:共同作業者
フォルダやコンテンツのRead、CreateとUpload、Updateの権限を持ちます
フォルダにアクセスしてファイルの閲覧、ダウンロード、ファイルの編集、プロパティの編集やコピーなどが可能です。

※ Owner:作成者
全ての権限を持っていないユーザでも、ファイルやフォルダの作成者であれば自分で作成したフォルダやファイルに関してはOwnerとして全ての権限を持つため、削除や更新、権限管理なども可能です。
  • Coordinator:調整者
フルアクセス可能なので、全ての権限を持ちます。
Collaborator(共同作業者)では出来ないルールの管理や権限の管理も可能です。

フォルダ権限を設定してみる


権限を付与したいフォルダの『権限の管理』を選択します。


右上の『ユーザー/グループの追加』からユーザーやグループを追加します。

任意の役割を選択して保存します。

実際にログインしてみます。


 利用者権限を持つユーザでログイン 

Read権限のみを持つため、上部メニューの作成やアップロードが非アクティブになっていて選択できないようになっています。

 編集者権限を持つユーザでログイン 

ReadとUpdate権限を持つため、上部メニューの作成やアップロードは非アクティブですが、プロパティの編集などがコンテンツの右部メニューに表示されていてプロパティの編集もできます。


 投稿者権限を持つユーザでログイン 


Read、CreateとUpload権限を持つため、上部メニューの作成とアップロードがアクティブになっていますが、Update権限は持たないため右部メニューにプロパティの編集などがありません。


 共同作業者権限を持つユーザでログイン 


Read、CreateとUpload、Updateの権限を持つため、上部メニューの作成とアップロードがアクティブ、右部メニューにもプロパティの編集等が表示されています。


 調整者権限を持つユーザでログイン 


全ての権限を持つため、作成やアップロードはもちろん、プロパティの編集と移動や削除、権限の管理やルールの管理も可能です。

 Owner:作成者 
調整者ではない権限のユーザでコンテンツを作成してみました。
ユーザの権限は変わらないですが、このコンテンツに関しては Owner権限 を持ちます。


共同作業者権限のユーザでログインしている場合、他のユーザが作成したコンテンツ(先に紹介したコンテンツA参照)では右部メニューに『文書の削除』や『移動先』などが表示されていなかったですが、自分で作成したコンテンツはメニューに表示されています。

投稿者権限のユーザでログインしている場合、自分で作成したコンテンツはメニューに『文書の削除』や『移動先』などが表示されています。

サイトのPermissionとRole



サイトではアクセス権限の設定のために、以下のロールが提供されています。
    • Site Consumer:サイト利用者
    リポジトリのConsumerと同じで、フォルダやコンテンツのRead権限を持ちます。
    • Site Contributor:サイト投稿者
    リポジトリのContributorと同じで、フォルダやコンテンツのRead、CreateとUpload権限を持ちます。
      • Site Collaborator:サイト共同作業者
      リポジトリのCollaboratorと同じで、フォルダやコンテンツのRead、CreateとUpload、Updateの権限を持ちます
        • Site Manager:サイトマネージャ
        リポジトリのCoordinatorと同じで、フルアクセス可能なので、全ての権限を持ち、Site Collaborator(サイト共同作業者)では出来ないルールの管理や権限の管理も可能です。

        フォルダ権限を設定してみる


        権限を付与したいフォルダの『権限の管理』を選択します。


        右上の『ユーザー/グループの追加』からユーザーやグループを追加します。

        任意の役割を選択して保存します。

        実際にログインしてみます。

         サイト利用者権限を持つユーザでログイン 

        コンテンツの閲覧のみなので、上部メニューの作成、アップロードが非アクティブになっています。
        プロパティの編集もメニューに表示されていません。

         サイト投稿者権限を持つユーザでログイン 

        コンテンツの閲覧に加え、作成とアップロードができるためメニューがアクティブになっています。
        プロパティの編集もできないため、メニューに表示されていません。

         サイト共同作業者権限を持つユーザでログイン 

        コンテンツの閲覧、作成、アップロードと編集ができるため、上部メニューの作成、アップロードがアクティブになっており、またプロパティの編集も表示されています。

         サイトマネージャ権限を持つユーザでログイン 



        全ての権限を持つため、作成やアップロード、プロパティの編集はもちろん、削除や移動、権限の管理やルールの管理も可能です。

         Owner:作成者 
        調整者ではない権限のユーザでコンテンツを作成しました。
        ユーザの権限は変わらないですが、リポジトリ同様、このコンテンツに関しては Owner権限 を持つためリポジトリと同じ動きをしていることが分かります。

        サイト共同作業者権限のユーザでログイン

        サイト投稿者権限のユーザでログイン


        リポジトリとサイトでは名称や種類など多少の違いはありますが、リポジトリを覚えてしまえばサイトもほとんど変わらないので覚えやすいかと思います。