Project

General

Profile

« Previous | Next » 

Revision c651d3b1

Added by Andreas Kohlbecker about 8 years ago

#2393 further refactoring of feature block code and at the same time solving the named ticket

View differences:

modules/cdm_dataportal/includes/descriptions.inc
377 377
 * @param $element_markup
378 378
 * @param $footnote_list_key_suggestion
379 379
 */
380
function compose_description_element($element, $feature_block_settings, $element_markup, $footnote_list_key_suggestion)
380
function compose_description_element($element, $feature_block_settings, $element_markup, $footnote_list_key_suggestion, $prepend_feature_label = FALSE)
381 381
{
382 382

  
383 383
  $render_array = array(
......
412 412
    $source_references_markup = '<span class="sources">' . join(' ', $annotations_and_sources['source_references']) . '<span>';
413 413
  }
414 414

  
415
  $render_array['#value'] = $names_used_in_source_markup . $element_markup . $source_references_markup;
415
  $feature_label = '';
416
  if ($prepend_feature_label) {
417
    $feature_label = '<span class="nested-feature-tree-feature-label">' . $element->feature->representation_L10n . ':</span> ';
418
  }
419
  $render_array['#value'] = $feature_label . $names_used_in_source_markup . $element_markup . $source_references_markup;
416 420
  $render_array['#value_suffix'] = $annotations_and_sources['foot_note_keys'];
417 421

  
418 422
  return $render_array;
......
572 576
    foreach ($mergedFeatureNodes as $node) {
573 577

  
574 578
      if ((isset($node->descriptionElements['#type']) ||
575
          has_feature_node_description_elements($node)) && $node->feature->uuid != UUID_IMAGE) { // skip empty or supressed features
579
          has_feature_node_description_elements($node)) && $node->feature->uuid != UUID_IMAGE) { // skip empty or suppressed features
576 580

  
577 581
        $feature_name = cdm_term_representation($node->feature, 'Unnamed Feature');
578 582
        $feature_block_settings = get_feature_block_settings($node->feature->uuid);
......
580 584
        $block = feature_block($feature_name, $node->feature);
581 585
        $block->content = array();
582 586
        $block_content_is_empty = TRUE;
583
        $block_content_weight = 0;
584 587

  
585 588
        /*
586 589
         * Content/DISTRIBUTION.
......
611 614
        else {
612 615

  
613 616
          $media_list = array();
614
          $out_child_elements = '';
617
          $elements_render_array = array();
618
          $child_elements_render_array = null;
615 619

  
616
          if (isset($node->descriptionElements)) {
620
          if (isset($node->descriptionElements[0])) {
617 621
            $elements_render_array = compose_feature_block_items_generic($node->descriptionElements, $node->feature);
618
            $block_content_is_empty = empty($elements_render_array);
619
            $block->content[] = $elements_render_array;
620 622
          }
621 623

  
622 624
          // Content/ALL OTHER FEATURES/Subordinate Features
623 625
          // subordinate features are printed inline in one floating text,
624 626
          // it is expected hat subordinate features can "contain" TextData,
625
          // Qualitative- and Qualitative- DescriptioneElements
627
          // Qualitative- and Qualitative- DescriptionElements
626 628
          if (isset($node->childNodes[0])) {
627

  
628
            // TODO support more than one level of children.
629
            // can this be solved by recursively calling this function?
630
            // @see http://dev.e-taxonomy.eu/trac/ticket/2393
631
            $text = '';
632
            foreach ($node->childNodes as $child) {
633

  
634
              if (isset($child->descriptionElements) && is_array($child->descriptionElements)) {
635
                foreach ($child->descriptionElements as $element) {
636

  
637
                  //TODO it would be better if we could use compose_feature_block_items_generic() directly instead of the below stuff
638

  
639
                  if (is_array($element->media)) {
640
                    // Append media of subordinate elements to list of main
641
                    // feature.
642
                    $media_list = array_merge($media_list, $element->media);
643
                  }
644

  
645
                  switch ($element->class) {
646
                    case 'TextData':
647
                      // FIXME use compose_description_element_text_data()
648
                      if(isset($element->multilanguageText_L10n->text)){
649
                        $out_child_elements = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
650
                      }
651
                      $out_child_elements = str_replace($child->feature->titleCache, '<em>' . $child->feature->representation_L10n . '</em>', $out_child_elements);
652
                      break;
653
                    case 'CategoricalData':
654
                      $out_child_elements  = '<em>' . $child->feature->representation_L10n . '</em> '
655
                        . compose_description_element_categorical_data($element, $feature_block_settings);
656
                      break;
657
                    case 'QuantitativeData':
658
                      $out_child_elements = '<em>' . $child->feature->representation_L10n . '</em> '
659
                        . compose_description_element_quantitative_data($element, $feature_block_settings);
660

  
661
                  }
662

  
663
                }
664
                $text .= " " . $out_child_elements;
665
                $out_child_elements = '';
666
              }
667
            }
668
            $block_content_is_empty = $block_content_is_empty && empty($text);
669
            $block->content[] = markup_to_render_array('<div id="Description" class="feature-block-elements"><div>' . $text . '</div></div>');
670
            $block_content_is_empty = $block_content_is_empty && empty($media_list);
629
            $child_elements_render_array = compose_feature_block_items_nested($node, $media_list, $feature_block_settings);
630
            $elements_render_array = array_merge($elements_render_array, $child_elements_render_array);
631
          }
632
          $block_content_is_empty = $block_content_is_empty && empty($media_list) && empty($elements_render_array);
633
          if(!$block_content_is_empty){
634
            $block->content[] = compose_feature_block_wrap_elements($elements_render_array, $node->feature);
635
            $block->content[] = compose_feature_media_gallery($node, $media_list, $gallery_settings);
636
            /*
637
             * Footnotes for the feature block
638
             */
639
            $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => 'BIBLIOGRAPHY-' . $node->feature->uuid)));
