{#
This file is part of EC-CUBE
Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
http://www.ec-cube.co.jp/
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{# ============================================================
カテゴリナビゲーション(PC版)
機能:
- カテゴリ一覧をツリー構造で表示
- 在庫切れカテゴリの表示/非表示切り替え対応
- カウント表示の動的切り替え対応(全商品数/在庫あり商品数)
============================================================ #}
{# データ取得 #}
{% set Categories = repository('Eccube\\Entity\\Category').getList() %}
{% set CategoriesCount = repository('Eccube\\Entity\\Product').findProductsWithCategoriesCount() %}
{% set CategoriesCountInStock = repository('Eccube\\Entity\\Product').findProductsWithCategoriesCountInStock() %}
{# ============================================================
マクロ: hasStockInTree
目的: カテゴリまたはその子孫カテゴリに在庫あり商品があるか判定
引数:
- Category: 判定対象のカテゴリエンティティ
- CategoriesCountInStock: カテゴリごとの在庫あり商品数の配列
戻り値: 'true' または 'false' (文字列)
ロジック:
1. 該当カテゴリ自体に在庫あり商品があれば 'true'
2. なければ子カテゴリを再帰的にチェック
3. 子孫のどこかに在庫があれば 'true'、なければ 'false'
============================================================ #}
{% macro hasStockInTree(Category, CategoriesCountInStock) %}
{%- if CategoriesCountInStock[Category.id] is defined and CategoriesCountInStock[Category.id] > 0 -%}
true
{%- else -%}
{%- set found = 'false' -%}
{%- for ChildCategory in Category.children -%}
{%- if _self.hasStockInTree(ChildCategory, CategoriesCountInStock)|trim == 'true' -%}
{%- set found = 'true' -%}
{%- endif -%}
{%- endfor -%}
{{ found }}
{%- endif -%}
{% endmacro %}
{# ============================================================
マクロ: hasProductInTree
目的: カテゴリまたはその子孫カテゴリに商品があるか判定
引数:
- Category: 判定対象のカテゴリエンティティ
- CategoriesCount: カテゴリごとの全商品数の配列
戻り値: 'true' または 'false' (文字列)
ロジック:
1. 該当カテゴリ自体に商品があれば 'true'
2. なければ子カテゴリを再帰的にチェック
3. 子孫のどこかに商品があれば 'true'、なければ 'false'
============================================================ #}
{% macro hasProductInTree(Category, CategoriesCount) %}
{%- if CategoriesCount[Category.id] is defined and CategoriesCount[Category.id] > 0 -%}
true
{%- else -%}
{%- set found = 'false' -%}
{%- for ChildCategory in Category.children -%}
{%- if _self.hasProductInTree(ChildCategory, CategoriesCount)|trim == 'true' -%}
{%- set found = 'true' -%}
{%- endif -%}
{%- endfor -%}
{{ found }}
{%- endif -%}
{% endmacro %}
{# ============================================================
マクロ: tree
目的: カテゴリを再帰的にツリー表示
引数:
- Category: 表示対象のカテゴリエンティティ
- CategoriesCount: カテゴリごとの全商品数の配列
- CategoriesCountInStock: カテゴリごとの在庫あり商品数の配列
出力するHTML属性:
- data-count-all: 全商品数(JS用)
- data-count-stock: 在庫あり商品数(JS用)
- data-has-stock: 在庫有無フラグ(JS用)
- no-stock-category: 在庫なしカテゴリのCSSクラス
============================================================ #}
{% macro tree(Category, CategoriesCount, CategoriesCountInStock) %}
{% from _self import tree, hasStockInTree, hasProductInTree %}
{# カウント値を取得(未定義の場合は0) #}
{% set countAll = CategoriesCount[Category.id] is defined ? CategoriesCount[Category.id] : 0 %}
{% set countStock = CategoriesCountInStock[Category.id] is defined ? CategoriesCountInStock[Category.id] : 0 %}
{# カテゴリリンク
- data-count-all: JSで全商品数表示に切り替える際に使用
- data-count-stock: JSで在庫あり商品数表示に切り替える際に使用
- js-category-count: JSでカウント表示を更新するためのクラス #}
<a class="left-menu-link js-category-link" href="{{ url('product_list') }}?category_id={{ Category.id }}" data-count-all="{{ countAll }}" data-count-stock="{{ countStock }}">
{# トップレベルカテゴリのみアイコン表示 #}
{% if (Category.Parent == "") %}
<img class="menu-icon" src="/html/user_data/assets/img/category/{{ Category.id }}.png" alt="{{ Category.name }}">
{% endif %}
<span class="category-text">{{ Category.name }} (<span class="js-category-count">{{ countAll|number_format }}</span>)</span>
</a>
{# 子カテゴリがある場合、サブメニューを表示 #}
{% if Category.children|length > 0 %}
{% set childCount = Category.children|length %}
{# 子カテゴリ数に応じてカラム表示クラスを設定
- 16個以上: 3列表示
- 8-15個: 2列表示
- 7個以下: 1列表示
※ 孫カテゴリ以降は常に1列 #}
{% if Category.Parent == "" %}
{# トップレベルカテゴリの子(1階層目) #}
{% if childCount >= 16 %}
{% set submenuClass = 'js-submenu-three-column' %}
{% elseif childCount >= 8 %}
{% set submenuClass = 'js-submenu-two-column' %}
{% else %}
{% set submenuClass = '' %}
{% endif %}
{% elseif Category.Parent.Parent == "" %}
{# 2階層目(孫カテゴリ)は常に1列 #}
{% set submenuClass = '' %}
{% else %}
{# 3階層目以降も常に1列 #}
{% set submenuClass = '' %}
{% endif %}
<ul class="{{ submenuClass }}" data-child-count="{{ childCount }}">
{% for ChildCategory in Category.children %}
{# 子カテゴリの在庫判定(子孫含む) #}
{% set childHasStock = hasStockInTree(ChildCategory, CategoriesCountInStock)|trim %}
{# 子カテゴリの商品有無判定(子孫含む) #}
{% set childHasProduct = hasProductInTree(ChildCategory, CategoriesCount)|trim %}
{# no-stock-category: 在庫なしカテゴリを非表示にするためのクラス
no-product-category: 商品なしカテゴリを常に非表示にするためのクラス
data-has-stock: JSで在庫状態を判定するための属性 #}
<li class="{% if childHasStock == 'false' %}no-stock-category {% endif %}{% if childHasProduct == 'false' %}no-product-category{% endif %}" data-has-stock="{{ childHasStock }}">
{{ tree(ChildCategory, CategoriesCount, CategoriesCountInStock) }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{# マクロのインポート @see https://github.com/bolt/bolt/pull/2388 #}
{% from _self import tree, hasStockInTree, hasProductInTree %}
{# ============================================================
カテゴリナビゲーション本体
============================================================ #}
<div class="category_list">
<dl>
<dt>カテゴリ一覧</dt>
</dl>
</div>
<div class="ec-categoryNaviRole">
<div class="ec-itemNav">
<ul class="ec-itemNav__nav">
{% for Category in Categories %}
{# トップレベルカテゴリの子カテゴリ数に応じてクラスを設定 #}
{% set topChildCount = Category.children|length %}
{% if topChildCount >= 16 %}
{% set topLevelClass = 'js-has-very-many-children' %}
{% elseif topChildCount >= 8 %}
{% set topLevelClass = 'js-has-many-children' %}
{% else %}
{% set topLevelClass = '' %}
{% endif %}
{# 在庫判定(子孫含む) #}
{% set hasStock = hasStockInTree(Category, CategoriesCountInStock)|trim %}
{# 商品有無判定(子孫含む) #}
{% set hasProduct = hasProductInTree(Category, CategoriesCount)|trim %}
{# トップレベルカテゴリのli要素
- no-stock-category: 在庫なしの場合に付与(JSで表示/非表示制御)
- no-product-category: 商品なしの場合に付与(常に非表示)
- data-has-stock: 在庫状態フラグ #}
<li class="{{ topLevelClass }}{% if hasStock == 'false' %} no-stock-category{% endif %}{% if hasProduct == 'false' %} no-product-category{% endif %}" data-child-count="{{ topChildCount }}" data-has-stock="{{ hasStock }}">
{{ tree(Category, CategoriesCount, CategoriesCountInStock) }}
</li>
{% endfor %}
</ul>
</div>
</div>