diff core/lib/Drupal/Core/Render/Element.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/lib/Drupal/Core/Render/Element.php	Wed Nov 29 16:09:58 2017 +0000
@@ -0,0 +1,202 @@
+<?php
+
+namespace Drupal\Core\Render;
+
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Access\AccessResultInterface;
+
+/**
+ * Provides helper methods for Drupal render elements.
+ *
+ * @see \Drupal\Core\Render\Element\ElementInterface
+ *
+ * @ingroup theme_render
+ */
+class Element {
+
+  /**
+   * Checks if the key is a property.
+   *
+   * @param string $key
+   *   The key to check.
+   *
+   * @return bool
+   *   TRUE of the key is a property, FALSE otherwise.
+   */
+  public static function property($key) {
+    return $key[0] == '#';
+  }
+
+  /**
+   * Gets properties of a structured array element (keys beginning with '#').
+   *
+   * @param array $element
+   *   An element array to return properties for.
+   *
+   * @return array
+   *   An array of property keys for the element.
+   */
+  public static function properties(array $element) {
+    return array_filter(array_keys($element), 'static::property');
+  }
+
+  /**
+   * Checks if the key is a child.
+   *
+   * @param string $key
+   *   The key to check.
+   *
+   * @return bool
+   *   TRUE if the element is a child, FALSE otherwise.
+   */
+  public static function child($key) {
+    return !isset($key[0]) || $key[0] != '#';
+  }
+
+  /**
+   * Identifies the children of an element array, optionally sorted by weight.
+   *
+   * The children of a element array are those key/value pairs whose key does
+   * not start with a '#'. See drupal_render() for details.
+   *
+   * @param array $elements
+   *   The element array whose children are to be identified. Passed by
+   *   reference.
+   * @param bool $sort
+   *   Boolean to indicate whether the children should be sorted by weight.
+   *
+   * @return array
+   *   The array keys of the element's children.
+   */
+  public static function children(array &$elements, $sort = FALSE) {
+    // Do not attempt to sort elements which have already been sorted.
+    $sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort;
+
+    // Filter out properties from the element, leaving only children.
+    $count = count($elements);
+    $child_weights = [];
+    $i = 0;
+    $sortable = FALSE;
+    foreach ($elements as $key => $value) {
+      if ($key === '' || $key[0] !== '#') {
+        if (is_array($value)) {
+          if (isset($value['#weight'])) {
+            $weight = $value['#weight'];
+            $sortable = TRUE;
+          }
+          else {
+            $weight = 0;
+          }
+          // Supports weight with up to three digit precision and conserve
+          // the insertion order.
+          $child_weights[$key] = floor($weight * 1000) + $i / $count;
+        }
+        // Only trigger an error if the value is not null.
+        // @see https://www.drupal.org/node/1283892
+        elseif (isset($value)) {
+          trigger_error(SafeMarkup::format('"@key" is an invalid render array key', ['@key' => $key]), E_USER_ERROR);
+        }
+      }
+      $i++;
+    }
+
+    // Sort the children if necessary.
+    if ($sort && $sortable) {
+      asort($child_weights);
+      // Put the sorted children back into $elements in the correct order, to
+      // preserve sorting if the same element is passed through
+      // \Drupal\Core\Render\Element::children() twice.
+      foreach ($child_weights as $key => $weight) {
+        $value = $elements[$key];
+        unset($elements[$key]);
+        $elements[$key] = $value;
+      }
+      $elements['#sorted'] = TRUE;
+    }
+
+    return array_keys($child_weights);
+  }
+
+  /**
+   * Returns the visible children of an element.
+   *
+   * @param array $elements
+   *   The parent element.
+   *
+   * @return array
+   *   The array keys of the element's visible children.
+   */
+  public static function getVisibleChildren(array $elements) {
+    $visible_children = [];
+
+    foreach (static::children($elements) as $key) {
+      $child = $elements[$key];
+
+      // Skip value and hidden elements, since they are not rendered.
+      if (!static::isVisibleElement($child)) {
+        continue;
+      }
+
+      $visible_children[$key] = $child;
+    }
+
+    return array_keys($visible_children);
+  }
+
+  /**
+   * Determines if an element is visible.
+   *
+   * @param array $element
+   *   The element to check for visibility.
+   *
+   * @return bool
+   *   TRUE if the element is visible, otherwise FALSE.
+   */
+  public static function isVisibleElement($element) {
+    return (!isset($element['#type']) || !in_array($element['#type'], ['value', 'hidden', 'token']))
+      && (!isset($element['#access'])
+      || (($element['#access'] instanceof AccessResultInterface && $element['#access']->isAllowed()) || ($element['#access'] === TRUE)));
+  }
+
+  /**
+   * Sets HTML attributes based on element properties.
+   *
+   * @param array $element
+   *   The renderable element to process. Passed by reference.
+   * @param array $map
+   *   An associative array whose keys are element property names and whose
+   *   values are the HTML attribute names to set on the corresponding
+   *   property; e.g., array('#propertyname' => 'attributename'). If both names
+   *   are identical except for the leading '#', then an attribute name value is
+   *   sufficient and no property name needs to be specified.
+   */
+  public static function setAttributes(array &$element, array $map) {
+    foreach ($map as $property => $attribute) {
+      // If the key is numeric, the attribute name needs to be taken over.
+      if (is_int($property)) {
+        $property = '#' . $attribute;
+      }
+      // Do not overwrite already existing attributes.
+      if (isset($element[$property]) && !isset($element['#attributes'][$attribute])) {
+        $element['#attributes'][$attribute] = $element[$property];
+      }
+    }
+  }
+
+  /**
+   * Indicates whether the given element is empty.
+   *
+   * An element that only has #cache set is considered empty, because it will
+   * render to the empty string.
+   *
+   * @param array $elements
+   *   The element.
+   *
+   * @return bool
+   *   Whether the given element is empty.
+   */
+  public static function isEmpty(array $elements) {
+    return empty($elements) || (count($elements) === 1 && array_keys($elements) === ['#cache']);
+  }
+
+}