640
            $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => $node->feature->uuid)));
641
            $block->content[] = markup_to_render_array(theme('cdm_annotation_footnotes', array('footnoteListKey' => $node->feature->uuid)));
671 642
          }
672

  
673
          $block->content[] = compose_feature_media_gallery($node, $media_list, $gallery_settings);
674
          /*
675
           * Footnotes for the feature block
676
           */
677
          $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => 'BIBLIOGRAPHY-' . $node->feature->uuid)));
678
          $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => $node->feature->uuid)));
679
          $block->content[] = markup_to_render_array(theme('cdm_annotation_footnotes', array('footnoteListKey' => $node->feature->uuid)));
680 643
        } // END all other features
681 644

  
682 645
        // allows modifying the block contents via a the hook_cdm_feature_node_block_content_alter
......
686 649
          $block_list[] = $block;
687 650
          cdm_toc_list_add_item(cdm_term_representation($node->feature), $node->feature->uuid);
688 651
        } // END: skip empty block content
689
      } // END: skip empty or supressed features
652
      } // END: skip empty or suppressed features
690 653
    } // END: creating a block per feature
691 654

  
692 655
    drupal_alter('cdm_feature_node_blocks', $block_list, $taxon);
......
696 659
    return _block_get_renderable_array($block_list);
697 660
  }
698 661

  
662
/**
663
 * Creates a render array of description elements  held by child nodes of the given feature node.
664
 *
665
 * This function is called recursively!
666
 *
667
 * @param $node
668
 *   The feature node.
669
 * @param array $media_list
670
 *   List of CDM Media entities. All media of subordinate elements should be passed to the main feature.รค
671
 * @param $feature_block_settings
672
 *   The feature block settings.
673
 * @param $main_feature
674
 *  Only used internally in recursive calls.
675
 *
676
 * @return array
677
 *  A Drupal render array
678
 *
679
 * @ingroup compose
680
 */
