KeyValueStringParser.php 4.33 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\UserException;
15
16

require_once(__DIR__ . '/../exceptions/UserException.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
42
43
     * @param array $keyValueArray
     * @param string $keyValueDelimiter
     * @param string $listDelimiter
     * @return string
44
     */
45
    public static function unparse(array $keyValueArray, $keyValueDelimiter = ":", $listDelimiter = ",") {
46
47
48
49
50
        array_walk($keyValueArray, function (&$value) {
            if (!is_string($value) || $value === "" || strlen($value) === 1) {
                return;
            }

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

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

61
        return implode($listDelimiter, $newKeyValuePairImploded);
62
63
    }

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

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

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

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

96
        $keyValuePairs = explode($listDelimiter, $keyValueString);
97
98
99
100
101
102
103
104

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

            if ($keyValuePairString === "") {
                continue;
            }

105
            $keyValueArray = explode($keyValueDelimiter, $keyValuePairString, 2);
106
107
108
109

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

            // skip comments
110
            if (substr($key, 0, 1) == '#' || substr($key, 0, 1) == ';') {
111
112
113
114
115
                continue;
            }

            if ($key === '') {
                // ":", ":1"
116
                throw new UserException("Value has no key: '$keyValuePairString'", ERROR_VALUE_HAS_NO_KEY);
117
118
119
120
            }

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

        return $returnValue;
    }

    /**
     * @param $string
     * @return string
     */
    private function removeSourroundingQuotes($string) {
        $quotes = ['\'', '"'];

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

142
        if (in_array($string[0], $quotes) === true && self::isFirstAndLastCharacterIdentical($string)) {
143
144
145
146
147
148
            return substr($string, 1, strlen($string) - 2);
        }

        return $string;
    }
}