diff --git a/modules/wsdata_extras/src/Plugin/WSDecoder/WSDecoderJSONList.php b/modules/wsdata_extras/src/Plugin/WSDecoder/WSDecoderJSONList.php new file mode 100644 index 0000000000000000000000000000000000000000..8530cf44ca3ed9e85a6910feec35704ce55fee96 --- /dev/null +++ b/modules/wsdata_extras/src/Plugin/WSDecoder/WSDecoderJSONList.php @@ -0,0 +1,182 @@ +<?php + +namespace Drupal\wsdata_extras\Plugin\WSDecoder; + +use Drupal\wsdata\Plugin\WSDecoder\WSDecoderJSON; + +/** + * JSON Decoder. + * + * @WSDecoder( + * id = "WSDecoderJSONList", + * label = @Translation("JSON Decoder for list data", context = "WSDecoder"), + * ) + */ +class WSDecoderJSONList extends WSDecoderJSON { + + /** + * Returns help text to display with the key/token select input. + */ + public function getKeyHelpText() { + return $this->t('Use the format markup_wrapper_element/key_1:key_2:..:key_n where markup_wrapper_element is optional (div, p, span, ol, ul) and key elements are separated by : '); + } + + /** + * Retrieve the value for the given data key. + * + * This function retrieves data from $this->data that is, + * in this case, a list or array. + * If defined, $key will select that key from each list item. + * All selected data will be wrapped in markup and concatenated. + * $key is a string, with the format "markup_element/foo:bar" + * where markup_element suggests markup to wrap the items, + * and the character ':' delimiting the parts of the key. + * Valid markup elements are: div, ol, ul, span, p. + * I.E. The key div/foo:bar will retrieve $this->data[*]['foo']['bar'] + * and wrap each item in a <div> element. + * + * @param string $key + * Optional - Data key to load. + * @param string $lang + * Optional - Language key. + * + * @return mixed + * Returns the requested data, FALSE otherwise. + */ + public function getData($key = NULL, $lang = NULL) { + if (!is_array($this->data)) { + return $this->data; + } + + $return_data = FALSE; + // Paths to load data from. + $paths = []; + + // Default markup element for flattening. + $markup_element = 'div'; + + // Split out the key from the markup element. + $key_components = explode('/', $key); + if (count($key_components) > 1) { + // Markup element specified. + $markup_element = $key_components[0]; + $key = $key_components[1]; + } + else { + // No markup element specified. + $key = $key_components[0]; + } + + // First, see if we want a specific language. + if ($this->languages) { + if (!is_null($lang) and array_key_exists($lang, $this->data)) { + $paths[$lang] = !empty($key) ? $lang . ':' . $key : $lang; + } + else { + foreach ($this->languages as $lang) { + $paths[$lang] = !empty($key) ? $lang . ':' . $key : $lang; + } + } + } + else { + if (!empty($key)) { + $paths[$key] = $key; + } + } + + // Simplest case, return all data. + if (empty($paths)) { + return '<div>' . implode('</div><div>', $this->data) . '</div>'; + } + + // Second simplest case, one specific value. + if (!empty($paths[$key])) { + $location = explode(':', $paths[$key]); + $return_data = []; + // Loop through the data array and select key from each. + foreach ($this->data as $item_data) { + foreach ($location as $l) { + if (isset($item_data[$l])) { + $item_data = $item_data[$l]; + } + else { + $item_data = FALSE; + } + } + // Add selected data to output array. + $return_data[] = $item_data; + } + // Wrap all selected data items in markup and return. + return $this->flatten($return_data, $markup_element); + } + + // Third case, one specific value in a given language. + if (!empty($paths[$lang]) and count($paths) == 1) { + $location = explode(':', $paths[$lang]); + foreach ($location as $l) { + if (isset($return_data[$l])) { + $return_data = $return_data[$l]; + } + else { + $return_data = FALSE; + } + } + // Language specific data is always keyed by the language. + $return_data[$lang] = $return_data; + return $return_data; + } + + // Lastly, the complicated case. Keyed value for all languages. + if ($this->languages and count($paths) > 1) { + $keyed_data = []; + foreach ($paths as $p => $path) { + // Reset return data. + $return_data = $this->data; + $location = explode(':', $path); + foreach ($location as $l) { + if (isset($return_data[$l])) { + $return_data = $return_data[$l]; + } + else { + $return_data = FALSE; + } + } + $keyed_data[$p] = $return_data; + } + + // Finally, put the keyed data back into the return data. + return $keyed_data; + } + } + + /** + * Takes an array of items and flattens it to a single string + * using a suggested markup element to wrap the items. + * + * @param array $items + * The array of items. + * @param string $markup_element + * The markup element in which to wrap the items. + * + * @return string + * Returns a flat string with all items. + */ + protected function flatten($items, $markup_element) { + $flat = ''; + switch ($markup_element) { + case 'ol': + case 'ul': + $flat = '<'.$markup_element.'><li>' . implode('</li><li>', $items) . '</li></'.$markup_element.'>'; + break; + case 'span': + case 'p': + case 'div': + $flat = '<'.$markup_element.'>' . implode('</div><div>', $items) . '</'.$markup_element.'>'; + break; + default: + $flat = '<div>' . implode('</div><div>', $items) . '</div>'; + } + return $flat; + } + +}