681
function compose_feature_block_items_nested($node, &$media_list, $feature_block_settings, $main_feature = NULL)
682
{
683

  
684
  if(!$main_feature){
685
    $main_feature = $node->feature;
686
  }
687
  /*
688
   * TODO should be configurable, options; YES, NO, AUTOMATIC
689
   * (automatic will only place the label if the first word of the description element text is not the same)
690
   */
691
  $prepend_feature_label = false;
692

  
693
  $render_arrays = array();
694
  foreach ($node->childNodes as $child_node) {
695
    if (isset($child_node->descriptionElements[0])) {
696
      foreach ($child_node->descriptionElements as $element) {
697

  
698
        if (isset($element->media[0])) {
699
          // Append media of subordinate elements to list of main
700
          // feature.
701
          $media_list = array_merge($media_list, $element->media);
702
        }
703

  
704
        $child_node_element = null;
705
        switch ($element->class) {
706
          case 'TextData':
707
            $child_node_element = compose_description_element_text_data($element, $element->feature->uuid, $feature_block_settings, $prepend_feature_label);
708
            break;
709
          case 'CategoricalData':
710
            $child_node_element = compose_description_element_categorical_data($element, $feature_block_settings, $prepend_feature_label);
711
            break;
712
          case 'QuantitativeData':
713
            $child_node_element = compose_description_element_quantitative_data($element, $feature_block_settings, $prepend_feature_label);
714

  
715
        }
716
        if (is_array($child_node_element)) {
717
          $render_arrays[] = $child_node_element;
718
        }
719
      }
720
    }
721

  
722
    if(isset($child_node->childNodes[0])){
723
      $render_arrays = array_merge($render_arrays, compose_feature_block_items_nested($child_node, $media_list, $feature_block_settings, $main_feature ));
724
    }
725
  }
726

  
727
  return $render_arrays;
728
}
729

  
699 730
  /**
731
   *
700 732
   * @param $node
733
   *  The merged feature three node which potentially contains media in its description elements.
701 734
   * @param $media_list
735
   *    Additional media to be merged witht the media contained in the nodes description elements
702 736
   * @param $gallery_settings
703 737
   * @return array
738
   *
739
   * @ingroup compose
704 740
   */
