KeyValueStringParser.php 4.57 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
<?php
/**
 * Created by PhpStorm.
 * @author: crose
 * Date: 7/8/15
 * Time: 10:12 AM
 *
 * $Id$
 */

11
namespace qfq;
Carsten  Rose's avatar
Carsten Rose committed
12
13

use qfq;
14
use qfq\UserFormException;
15

16
require_once(__DIR__ . '/../exceptions/UserFormException.php');
17
require_once(__DIR__ . '/../../qfq/Constants.php');
18
19
20
21
22
23
24
25
26
27
28
29
30

/**
 * Class KeyValueStringParser
 *
 * KeyValueStringParser is a parser for strings of the form
 *
 *     key1<delimiterA>value1<delimiterB>key2<delimiterA>value2<delimiterB>
 *
 * For instance
 *
 *     id=1,name=doe,firstname=john
 *
 * - Leading and trailing whitespace will be removed from keys and values.
31
 * - If a value is surrounded by quotes (`'`,  `"`), leading and trailing
32
 *   whitespace will be preserved (leading/trailing, quotes will be removed from value).
33
 * - Comments, lines starting with a '#' or ';', will be skipped.
34
35
36
37
38
39
 *
 * @package qfq
 */
class KeyValueStringParser {

    /**
40
41
     * Builds a string based on kvp array. Concatenatet by the given delimiter.
     *
42
43
44
45
     * @param array $keyValueArray
     * @param string $keyValueDelimiter
     * @param string $listDelimiter
     * @return string
46
     */
47
    public static function unparse(array $keyValueArray, $keyValueDelimiter = ":", $listDelimiter = ",") {
48
49
50
51
52
        array_walk($keyValueArray, function (&$value) {
            if (!is_string($value) || $value === "" || strlen($value) === 1) {
                return;
            }

53
            if ($value[0] === " " && self::isFirstAndLastCharacterIdentical($value[0])) {
54
55
56
57
58
59
                $value = '"' . $value . '"';
            }
        });

        $newKeyValuePairImploded = array();
        foreach ($keyValueArray as $key => $value) {
60
            $newKeyValuePairImploded[] = trim($key) . $keyValueDelimiter . $value;
61
62
        }

63
        return implode($listDelimiter, $newKeyValuePairImploded);
64
65
    }

66
67
68
69
    /**
     * @param $string
     * @return bool
     */
70
    private static function isFirstAndLastCharacterIdentical($string) {
71
72
73
74
75
76
77
78
        if ($string === "") {
            return false;
        }

        return $string[0] === $string[strlen($string) - 1];
    }

    /**
79
     * Parse key/value pairs string and returns them as an assoc array
80
     *
Carsten  Rose's avatar
Carsten Rose committed
81
     * Hint $keyValueString: "a:1,b:2,c:,d",  "," (empty key AND empty value)
82
     *
Carsten  Rose's avatar
Carsten Rose committed
83
     * @param string $keyValueString string of key/value pairs. E.g.: 'a=100,b=test'
84
85
     * @param string $keyValueDelimiter
     * @param string $listDelimiter
86
     * @param string $valueMode
87
88
     *  * KVP_VALUE_GIVEN: If only a key is given, the value is ''.  E.G. 'a,b' >> [ 'a' => '', 'b' => '' ]
     *  * KVP_IF_VALUE_EMPTY_COPY_KEY: If only a key is given, the value is the same as the key. E.G. 'a,b' >> [ 'a' => 'a', 'b' => 'b' ].
89
     * @return array  associative array indexed by keys
90
     * @throws UserFormException Thrown if there is a value but no key.
91
92
     */

93
    public static function parse($keyValueString, $keyValueDelimiter = ":", $listDelimiter = ",", $valueMode = KVP_VALUE_GIVEN) {
94
95
96
97
        if ($keyValueString === "") {
            return array();
        }

98
99
100
        // Clean any "\r\n" to "\n"
        $keyValueString = str_replace("\r\n", "\n", $keyValueString);

101
        $keyValuePairs = explode($listDelimiter, $keyValueString);
102
103
104
105

        $returnValue = array();
        foreach ($keyValuePairs as $keyValuePairString) {

106
            if (trim($keyValuePairString === "")) {
107
108
109
                continue;
            }

110
            $keyValueArray = explode($keyValueDelimiter, $keyValuePairString, 2);
111
112
113
114

            $key = trim($keyValueArray[0]);

            // skip comments
115
            if (substr($key, 0, 1) == '#' || substr($key, 0, 1) == ';') {
116
117
118
119
120
                continue;
            }

            if ($key === '') {
                // ":", ":1"
121
                throw new UserFormException("Value has no key: '$keyValuePairString'", ERROR_KVP_VALUE_HAS_NO_KEY);
122
123
124
125
            }

            if (count($keyValueArray) === 2) {
                // "a:1", "a:"
126
                $returnValue[$key] = self::removeSourroundingQuotes(trim($keyValueArray[1]));
127
128
            } else {
                // no Value given: "a"
129
                $returnValue[$key] = ($valueMode === KVP_VALUE_GIVEN) ? "" : $key;
130
131
132
133
134
135
136
137
138
139
            }
        }

        return $returnValue;
    }

    /**
     * @param $string
     * @return string
     */
140
    private static function removeSourroundingQuotes($string) {
141
142
143
144
145
146
        $quotes = ['\'', '"'];

        if ($string === "" || strlen($string) === 1) {
            return $string;
        }

147
        if (in_array($string[0], $quotes) === true && self::isFirstAndLastCharacterIdentical($string)) {
148
149
150
151
152
153
            return substr($string, 1, strlen($string) - 2);
        }

        return $string;
    }
}