Liferay 7 / DXPで上部の管理ナビゲーションバー(Control menu)の色を変更したい

## 対応バージョン
Liferay DXP SP1以降 / Liferay 7 CE

## はじめに
プロジェクトの要件で、Liferayの上部に表示される管理ナビゲーションバー(Control Menu/Product Menu/Simulation Menuからなるナビゲーション)の色を変更したい（Themeと色味を合わせたい)という要件は多くある。その場合の対応方法を説明する。

[公式ドキュメント:THEME CONTRIBUTORS](https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/theme-contributors)
[公式ドキュメント:CONTEXT CONTRIBUTORS](https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/context-contributors)
に対応方法の説明が載っているが、実際のポートレットの作成方法をここに説明する。

## 前提条件
Liferay workspaceは作成されていて、bladeツール、Theme作成ツール各種はインストールされている前提とする。以下の資料でセットアップ方法は説明している。

- [Liferay DXP / 7におけるサービスビルダーポートレットの作成方法](http://qiita.com/yasuflatland-lf/items/df60ef27b7710bca1607)
- [Liferay 7 / DXPでのテーマの作り方](http://qiita.com/yasuflatland-lf/items/857b009ccbc9f9e3ae59)

テストシナリオとして、Control Menuを赤く変更するための実装を行うこととする。対応するCoreのTheme provierとの関連は以下の通りになる。

| 機能名       | プロジェクト名 | パス |
|:--|--:|--:|
| Control Menu |product-navigation-control-menu-dxp-theme-contributor | /liferay-portal/modules/private/apps/web-experience/product-navigation |
| Product Menu |product-navigation-product-menu-dxp-theme-contributor | /liferay-portal/modules/private/apps/web-experience/product-navigation |
| Simulation Menu | product-navigation-simulation-theme-contributor | /liferay-portal/modules/apps/web-experience/product-navigation |

## Theme contributorの作成
$(liferay_workspace)/modulesの下に移動。

そこでControl Menuのバンドルを置換するためのTheme contributerを作成する必要がある。Liferay Developer Studio / IDEの File -> New -> Liferay Module Projectを選択、Project Template Nameでtemplatecontextcontributorを選択。
もしくはコマンドラインで

```bash
blade create -t template-context-contributor -p com.liferay.product.navigation.control.menu.theme.contributor -c SampleProductNavigationControlMenu sample-product-navigation-control-menu-theme-contributor
```

でbladeツールを使ってモジュールプロジェクトを作成する。

### SampleProductNavigationControlMenuTemplateContextContributorの作成

Control Menuのベースとなるファイルを開く

```bash:ProductNavigationControlMenuTemplateContextContributor.java
vi /liferay-portal/modules/apps/web-experience/product-navigation/product-navigation-control-menu-theme-contributor/src/main/java/com/liferay/product/navigation/control/menu/theme/contributor/internal/ProductNavigationControlMenuTemplateContextContributor.java
```

ProductNavigationControlMenuTemplateContextContributor.javaの中身をSampleProductNavigationControlMenuTemplateContextContributor.javaにコピー。

```java:SampleProductNavigationControlMenuTemplateContextContributor.java

	@Override
	public void prepare(
		Map<String, Object> contextObjects, HttpServletRequest request) {

		if (!isShowControlMenu(request)) {
			return;
		}

		String cssClass = GetterUtil.getString(
			contextObjects.get("bodyCssClass"));

		contextObjects.put("bodyCssClass", cssClass + " has-control-menu");
	}

	protected boolean isShowControlMenu(HttpServletRequest request) {
		ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
			WebKeys.THEME_DISPLAY);

		if (themeDisplay.isImpersonated()) {
			return true;
		}

		if (!themeDisplay.isSignedIn()) {
			return false;
		}

		User user = themeDisplay.getUser();

		if (!user.isSetupComplete()) {
			return false;
		}

		return true;
	}
```

### SCSSリソースのコピー
product-navigation-control-menu-theme-contributor(***オリジナル***)の方のresourcesディレクトリ以下

```bash
/src/main/resources
```

をsample-product-navigation-control-menu-theme-contributor(***今回作成のTheme contributer***)の

```bash
/src/main/resources
```

以下にコピーする。(mainディレクトリ以下はjavaディレクトリしかないので、resourcesフォルダごとコピー)

次に以下のファイルの箇所を変更してみる

```scss:_control_menu.scssの34行目付近
.control-menu-level-1 {
	background-color: #990000; //ここを直値でテストで赤に変更。本当はSCSSで変数を作って対応する。
	color: $control-menu-level-1-color;
```

### bnd.bndファイルの設定

***オリジナル***のbndファイルの内容を確認し、以下のように***今回作成のTheme contributer***のbnd.bndファイルにコピーする

```properties:bnd.bnd
Bundle-Name: Liferay Product Navigation Control Menu DXP Theme Contributor SAMPLE
Bundle-SymbolicName: com.liferay.product.navigation.control.menu.dxp.theme.contributor
Bundle-Version: 1.0.7
Liferay-Releng-Module-Group-Description:
Liferay-Releng-Module-Group-Title: Product Navigation
Liferay-Theme-Contributor-Type: product-navigation-control-menu
Liferay-Theme-Contributor-Weight: 1500
Web-ContextPath: /product-navigation-control-menu-dxp-theme-contributor
```

ここでは以下に注意する。

<dl>
    <dt>Bundle-Version</dt>
    <dd>これはオリジナルの番号に合わせる</dd>
    <dt>Liferay-Theme-Contributor-Weight</dt>
    <dd>これはオリジナルの値より大きい番号にする。それによってbundleのロード優先順位が変わる。</dd>
</dl>

### デプロイ
Liferay DXPを起動し、

```bash
blade deploy
```

でデプロイする。

### 注意点
 上記はControl Menuのみの例だが、Product Menu / Simulation Menu共に、同様の方法で色の変更ができる。ただし、これらのバンドルは管理画面やコアに深く関わる部分なので、変更は最小限に抑えておかないと、コア側の変更があった場合に、オーバーライドしたバンドルとの差分が生じ、問題が発生する可能性がある。

SCSSのバグにより、第一階層以外のSCSSファイルを変更しても、変更が反映されない、という動作をします。[(関連するJIRAチケット)](https://issues.liferay.com/browse/LPS-68319)なので、SCSSファイルを変更した場合は、必ず第一階層のSCSSファイル(Control Menuの場合はproduct_navigation_control_menu.scss)に改行を入れたり、抜いたりして編集して、SCSSがコンパイルされるようにしてからデプロイ(gradle cssBuildが走る）ようにしてください。

 また[Liferay 7 / DXPで上部の管理ナビゲーションバー(Control menu)の表示を制御したい](http://qiita.com/yasuflatland-lf/items/33d692aeec992a6b3cf4)の記事のように、表示・非表示の制御などもSampleProductNavigationControlMenuTemplateContextContributor.javaで変更可能なので、参考にしてみてほしい。