705 741
  function compose_feature_media_gallery($node, $media_list, $gallery_settings) {
706 742

  
......
779 815

  
780 816
        if (!array_search($repr, $text_data_out_array)) { // de-duplication !!
781 817
          $text_data_out_array[] = $repr;
782
          // TODO HINT: sorting in compose_feature_block_elements will
818
          // TODO HINT: sorting in compose_feature_block_wrap_elements will
783 819
          // not work since this array contains html attributes with uuids
784 820
          // and what is about cases like the bibliography where
785 821
          // any content can be prefixed with some foot-note anchors?
......
792 828

  
793 829

  
794 830
    if ($text_data_out_array && variable_get(DISTRIBUTION_TEXTDATA_DISPLAY_ON_TOP, 0)) {
795
      $block->content[] = compose_feature_block_elements(
831
      $block->content[] = compose_feature_block_wrap_elements(
796 832
        $text_data_out_array, $feature, $text_data_glue, $text_data_sortOutArray
797 833
      );
798 834
    }
......
878 914

  
879 915
      }
880 916
      //
881
      $block->content[] = compose_feature_block_elements(
917
      $block->content[] = compose_feature_block_wrap_elements(
882 918
        $dto_out_array, $feature, $distribution_glue, $distribution_sortOutArray
883 919
      );
884 920
    }
885 921

  
886 922
    // --- TextData at the bottom
887 923
    if ($text_data_out_array && !variable_get(DISTRIBUTION_TEXTDATA_DISPLAY_ON_TOP, 0)) {
888
      $block->content[] = compose_feature_block_elements(
924
      $block->content[] = compose_feature_block_wrap_elements(
889 925
        $text_data_out_array, $feature, $text_data_glue, $text_data_sortOutArray
890 926
      );
891 927
    }
......
904 940
   * @param $element
905 941
   *    The CDM TextData description element.
906 942
   *  @param $feature_uuid
943
   * @param bool $prepend_feature_label
944
   *   Used in nested feature trees to put the feature as label in front of the description element text representation.
907 945
   *
908 946
   * @return array
909 947
   *   A drupal render array with the following elements being used:
......
915 953
   *
916 954
   * @ingroup compose
917 955
   */
918
  function compose_description_element_text_data($element, $feature_uuid, $feature_block_settings) {
956
  function compose_description_element_text_data($element, $feature_uuid, $feature_block_settings, $prepend_feature_label = FALSE) {
919 957

  
920 958
    $footnote_list_key_suggestion = $feature_uuid;
921 959

  
922
    /*
923
    // FIXME remove this hack ---------------------------
924
    $default_theme = variable_get('theme_default', NULL);
925
    if($default_theme == 'garland_cichorieae' || $default_theme == 'cyprus'
926
      || $default_theme == 'flore_afrique_centrale' || $default_theme == 'flora_malesiana' || $default_theme == 'flore_gabon' ){
927
      $asListElement = $feature_block_settings['as_list'] == 'ul';
928
    }
929
    // --------------------------------------------------
930
    */
931

  
932 960
    $element_markup = '';
933 961
    if (isset($element->multilanguageText_L10n->text)) {
934 962
      // TODO replacement of \n by <br> should be configurable
935 963
      $element_markup = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
936 964
    }
937 965

  
938
    $render_array = compose_description_element($element, $feature_block_settings, $element_markup, $footnote_list_key_suggestion);
966
    $render_array = compose_description_element($element, $feature_block_settings, $element_markup, $footnote_list_key_suggestion, $prepend_feature_label);
939 967

  
940 968
    return $render_array;
941 969
  }
......
1005 1033
 * Renders a single instance of the type CategoricalData.
1006 1034
 *
1007 1035
 * @param $element
1008
 *  The CDM CategoricalData entity#
1036
 *  The CDM CategoricalData entity
1037
 *
1009 1038
 * @param $feature_block_settings
1010 1039
 *
1040
 * @param bool $prepend_feature_label
1041
 *   Used in nested feature trees to put the feature as label in front of the description element text representation.
1042
 *
1011 1043
 * @return string
1012 1044
 *   a html representation of the given CategoricalData element
1013 1045
 *
1014 1046
 * @ingroup compose
1015 1047
 */
1016
function compose_description_element_categorical_data($element, $feature_block_settings) {
1048
function compose_description_element_categorical_data($element, $feature_block_settings, $prepend_feature_label = FALSE) {
1017 1049

  
1018 1050
  $enclosing_tag = cdm_feature_block_element_tag_name($feature_block_settings);
1019 1051

  
......
1040 1072

  
1041 1073
  $out = '<span class="' . html_class_attribute_ref($element) . '">' . implode(', ', $state_data_strings) . '</span>';
1042 1074

  
1043
  $render_array = compose_description_element($element, $feature_block_settings, $out, $element->feature->uuid);
1075
  $render_array = compose_description_element($element, $feature_block_settings, $out, $element->feature->uuid, $prepend_feature_label);
1044 1076

  
1045 1077
  return $render_array;
1046 1078
}
......
1063 1095
 * Special cases;
1064 1096
 * 1. Min==Max: this will be interpreted as Average
1065 1097
 *
1066
 * @param array $variables
1067
 *   An associative array containing:
1068
 *    - element: the QuantitativeData element
1098
 * @param $element
1099
 *  The CDM QuantitativeData entity
1100
 *
1101
 * @param $feature_block_settings
1102
 *
1103
 * @param bool $prepend_feature_label
1104
 *   Used in nested feature trees to put the feature as label in front of the description element text representation.
1105
 *
1069 1106
 *
1070 1107
 * @return string
1071 1108
 *   a html representation of the given QuantitativeData element
1072 1109
 *
1073 1110
 * @ingroup themeable
1074 1111
 */
1075
function compose_description_element_quantitative_data($element, $feature_block_settings) {
1112
function compose_description_element_quantitative_data($element, $feature_block_settings, $prepend_feature_label = FALSE) {
1076 1113
  /*
1077 1114
   * - statisticalValues
1078 1115
   *   - value
......
1151 1188
    $out = $element->modifyingText_L10n . ' ' . $out;
1152 1189
  }
1153 1190

  
1154
  $render_array = compose_description_element($element, $feature_block_settings, $out, $element->feature->uuid);
1191
  $render_array = compose_description_element($element, $feature_block_settings, $out, $element->feature->uuid, $prepend_feature_label);
1155 1192

  
1156 1193
  return $render_array;
1157 1194
}
1158 1195

  
1159 1196

  
1160 1197
/**
1161
 * Creates a render array for string representations of description elements for the given feature.
1198
 * Wraps the render array for the given feature into an enclosing html tag.
1162 1199
 *
1163
 * @param array $elements
1200
 * Optionally the elements can be sorted and glued together by a separator string.
1201
 *
1202
 * @param array $description_element_render_arrays
1164 1203
 *   An list of render arrays. Which are usually are produced by the compose_description_element()
1165 1204
 *   function. The render arrays should be of #type=html_tag, so that they can understand the #attribute property.
1166 1205
 * @param  $feature :
......
1170 1209
 * @param bool $sort
1171 1210
 *   Boolean Whether to sort the $elements alphabetically, default is FALSE
1172 1211
 *
1173
 * @return array|void
1212
 * @return array
1213
 *    A Drupal render array
1174 1214
 *
1175 1215
 * @ingroup compose
1176 1216
 */
1177
  function compose_feature_block_elements(array $elements, $feature, $glue = '', $sort = FALSE)
1217
  function compose_feature_block_wrap_elements(array $description_element_render_arrays, $feature, $glue = '', $sort = FALSE)
1178 1218
  {
1179 1219

  
1180 1220
    $feature_block_settings = get_feature_block_settings($feature->uuid);
1181 1221
    $enclosing_tag = $feature_block_settings['as_list'];
1182 1222

  
1183 1223
    if ($sort) { // TODO remove parameter and replace by $feature_block_settings['sort_elements']
1184
      usort($elements, 'compare_description_element_render_arrays');
1224
      usort($description_element_render_arrays, 'compare_description_element_render_arrays');
1185 1225
    }
1186 1226

  
1187 1227
    $is_first = true;
1188
    foreach($elements as &$element_render_array){
1228
    foreach($description_element_render_arrays as &$element_render_array){
1189 1229
      if(!is_array($element_render_array)){
1190 1230
        $element_render_array = markup_to_render_array($element_render_array);
1191 1231
      }
......
1202 1242
      $is_first = false;
1203 1243
    }
1204 1244

  
1205
    $render_array['elements']['children'] = $elements;
1245
    $render_array['elements']['children'] = $description_element_render_arrays;
1206 1246

  
1207 1247
    $render_array['elements']['#prefix'] = '<' . $enclosing_tag . ' class="feature-block-elements" id="' . $feature->representation_L10n . '">';
1208 1248
    $render_array['elements']['#suffix'] = '</' . $enclosing_tag . '>';
......
1284 1324
   *
1285 1325
   * Usually these are of a specific feature type.
1286 1326
   *
1287
   * @param $descriptionElements
1327
   * @param $description_elements
1288 1328
   *   array of descriptionElements which belong to the same feature.
1289 1329
   *   These descriptions elements of a Description must be ordered by the chosen feature tree by
1290 1330
   *   calling the function _mergeFeatureTreeDescriptions().
......
1298 1338
   *
1299 1339
   * @ingroup compose
1300 1340
   */
1301
  function compose_feature_block_items_generic($descriptionElements, $feature) {
1341
  function compose_feature_block_items_generic($description_elements, $feature) {
1302 1342

  
1303
    $render_array = array();
1304 1343
    $elements_out_array = array();
1305 1344
    $distribution_tree = null;
1306 1345

  
......
1312 1351
     */
1313 1352
    $feature_block_has_content = false;
1314 1353

  
1315
    RenderHints::pushToRenderStack($feature->uuid);
1316

  
1317
    if (is_array($descriptionElements)) {
1318
      foreach ($descriptionElements as $descriptionElement) {
1354
    if (is_array($description_elements)) {
1355
      foreach ($description_elements as $description_element) {
1319 1356
          /* decide based on the description element class
1320 1357
           *
1321 1358
           * Features handled here:
......
1323 1360
           *
1324 1361
           * TODO provide api_hook as extension point for this?
1325 1362
           */
1326
        $feature_block_settings = get_feature_block_settings($descriptionElement->feature->uuid);
1327
        switch ($descriptionElement->class) {
1363
        $feature_block_settings = get_feature_block_settings($description_element->feature->uuid);
1364
        switch ($description_element->class) {
1328 1365
          case 'TextData':
1329
            $elements_out_array[] = compose_description_element_text_data($descriptionElement, $descriptionElement->feature->uuid, $feature_block_settings);
1366
            $elements_out_array[] = compose_description_element_text_data($description_element, $description_element->feature->uuid, $feature_block_settings);
1330 1367
            break;
1331 1368
          case 'CategoricalData':
1332
            $elements_out_array[] = compose_description_element_categorical_data($descriptionElement, $feature_block_settings);
1369
            $elements_out_array[] = compose_description_element_categorical_data($description_element, $feature_block_settings);
1333 1370
            break;
1334 1371
          case 'QuantitativeData':
1335
            $elements_out_array[] = compose_description_element_quantitative_data($descriptionElement, $feature_block_settings);
1372
            $elements_out_array[] = compose_description_element_quantitative_data($description_element, $feature_block_settings);
1336 1373
            break;
1337 1374
          case 'IndividualsAssociation':
1338
            $elements_out_array[] = compose_description_element_individuals_association($descriptionElement, $feature_block_settings);
1375
            $elements_out_array[] = compose_description_element_individuals_association($description_element, $feature_block_settings);
1339 1376
            break;
1340 1377
          case 'TaxonInteraction':
1341
            $elements_out_array[] = compose_description_element_taxon_interaction($descriptionElement, $feature_block_settings);
1378
            $elements_out_array[] = compose_description_element_taxon_interaction($description_element, $feature_block_settings);
1342 1379
            break;
1343 1380
          case 'Uses':
1344 1381
            /* IGNORE Uses classes, these are handled completely in theme_cdm_UseDescription */
1345 1382
            break;
1346 1383
          default:
1347 1384
            $feature_block_has_content = true;
1348
            $elements_out_array[] = markup_to_render_array('<li>No method for rendering unknown description class: ' . $descriptionElement->class . '</li>');
1385
            $elements_out_array[] = markup_to_render_array('<li>No method for rendering unknown description class: ' . $description_element->class . '</li>');
1349 1386
        }
1350 1387
        $elements_out_array_last_item = $elements_out_array[count($elements_out_array) - 1];
1351 1388
        // considering not empty as long as the last item added is a render array
......
1354 1391

  
1355 1392
      // If feature = CITATION sort the list of sources.
1356 1393
      // This is ONLY for FLORA MALESIANA and FLORE d'AFRIQUE CENTRALE.
1357
      if (isset($descriptionElement) && $descriptionElement->feature->uuid == UUID_CITATION) {
1394
      if (isset($description_element) && $description_element->feature->uuid == UUID_CITATION) {
1358 1395
        sort($elements_out_array);
1359 1396
      }
1360 1397
    }
1361 1398

  
1362
    if($feature_block_has_content){
1363
      $render_array = compose_feature_block_elements(
1364
        $elements_out_array, $feature
1365
      );
1366
    }
1367

  
1368
    RenderHints::popFromRenderStack();
1369
    return $render_array;
1399
    return $elements_out_array;
1370 1400
  }
1371 1401

  
1372 1402
/**
......
1449 1479
    } // End of loop over set of elements per language area
1450 1480

  
1451 1481

  
1452
    $common_name_feature_elements_render_array = compose_feature_block_elements(
1482
    $common_name_feature_elements_render_array = compose_feature_block_wrap_elements(
1453 1483
      $common_name_feature_elements, $feature, '; ', FALSE
1454 1484
    );
1455 1485
    $common_name_out .= drupal_render($common_name_feature_elements_render_array); // FIXME should this be a render array instead?
......
1467 1497
    $text_data_out[] = drupal_render($text_data_render_array);
1468 1498
  }
1469 1499

  
1470
  $common_name_out_text_data = compose_feature_block_elements(
1500
  $common_name_out_text_data = compose_feature_block_wrap_elements(
1471 1501
    $text_data_out, $feature
1472 1502
  );
1473 1503

  

Also available in: Unified diff