diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index 98499b4b90ff62b5ccaf352e0cad569fb3000c63..109535f25e027d8368e2a186bbc37be06fde5de7 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -727,10 +727,13 @@ abstract class AbstractBuildForm {
         $attribute = '';
         $class = 'form-control';
 
-        if (isset($formElement[FE_TYPE_AHEAD_SQL])) {
-            $class .= ' qfq-type-ahead';
-            $dataSip = $this->sip->queryStringToSip(TYPE_AHEAD_SELECT . '=' . $formElement[FE_TYPE_AHEAD_SQL], RETURN_SIP);
-            $attribute .= Support::doAttribute(DATA_SIP, $dataSip);
+        $typeAheadUrlParam = $this->typeAheadBuildParam($formElement);
+        if ($typeAheadUrlParam != '') {
+            $class .= ' ' . CLASS_TYPEAHEAD;
+            $dataSip = $this->sip->queryStringToSip($typeAheadUrlParam, RETURN_SIP);
+            $attribute .= Support::doAttribute(DATA_TYPEAHEAD_SIP, $dataSip);
+            $attribute .= Support::doAttribute(DATA_TYPEAHEAD_LIMIT, $formElement[FE_TYPEAHEAD_LIMIT]);
+            $attribute .= Support::doAttribute(DATA_TYPEAHEAD_MINLENGTH, $formElement[FE_TYPEAHEAD_MINLENGTH]);
         }
 
         $attribute .= Support::doAttribute('id', $formElement[FE_HTML_ID]);
@@ -781,6 +784,47 @@ abstract class AbstractBuildForm {
 
     }
 
+    /**
+     * Check $formElement for FE_TYPE_AHEAD_SQL or FE_TYPE_AHEAD_LDAP_SERVER.
+     * If one of them is given: fill $urlParam.
+     *
+     * @param array $formElement
+     * @return string
+     */
+    private function typeAheadBuildParam(array $formElement) {
+
+        $urlParam = '';
+
+        if (isset($formElement[FE_TYPEAHEAD_SQL])) {
+            $urlParam = FE_TYPEAHEAD_SQL . '=' . $formElement[FE_TYPEAHEAD_SQL];
+        } elseif (isset($formElement[FE_TYPEAHEAD_LDAP_SERVER])) {
+            $formElement[FE_TYPEAHEAD_LDAP_SERVER] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_SERVER);
+            $formElement[FE_TYPEAHEAD_LDAP_BASE_DN] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_BASE_DN);
+            $formElement[FE_TYPEAHEAD_LDAP_SEARCH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_SEARCH);
+            $formElement[FE_TYPEAHEAD_LDAP_VALUE_PRINTF] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_VALUE_PRINTF);
+            $formElement[FE_TYPEAHEAD_LDAP_KEY_PRINTF] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_KEY_PRINTF);
+            $formElement[FE_TYPEAHEAD_LIMIT] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LIMIT, TYPEAHEAD_DEFAULT_LIMIT);
+
+            $arr = [
+                FE_TYPEAHEAD_LDAP_SERVER => $formElement[FE_TYPEAHEAD_LDAP_SERVER],
+                FE_TYPEAHEAD_LDAP_BASE_DN => $formElement[FE_TYPEAHEAD_LDAP_BASE_DN],
+                FE_TYPEAHEAD_LDAP_SEARCH => $formElement[FE_TYPEAHEAD_LDAP_SEARCH],
+                FE_TYPEAHEAD_LDAP_VALUE_PRINTF => $formElement[FE_TYPEAHEAD_LDAP_VALUE_PRINTF],
+                FE_TYPEAHEAD_LDAP_KEY_PRINTF => $formElement[FE_TYPEAHEAD_LDAP_KEY_PRINTF],
+                FE_TYPEAHEAD_LIMIT => $formElement[FE_TYPEAHEAD_LIMIT],
+            ];
+
+            $urlParam = OnArray::toString($arr);
+        }
+
+        if ($urlParam != '') {
+            $formElement[FE_TYPEAHEAD_LIMIT] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LIMIT, TYPEAHEAD_DEFAULT_LIMIT);
+            $formElement[FE_TYPEAHEAD_MINLENGTH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_MINLENGTH, 2);
+        }
+
+        return $urlParam;
+    }
+
     /**
      * Calculates the maxlength of an input field, based on formElement type, formElement user definition and table.field definition.
      *
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index 8b0de6dfaa6a1d7364bf22c88c2cc0fcd2a7b746..4ae06fad2732aaee4d054ec0e1df14c43187df44 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -162,6 +162,7 @@ const ERROR_OVERWRITE_RECORD_ID = 1073;
 const ERROR_MISSING_SLAVE_ID_DEFINITION = 1074;
 const ERROR_MISSING_INTL = 1075;
 const ERROR_HTML_TOKEN_TOO_SHORT = 1076;
+const ERROR_MISSING_PRINTF_ARGUMENTS = 1077;
 
 // Subrecord
 const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100;
@@ -198,6 +199,8 @@ const ERROR_UPLOAD = 1500;
 const ERROR_UNKNOWN_ACTION = 1502;
 const ERROR_NO_TARGET_PATH_FILE_NAME = 1503;
 
+const ERROR_LDAP_CONNECT = 1600;
+
 // KeyValueParser
 const ERROR_KVP_VALUE_HAS_NO_KEY = 1900;
 
@@ -374,15 +377,17 @@ const VAR_SLAVE_ID = ACTION_KEYWORD_SLAVE_ID;
 const VAR_FILENAME = 'filename'; // Original filename of an uploaded file.
 
 
-// Class DB can operate in these modes
+// PHP class DB can operate in these modes
 const MODE_DB_REGULAR = 'regular';
 const MODE_DB_NO_LOG = 'noLog';
 
-// CLASS TypeAhead
-const TYPE_AHEAD_API_QUERY = 'query';  // Name of parameter in API call of typeahead.php?query=...&s=...
-const TYPE_AHEAD_API_SIP = 'sip';  // Name of parameter in API call of typeahead.php?query=...&s=...
-const TYPE_AHEAD_SELECT = 'select'; // Value of FE_TYPE_AHEAD_SQL, stored in a SIP under the name TYPE_AHEAD_SELECT.
-const TYPE_AHEAD_LDAP = 'ldap'; // Value of FE_TYPE_AHEAD_LDAP, stored in a SIP under the name TYPE_AHEAD_LDAP.
+// PHPO class Typeahead
+const TYPEAHEAD_API_QUERY = 'query';  // Name of parameter in API call of typeahead.php?query=...&s=... - See also FE_TYPE_AHEAD_SQL
+const TYPEAHEAD_API_SIP = 'sip';  // Name of parameter in API call of typeahead.php?query=...&s=...
+const TYPEAHEAD_DEFAULT_LIMIT = 20;
+
+const SINGLE_TICK = "'";
+const DOUBLE_TICK = '"';
 
 // TOKEN evaluate
 const TOKEN_ESCAPE_SINGLE_TICK = 's';
@@ -440,18 +445,25 @@ const API_JSON_HIDDEN = 'hidden';
 const API_JSON_DISABLED = 'disabled';
 const API_JSON_REQUIRED = 'required';
 
-const DATA_HIDDEN = 'data-hidden';
-const DATA_DISABLED = 'data-disabled';
-const DATA_REQUIRED = 'data-required';
-
-const DATA_SIP = 'data-sip'; // Used for typeAhead
-
 const API_ANSWER_STATUS_SUCCESS = 'success';
 const API_ANSWER_STATUS_ERROR = 'error';
 const API_ANSWER_REDIRECT_CLIENT = 'client';
 const API_ANSWER_REDIRECT_NO = 'no';
 const API_ANSWER_REDIRECT_URL = 'url';
 
+const API_TYPEAHEAD_KEY = 'key';
+const API_TYPEAHEAD_VALUE = 'value';
+
+const DATA_HIDDEN = 'data-hidden';
+const DATA_DISABLED = 'data-disabled';
+const DATA_REQUIRED = 'data-required';
+
+const DATA_TYPEAHEAD_SIP = 'data-typeahead-sip'; // Used for typeAhead
+const DATA_TYPEAHEAD_LIMIT = 'data-typeahead-limit';
+const DATA_TYPEAHEAD_MINLENGTH = 'data-typeahead-minlength';
+const CLASS_TYPEAHEAD = 'qfq-typeahead';
+
+
 // BuildForm
 const SYMBOL_NEW = 'new';
 const SYMBOL_EDIT = 'edit';
@@ -591,12 +603,18 @@ const FE_TEMPLATE_GROUP_CLASS = 'tgClass';
 const FE_TEMPLATE_GROUP_DEFAULT_MAX_LENGTH = 5;
 const FE_TEMPLATE_GROUP_NAME_PATTERN = '%d';
 const FE_BUTTON_CLASS = 'buttonClass';
-const FE_TYPE_AHEAD_SQL = 'typeAheadSql';
+const FE_TYPEAHEAD_LIMIT = 'typeaheadLimit';
+const FE_TYPEAHEAD_MINLENGTH = 'typeaheadMinLength';
+const FE_TYPEAHEAD_SQL = 'typeAheadSql';
+const FE_TYPEAHEAD_LDAP_SERVER = 'typeAheadLdapServer';
+const FE_TYPEAHEAD_LDAP_BASE_DN = 'typeAheadLdapBaseDn';
+const FE_TYPEAHEAD_LDAP_SEARCH = 'typeAheadLdapSearch';
+const FE_TYPEAHEAD_LDAP_VALUE_PRINTF = 'typeAheadLdapValuePrintf';
+const FE_TYPEAHEAD_LDAP_KEY_PRINTF = 'typeAheadLdapKeyPrintf';
 const RETYPE_FE_NAME_EXTENSION = 'RETYPE';
 
 const FE_HTML_ID = 'htmlId'; // Will be dynamically computed during runtime.
 
-
 // FormElement Types
 const FE_TYPE_UPLOAD = 'upload';
 const FE_TYPE_EXTRA = 'extra';
diff --git a/extension/qfq/qfq/form/TypeAhead.php b/extension/qfq/qfq/form/TypeAhead.php
index d5152d00dc393d678252ce9a2b387048f9500b0b..fc8d032bfb49dafe1d5f2e56f9f5830c519b0aa7 100644
--- a/extension/qfq/qfq/form/TypeAhead.php
+++ b/extension/qfq/qfq/form/TypeAhead.php
@@ -8,12 +8,15 @@
 
 namespace qfq;
 
+use TYPO3\CMS\Core\FormProtection\Exception;
+
 require_once(__DIR__ . '/../store/Sip.php');
 //require_once(__DIR__ . '/store/FillStoreForm.php');
 require_once(__DIR__ . '/../store/Session.php');
 require_once(__DIR__ . '/../Constants.php');
 //require_once(__DIR__ . '/Save.php');
 //require_once(__DIR__ . '/helper/KeyValueStringParser.php');
+require_once(__DIR__ . '/../helper/Ldap.php');
 //require_once(__DIR__ . '/helper/HelperFormElement.php');
 //require_once(__DIR__ . '/exceptions/UserFormException.php');
 //require_once(__DIR__ . '/exceptions/CodeException.php');
@@ -47,12 +50,12 @@ class TypeAhead {
      */
     public function __construct($phpUnit = false) {
 
-        if (!isset($_GET[TYPE_AHEAD_API_QUERY]) || !isset($_GET[TYPE_AHEAD_API_SIP])) {
-            throw new CodeException('Missing GET parameter "' . TYPE_AHEAD_API_SIP . '" or "' . TYPE_AHEAD_API_QUERY . '"');
+        if (!isset($_GET[TYPEAHEAD_API_QUERY]) || !isset($_GET[TYPEAHEAD_API_SIP])) {
+            throw new CodeException('Missing GET parameter "' . TYPEAHEAD_API_SIP . '" or "' . TYPEAHEAD_API_QUERY . '"');
         }
 
-        $this->vars[TYPE_AHEAD_API_QUERY] = $_GET[TYPE_AHEAD_API_QUERY];
-        $this->vars[TYPE_AHEAD_API_SIP] = $_GET[TYPE_AHEAD_API_SIP];
+        $this->vars[TYPEAHEAD_API_QUERY] = $_GET[TYPEAHEAD_API_QUERY];
+        $this->vars[TYPEAHEAD_API_SIP] = $_GET[TYPEAHEAD_API_SIP];
 
         $session = Session::getInstance($phpUnit);
 
@@ -67,25 +70,41 @@ class TypeAhead {
      * @throws UserFormException
      */
     public function process() {
-        //test
+
         $arr = array();
         $values = array();
 
         $sipClass = new Sip();
 
-        $sipVars = $sipClass->getVarsFromSip($this->vars[TYPE_AHEAD_API_SIP]);
+        $sipVars = $sipClass->getVarsFromSip($this->vars[TYPEAHEAD_API_SIP]);
 
-        $query = '%' . $this->vars[TYPE_AHEAD_API_QUERY] . '%';
-        $cnt = substr_count($sipVars[TYPE_AHEAD_SELECT], '?');
-        for ($ii = 0; $ii < $cnt; $ii++) {
-            $values[] = $query;
+        if (isset($sipVars[FE_TYPEAHEAD_SQL])) {
+            $arr = typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
+        } elseif (isset($sipVars[FE_TYPEAHEAD_LDAP_SERVER])) {
+            $ldap = new Ldap();
+            $arr = $ldap->process($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
         }
 
-        if (isset($sipVars[TYPE_AHEAD_SELECT])) {
-            $arr = $this->db->sql($sipVars[TYPE_AHEAD_SELECT], ROW_REGULAR, $values);
+        return $arr;
+    }
+
+    /**
+     * @param array $config
+     * @param $query
+     * @return array|int
+     * @throws CodeException
+     * @throws DbException
+     */
+    private function typeAheadSql(array $config, $query) {
+        $values = array();
+
+        $query = '%' . $query . '%';
+        $cnt = substr_count($config[FE_TYPEAHEAD_SQL], '?');
+        for ($ii = 0; $ii < $cnt; $ii++) {
+            $values[] = $query;
         }
 
-        return $arr;
+        return $this->db->sql($config[FE_TYPEAHEAD_SQL], ROW_REGULAR, $values);
     }
 
 }
\ No newline at end of file
diff --git a/extension/qfq/qfq/helper/KeyValueStringParser.php b/extension/qfq/qfq/helper/KeyValueStringParser.php
index b44f9ab9c46f7b682ebd433e46a51d690f0c8df6..c940cd6ff6e189a701e1e9d5c85e0fee251c00ad 100644
--- a/extension/qfq/qfq/helper/KeyValueStringParser.php
+++ b/extension/qfq/qfq/helper/KeyValueStringParser.php
@@ -147,7 +147,89 @@ class KeyValueStringParser {
         if (in_array($string[0], $quotes) === true && self::isFirstAndLastCharacterIdentical($string)) {
             return substr($string, 1, strlen($string) - 2);
         }
-
         return $string;
     }
+
+    /**
+     * Works like PHP 'explode()', but respects $delimeter wrapped in ticks (single or double): those are not interpreted as delimiter.
+     *
+     * E.g.: "a,b,'c,d',e" with delimiter ',' will result in [ 'a', 'b', 'c,d', 'e' ]
+     *
+     * @param $delimeter
+     * @param $str
+     * @param int $limit
+     * @return array|bool
+     * @throws CodeException
+     */
+    public static function explodeWrapped($delimeter, $str, $limit=PHP_INT_MAX ) {
+
+        if($delimeter=='') {
+            return false;
+        }
+
+        if($limit<0) {
+            throw new CodeException("Not Implemented: limit<0", ERROR_NOT_IMPLEMENTED);
+        }
+
+        if($limit==0) {
+            $limit = 1;
+        }
+
+        $final = array();
+        $startToken='';
+        $onHold = '';
+
+        $cnt = 0;
+        $arr = explode($delimeter, $str, PHP_INT_MAX);
+        foreach($arr as $value) {
+            $trimmed=trim($value);
+            if($value=='' && $startToken=='') {
+
+                if($cnt<$limit) {
+                    $final[] = '';
+                    $cnt++;
+                }
+                continue;
+            }
+
+            if($startToken=='') {
+                switch ($trimmed[0]) {
+                    case SINGLE_TICK:
+                    case DOUBLE_TICK:
+                        if($trimmed[0] == substr($trimmed, -1)) {
+                            break; // In case start and end token is in one exploded item
+                        }
+                        $startToken = $trimmed[0];
+                        $onHold = $value;
+                        continue 2;
+                    default:
+                        break;
+                }
+
+                if($cnt>=$limit) {
+                    $final[$cnt-1] .= $delimeter . $value;
+                } else {
+                    $final[] = $value;
+                    $cnt++;
+                }
+                continue;
+            } else {
+                $onHold .= $delimeter . $value;
+                $lastChar = substr($trimmed,-1);
+                if($startToken == $lastChar) {
+
+                    if($cnt>=$limit) {
+                        $final[$cnt-1] .=  $delimeter . $onHold;
+                    } else {
+                        $final[] = $onHold;
+                        $cnt++;
+                    }
+                    $startToken = '';
+                    $onHold = '';
+                }
+            }
+        }
+
+        return $final;
+    }
 }
diff --git a/extension/qfq/qfq/helper/Ldap.php b/extension/qfq/qfq/helper/Ldap.php
new file mode 100644
index 0000000000000000000000000000000000000000..1425f7def6b0d037e746e72bda262cf430dbdd64
--- /dev/null
+++ b/extension/qfq/qfq/helper/Ldap.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: crose
+ * Date: 3/14/17
+ * Time: 11:32 PM
+ */
+
+namespace qfq;
+
+use qfq;
+
+require_once(__DIR__ . '/KeyValueStringParser.php');
+
+class Ldap {
+
+    /**
+     * @param $query
+     * @return array
+     * @throws UserFormException
+     */
+    public function process($config, $query) {
+        $arr = array();
+
+        $ldapServer = $config[FE_TYPEAHEAD_LDAP_SERVER];
+        $ldapBaseDn = $config[FE_TYPEAHEAD_LDAP_BASE_DN];
+        $ldapSearch = $config[FE_TYPEAHEAD_LDAP_SEARCH];
+        $ldapSearch = str_replace('?', $query, $ldapSearch);
+        $ldapLimit = $config[FE_TYPEAHEAD_LIMIT];
+
+        $ds = ldap_connect($ldapServer);  // must be a valid LDAP server!
+        if (!$ds) {
+            throw new UserFormException("Unable to connect to LDAP server: $ldapServer", ERROR_LDAP_CONNECT);
+        }
+
+        $sr = ldap_search($ds, $ldapBaseDn, $ldapSearch, null, null, $ldapLimit);
+        $info = ldap_get_entries($ds, $sr);
+
+        for ($i = 0; $i < $info["count"]; $i++) {
+
+            $key = $this->printfResult($config[FE_TYPEAHEAD_LDAP_KEY_PRINTF], $info[$i]);
+            $value = $this->printfResult($config[FE_TYPEAHEAD_LDAP_VALUE_PRINTF], $info[$i]);
+
+            $arr[] = [API_TYPEAHEAD_KEY => $key, API_TYPEAHEAD_VALUE => $value];
+        }
+
+        ldap_close($ds);
+
+        return $arr;
+    }
+
+    /**
+     * Collects values from $inforElelement and sprintf them  as described in $format.
+     *
+     * @param $format
+     * @param $infoElement
+     * @return string       output of sprintf
+     * @throws CodeException
+     * @throws UserFormException
+     */
+    private function printfResult($format, $infoElement) {
+
+        // $format: "'%s / %s / %s', cn, mail, telephonenumber".
+        // keyArr[0]: printf format string
+        // keyArr[1..x]: columnnames
+        $keyArr = KeyValueStringParser::explodeWrapped(',', $format);
+        if (count($keyArr) <= 2) {
+            throw new UserFormException("Expect a sprintf compatible format string with a least one argument. Got: '" . $format . "'", ERROR_MISSING_PRINTF_ARGUMENTS);
+        }
+
+        $args = array();
+        $args[] = $keyArr[0];
+        $keyArr = array_shift($keyArr);
+        foreach ($keyArr as $arg) {
+            $keyName = trim($arg);
+            $args[] = $infoElement[$keyName][0];
+        }
+
+//        if(isset($info[$i]["mail"][0])) {
+//            $key = $info[$i]["mail"][0];
+//            if($key===false || $key===null || $key=='') {
+//                continue;
+//            }
+//            $arr[] = [ 'key' => $info[$i]["mail"][0], 'value' => $info[$i]["cn"][0] . ' / ' . $info[$i]["mail"][0] . ' / ' . $info[$i]["telephonenumber"][0]];
+//        }
+
+        return call_user_func_array('sprintf', $args);
+    }
+}
\ No newline at end of file
diff --git a/extension/qfq/qfq/helper/OnArray.php b/extension/qfq/qfq/helper/OnArray.php
index 54b48b57f16c8e9b6566e6803690e22c7a29dd64..0da2d056500e88658f9dcde13ef3064d096c89ca 100644
--- a/extension/qfq/qfq/helper/OnArray.php
+++ b/extension/qfq/qfq/helper/OnArray.php
@@ -29,6 +29,7 @@ class OnArray {
      * @param array $dataArray
      * @param string $keyValueGlue
      * @param string $rowGlue
+     * @param string $encloseValue  - char (or string) to enclose the value with.
      * @return string
      */
     public static function toString(array $dataArray, $keyValueGlue = '=', $rowGlue = '&', $encloseValue = '') {
diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php
index 7526a468bc2e53cd57b2fe609e96bbd0464aa137..1fc32d719d2c8725828dc71f385da52c417c36f8 100644
--- a/extension/qfq/qfq/helper/Support.php
+++ b/extension/qfq/qfq/helper/Support.php
@@ -625,6 +625,9 @@ class Support {
     }
 
     /**
+     * Looks in $arr if there is an element $index. If not, set it to $value.
+     * If  $overwriteThis!=false, replace the the original value with $value, if $arr[$index]==$overwriteThis.
+     *
      * @param array $arr
      * @param string $index
      * @param string $value
@@ -692,6 +695,8 @@ class Support {
     }
 
     /**
+     * Convert 'false' and 'empty' to '0'.
+     *
      * @param $val
      * @return string
      */
diff --git a/extension/qfq/tests/phpunit/KeyValueStringParserTest.php b/extension/qfq/tests/phpunit/KeyValueStringParserTest.php
index bebcb8339347d42fe821179e75c2c71a767a4098..c19b1c48be886cd87467283a761f5384a5742c3a 100644
--- a/extension/qfq/tests/phpunit/KeyValueStringParserTest.php
+++ b/extension/qfq/tests/phpunit/KeyValueStringParserTest.php
@@ -169,4 +169,85 @@ class KeyValueStringParserTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals($expected, $actual);
         $this->assertCount(2, $actual);
     }
+
+    public function testExplodeContent() {
+        $actual = keyValueStringParser::explodeWrapped('', '');
+        $this->assertEquals(false, $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(':', '');
+        $this->assertEquals([''], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(':', 'a,b,c');
+        $this->assertEquals(['a,b,c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b,c');
+        $this->assertEquals(['a' , 'b' ,'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', ' a,b,c');
+        $this->assertEquals([' a' , 'b' ,'c'], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', 'a ,b,c');
+        $this->assertEquals(['a ' , 'b' ,'c'], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', ' a ,b,c');
+        $this->assertEquals([' a ' , 'b' ,'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a, b,c');
+        $this->assertEquals(['a' , ' b' ,'c'], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b ,c');
+        $this->assertEquals(['a' , 'b ' ,'c'], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', 'a, b ,c');
+        $this->assertEquals(['a' , ' b ' ,'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b, c');
+        $this->assertEquals(['a' , 'b' ,' c'], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b,c ');
+        $this->assertEquals(['a' , 'b' ,'c '], $actual);
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b, c ');
+        $this->assertEquals(['a' , 'b' ,' c '], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,"b",c');
+        $this->assertEquals(['a' , '"b"','c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,"b,b",c');
+        $this->assertEquals(['a' , '"b,b"','c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,'b',c");
+        $this->assertEquals(['a' , "'b'",'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,'b,b',c");
+        $this->assertEquals(['a' , "'b,b'",'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,'b,b,b',c");
+        $this->assertEquals(['a' , "'b,b,b'",'c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "'a,a,a,a','b','c,c,c,c,c'");
+        $this->assertEquals(["'a,a,a,a'" , "'b'","'c,c,c,c,c'"], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', " 'a,a,a' , 'b' , 'c,c' ");
+        $this->assertEquals([" 'a,a,a' " , " 'b' "," 'c,c' "], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', 'a,b,c', 2);
+        $this->assertEquals(['a' , 'b,c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "'a,a',b,c", 2);
+        $this->assertEquals(["'a,a'" , 'b,c'], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,'b,b',c", 2);
+        $this->assertEquals(['a' , "'b,b',c" ], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,b,'c,c'", 2);
+        $this->assertEquals(['a' , "b,'c,c'" ], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,b,c", 0);
+        $this->assertEquals(['a,b,c' ], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,b,c", 1);
+        $this->assertEquals(['a,b,c' ], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "'a,b',c", 1);
+        $this->assertEquals(["'a,b',c" ], $actual);
+
+        $actual = keyValueStringParser::explodeWrapped(',', "a,'b,c'", 1);
+        $this->assertEquals(["a,'b,c'" ], $actual);
+
+    }
 }