Last active
December 31, 2019 18:47
-
-
Save emb03/9046ae343c40a1246a9324b52c539e0b to your computer and use it in GitHub Desktop.
Drupal 8 Services Example using PHP Traits and pass by reference
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style> | |
.grid { | |
display: grid; | |
grid-gap: 10px; | |
grid-template-columns: repeat(auto-fill, minmax(250px,1fr)); | |
grid-auto-rows: 40px; | |
} | |
</style> | |
<script> | |
var site_url = '{{ base_url }}'; | |
</script> | |
<!-- Fixed navbar --> | |
{% include directory ~ '/partials/header.html.twig' %} | |
{% | |
set classes = [ | |
'paragraph', | |
'paragraph--type--' ~ paragraph.bundle|clean_class, | |
'paragraph-id--' ~ paragraph.id(), | |
] | |
%} | |
{# page-banner #} | |
<div class="container-fluid"> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div id="page-title-bg" style="background-image: url('{{ file_url(node.field_image.entity.fileuri) }}')"></div> | |
</div> | |
</div> | |
</div> | |
{# End page-banner #} | |
<!-- contain --> | |
<div class="container" id="main-container"> | |
<!-- Main content --> | |
<div class="row"> | |
{{ drupal_entity('block', 'cpv3_local_tasks') }} | |
<div class="col-md-12" style="padding-left: 30px;"> | |
<h1>{{ node.label }}</h1> | |
</div> | |
</div> | |
<!-- Left-side bar --> | |
<div class="row content-wrapper" id="community-plan-update"> | |
<div class="col-md-9"> | |
<div class="section-content clear"> | |
<div class="row "> | |
{% if node.field_slider %} | |
{% for parag_id in node.field_slider.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
</div> | |
{# menu #} | |
<div class="row"> | |
<div class="col-md-12 dropdown"> | |
<div id="hollywood-tab"> | |
<ul class="nav nav-tabs" role="tablist"> | |
{% for item in downtown_menu %} | |
{% if loop.index == 0 %} | |
{% set active_class = 'active' %} | |
{% set class = 'padding-left0' %} | |
{% else %} | |
{% set active_class = '' %} | |
{% set class = '' %} | |
{% endif %} | |
<li role="presentation" class="padding-top0 {{ (loop.last) ? '' : 'tab-line' }}{{ active_class }}"> | |
<a href="#{{ item['name']|clean_id }}" tabindex="0" aria-controls="{{ item.counter }}" role="tab" data-toggle="tab" data-value="{{ item['name'] }}" class="{{ class }}"> | |
{{item['name']}} </a> | |
{% for sub in item['sub'] %} | |
{% if sub is not empty and loop.first %} | |
<i class="fa fa-caret-down"></i> | |
{% endif %} | |
{% endfor %} | |
<ul class="dropdown-submenu" role="tablist"> | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<li role="presentation" class="childLevel-1 padding-top0 {{ active_class }}"> | |
<a href="#{{ sub['name']|clean_id }}" tabindex="0" aria-controls="{{ item.counter }}" role="tab" data-toggle="tab" data-value="{{ sub['name'] }}" style="cursor: pointer;" class="{{ class }}"> | |
{{sub['name']}}</a></li> | |
{% endif %} | |
{% endfor %} | |
</ul> | |
</li> | |
{% endfor %} | |
</ul> | |
</div> | |
</div> | |
</div> | |
<!-- End hollywood-tab dropdown menu, taxonomy terms--> | |
<!-- Begin editor UI --> | |
<div class="row" id="hollywood"> | |
<div class="tab-content"> | |
{% for item in downtown_menu %} | |
{% if loop.index == 1 %} | |
<div class="tab-pane active fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_about_content_items %} | |
{% for parag_id in node.field_tab_about_content_items.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 1 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_1', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
{% for item in downtown_menu %} | |
{% if loop.index == 2 %} | |
<div class="tab-pane fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_plan_content_items %} | |
{% for parag_id in node.field_tab_plan_content_items.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 2 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_2', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
{% for item in downtown_menu %} | |
{% if loop.index == 3 %} | |
<div class="tab-pane fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_map_content_items %} | |
{% for parag_id in node.field_tab_map_content_items.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 3 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_3', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
{% for item in downtown_menu %} | |
{% if loop.index == 4 %} | |
<div class="tab-pane fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_resources_content_item %} | |
{% for parag_id in node.field_tab_resources_content_item.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 4 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_4', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
{% for item in downtown_menu %} | |
{% if loop.index == 5 %} | |
<div class="tab-pane fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_event_content_items %} | |
{% for parag_id in node.field_tab_event_content_items.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 5 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_5', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
{% for item in downtown_menu %} | |
{% if loop.index == 6 %} | |
<div class="tab-pane fade in row padding-left0" id="{{ item['name']|clean_class }}"> | |
{% endif %} | |
{% endfor %} | |
{% if node.field_tab_contact_content_items %} | |
{% for parag_id in node.field_tab_contact_content_items.value %} | |
{{ bamboo_render_entity('paragraph', parag_id['target_id']) }} | |
{% endfor %} | |
{% endif %} | |
</div> | |
{% for item in downtown_menu %} | |
{% if loop.index == 6 %} | |
{% for sub in item['sub'] %} | |
{% if sub is not empty %} | |
<div class="tab-pane fade in row" id="{{ sub['name']|clean_class }}"> | |
{% set submenu_content = drupal_field('field_submenu_content_order_6', 'node') %} | |
{% if loop.index == 1 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.0 }} | |
{% endif %} | |
{% if loop.index == 2 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.1 }} | |
{% endif %} | |
{% if loop.index == 3 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.2 }} | |
{% endif %} | |
{% if loop.index == 4 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.3 }} | |
{% endif %} | |
{% if loop.index == 5 %} | |
<h3>{{ sub['name'] }}</h3> | |
{{ submenu_content.4 }} | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endfor %} | |
{% endif %} | |
{% endfor %} | |
</div> | |
</div> | |
</div> | |
<!-- //End Left-side bar --> | |
<!-- Right-side bar --> | |
<div class="col-md-3 sidebar-menu hidden-sm hidden-xs"> | |
<div class="top-bar"></div> | |
{{ page.side_menu }} | |
</div> | |
<!-- //End Right-side bar --> | |
<!-- //End container --> | |
{# breakpoint() #} | |
{% for item in full_width_data %} | |
{% if item.flag %} | |
<div class="clear full-width-content {% if item.para_id == 122 %} block-qoute-wrapper {% endif %}"> | |
{# full width content goes here #} | |
{{ bamboo_render_entity('paragraph', item.para_id) }} | |
</div> | |
{% else %} | |
{# small width content goes here #} | |
<div class="container"> | |
<div class="row cms-fullwidth"> | |
<div class="section-content clear"> | |
{{ bamboo_render_entity('paragraph', item.para_id) }} | |
</div> | |
</div> | |
{% endif %} | |
{% endfor %} | |
</div> | |
</div> | |
</div> | |
{{ attach_library('cpv3/cpu') }} | |
<!-- footer section --> | |
{% include directory ~ '/partials/footer.html.twig' %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// @file src/taxterm_subs/Service/SubTerms.php | |
namespace Drupal\taxterm_subs\Service; | |
//namespace Drupal\taxterm_subs\SubtermsTraits; | |
//namespace Drupal\taxterm_subs\Traits; | |
//require_once DRUPAL_ROOT . '/modules/custom/taxterm_subs/src/SubtermsTrait/SubtermsTrait.php'; | |
//require_once 'SubtermsTrait.php'; | |
/** | |
SubtermsTrait | |
*/ | |
trait SubtermsTrait { | |
public function subterms(&$vid=('westside_community_plan_update')) { | |
$terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid, 0); | |
if (!empty($terms)) { | |
foreach ($terms as $term) { | |
$children = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid, $term->tid, 2); | |
if (empty($children)) { | |
// no child | |
if ($term->parents[0] == 0) | |
$tax_tree[$term->tid] = [ | |
'tid' => $term->tid, | |
'name' => $term->name, | |
]; | |
} else { | |
$tax_tree[$term->tid] = [ | |
'tid' => $term->tid, | |
'name' => $term->name, | |
]; | |
} | |
foreach ($children as $child) { | |
$tax_tree[$term->tid]['sub'][$child->tid] = [ | |
'tid' => $child->tid, | |
'name' => $child->name, | |
]; | |
} | |
} | |
} | |
return $tax_tree; | |
} | |
} | |
/** | |
* The SubTerms service. Loads child taxonomy terms for submenus here to keep theme file tidy. | |
*/ | |
class SubTerms { | |
use SubtermsTrait; | |
public function createSubtermsBhes(&$terms=array(), &$tax_tree=array(), &$vid=('boyle_heights_cpu_menu_es')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['bhspan_menu'] = \Drupal::service('term_subs')->createSubtermsBhes(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsBoyleHeights(&$terms=array(), &$tax_tree=array(), &$vid=('boyle_heights_cpu')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['boyleheights_menu'] = \Drupal::service('term_subs')->createSubtermsBoyleHeights(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsHarbor(&$terms=array(), &$tax_tree=array(), &$vid=('harbor_menu')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['harborplans_menu'] = \Drupal::service('term_subs')->createSubtermsHarbor(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsWestside(&$terms=array(), &$tax_tree=array(), &$vid=('westside_community_plan_update')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['westside_menu'] = \Drupal::service('term_subs')->createSubtermsWestside(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsSouthEast(&$terms=array(), &$tax_tree=array(), &$vid=('southeast_valley_menu')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['sevplans_menu'] = \Drupal::service('term_subs')->createSubtermsSouthEast(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsSouthWest(&$terms=array(), &$tax_tree=array(), &$vid=('southwest_valley_community_plan_')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['swvalley_menu'] = \Drupal::service('term_subs')->createSubtermsSouthWest(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsDowntown(&$terms=array(), &$tax_tree=array(), &$vid=('downtown_community_plan_update')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['downtown_menu'] = \Drupal::service('term_subs')->createSubtermsDowntown(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsGeneral(&$terms=array(), &$tax_tree=array(), &$vid=('gerneral_plan_update')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['general_menu'] = \Drupal::service('term_subs')->createSubtermsGeneral(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsHollywood(&$terms=array(), &$tax_tree=array(), &$vid=('hollywood_community_plan')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['hollywood_menu'] = \Drupal::service('term_subs')->createSubtermsHollywood(); | |
**/ | |
return $this->subterms($vid); | |
} | |
public function createSubtermsVenice(&$terms=array(), &$tax_tree=array(), &$vid=('venice_local_coastal_program')) { | |
$this->subterms(); | |
/** place in theme file: | |
* $variables['venice_menu'] = \Drupal::service('term_subs')->createSubtermsVenice(); | |
**/ | |
return $this->subterms($vid); | |
} | |
// public function createSubtermsHousing(&$terms=array(), &$tax_tree=array(), &$vid=('housing_element_update')) { | |
// $this->subterms(); | |
/** place in theme file: | |
* $variables['housing_menu'] = \Drupal::service('term_subs')->createSubtermsHousing(); | |
**/ | |
// return $this->subterms($vid); | |
// } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: 'taxterm_subs' | |
type: module | |
description: 'code for generating child terms as dropdown menu' | |
core: 8.x | |
package: 'Custom' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
term_subs: | |
class: '\Drupal\taxterm_subs\Service\SubTerms' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Drupal\node\Entity\Node; | |
use Drupal\image\Entity\ImageStyle; | |
use Drupal\taxonomy\Entity\Term; | |
use Drupal\taxterm_subs\SubTerms; | |
function theme_preprocess_page(&$variables) | |
{ | |
// Boyle Heights | |
cpuMenuBH($variables); | |
// Harbor | |
cpuMenuHarbor($variables); | |
// Westside | |
cpuMenuWestside($variables); | |
// SouthEast | |
cpuMenuSouthEast($variables); | |
// SouthWest Menu | |
cpuMenuSouthWest($variables); | |
// Downtown | |
cpuMenuDowntown($variables); | |
// General Plan | |
cpuMenuGeneral($variables); | |
// hollywood_menu | |
cpuMenuHollywood($variables); | |
// Venice | |
cpuMenuVenice($variables); | |
// housing_menu | |
//cpuMenuHousing($variables); | |
// CPU SPANISH TABBED MENUS // | |
// Boyle Heights | |
cpuMenuBHES($variables); | |
} | |
/** CPU SubMenus Drupal Service**/ | |
/** Boyle Heights Spanish **/ | |
function cpuMenuBHES(&$variables) { | |
$variables['bhspan_menu'] = \Drupal::service('term_subs')->createSubtermsBhes(); | |
} | |
/** Boyle Heights English **/ | |
function cpuMenuBH(&$variables) { | |
$variables['boyleheights_menu'] = \Drupal::service('term_subs')->createSubtermsBoyleHeights(); | |
} | |
/** Harbor **/ | |
function cpuMenuHarbor(&$variables) { | |
$variables['harborplans_menu'] = \Drupal::service('term_subs')->createSubtermsHarbor(); | |
} | |
/** Westside **/ | |
function cpuMenuWestside(&$variables) { | |
$variables['westside_menu'] = \Drupal::service('term_subs')->createSubtermsWestside(); | |
} | |
/** SouthEAST **/ | |
function cpuMenuSouthEast(&$variables) { | |
$variables['sevplans_menu'] = \Drupal::service('term_subs')->createSubtermsSouthEast(); | |
} | |
/** SouthWEST **/ | |
function cpuMenuSouthWest(&$variables) { | |
$variables['swvalley_menu'] = \Drupal::service('term_subs')->createSubtermsSouthWest(); | |
} | |
/** Downtown **/ | |
function cpuMenuDowntown(&$variables) { | |
$variables['downtown_menu'] = \Drupal::service('term_subs')->createSubtermsDowntown(); | |
} | |
/** General **/ | |
function cpuMenuGeneral(&$variables) { | |
$variables['general_menu'] = \Drupal::service('term_subs')->createSubtermsGeneral(); | |
} | |
/** Hollywood **/ | |
function cpuMenuHollywood(&$variables) { | |
$variables['hollywood_menu'] = \Drupal::service('term_subs')->createSubtermsHollywood(); | |
} | |
/** Venice **/ | |
function cpuMenuVenice(&$variables) { | |
$variables['venice_menu'] = \Drupal::service('term_subs')->createSubtermsVenice(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This service takes a taxonomy hierarchy (parent > child) and makes a dropdown menu from the child terms. It uses php traits to re-purpose code and passes by reference variables to populate 10 different vocabularies for 10 different 'mini' sites within a larger site.