Completed
Push — develop ( d2849b...41fc7f )
by Stuart
02:18
created

string-functions.php ➔ quote_index()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 4
c 1
b 0
f 1
nc 2
nop 1
dl 0
loc 7
rs 9.4285
1
<?php
2
3
/**
4
 * Copyright (c) 2016-present Ganbaro Digital Ltd
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *
14
 *   * Redistributions in binary form must reproduce the above copyright
15
 *     notice, this list of conditions and the following disclaimer in
16
 *     the documentation and/or other materials provided with the
17
 *     distribution.
18
 *
19
 *   * Neither the names of the copyright holders nor the names of his
20
 *     contributors may be used to endorse or promote products derived
21
 *     from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category  Libraries
37
 * @package   MissingBits/StringFunctions
38
 * @author    Stuart Herbert <[email protected]>
39
 * @copyright 2016-present Ganbaro Digital Ltd www.ganbarodigital.com
40
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
41
 * @link      http://ganbarodigital.github.io/php-the-missing-bits
42
 */
43
44
/**
45
* surround an array key with single quotes if appropriate
46
*
47
* If $key isn't a string, no quotes are added.
48
*
49
* @param  mixed $key
50
*         the item to (possibly) quote
51
* @return mixed
52
*         the unmodified $key if it is not a string
53
*         the quoted $key if it is a string
54
*/
55
function quote_index($key) {
56
    if (!is_string($key)) {
57
        return $key;
58
    }
59
60
    return "'$key'";
61
}
62
63
/**
64
 * surround a string with braces, if it would need braces in order to be used
65
 * as a PHP property name in eval()
66
 *
67
 * @param  string $propertyName
68
 *         the property name to add braces to (if required)
69
 * @return string
70
 */
71
function quote_property($propertyName) {
72
    // robustness!
73
    if (!is_stringy($propertyName)) {
74
        throw new InvalidArgumentException('$propertyName is not a valid class or object property name');
75
    }
76
77
    // would the string need braces if we used it in eval()?
78
    //
79
    // the rules are:
80
    // - first character must be an ASCII letter or an underscore
81
    // - the remaining characters can only be ASCII letters, numbers,
82
    //   or an underscore
83
    //
84
    // any string that doesn't satisfy those rules needs braces adding
85
    if (!preg_match("/[A-Za-z_][A-Za-z0-9_]{" . (strlen($propertyName) - 1) . "}/", $propertyName)) {
86
        // yes it would
87
        return '{' . $propertyName . '}';
88
    }
89
90
    // if we get here, then no action is needed
91
    return $propertyName;
92
}
93
94
if (!function_exists("vnsprintf")) {
95
96
/**
97
 * vsprintf()-compatible function, with support for named parameters in the
98
 * format string
99
 *
100
 * Internally, we convert named parameters into positional parameters. This
101
 * means that your format string:
102
 *
103
 * - must be a pure vsprintf()-compatible format string, or
104
 * - must use only named parameters, or
105
 * - must use a mix of named parameters and positional parameters
106
 *
107
 * You CANNOT mix named parameters and non-positional parameters.
108
 *
109
 * @param  string $format
110
 *         the format string to use
111
 * @param  array args
112
 *         the list of parameters to use
113
 * @return string
114
 *         the result of expanding $format
115
 */
116
function vnsprintf($format, $args)
117
{
118
    // we need to find all of the named parameters to expand
119
    $regex = "|(?<!%)(?:%)([^0-9].+)(?:\\\$)|U";
120
121
    $matches = [];
122
    $matchCount = preg_match_all($regex, $format, $matches, PREG_OFFSET_CAPTURE);
123
    if ($matchCount === 0) {
124
        // nothing to do
125
        return vsprintf($format, $args);
126
    }
127
128
    // if we get here, then we have some matches to expand
129
    // we're going to add them to the end of this array
130
    $messageData = $args;
131
132
    // this will keep track of where we've added the data
133
    $nextData = count($messageData);
134
    $paramKeys = array_fill_keys(array_keys($args), -1);
135
136
    // this will keep track of how we've shrunk the format string
137
    $formatChange = 0;
138
139
    // transform the named parameters into offset parameters
140
    foreach ($matches[1] as $match) {
141
        // what is the named parameter?
142
        $paramName = $match[0];
143
144
        // make sure the named parameter exists in our original data
145
        if (!isset($paramKeys[$paramName])) {
146
            throw new InvalidArgumentException("vnsprintf: named format-string parameter " . $paramName . " is not provided in \$args array");
147
        }
148
        // have we already assigned it a place in $messageData?
149
        // in case a named parameter appears multiple times in the format string
150
        if ($paramKeys[$paramName] === -1) {
151
            // no - it needs a home
152
            $messageData[$nextData] =& $args[$paramName];
153
            $paramKeys[$paramName] = $nextData;
154
            $nextData++;
155
        }
156
        // convert the named parameter in the format string into a positional
157
        // parameter into $messageData
158
        $paramOffset = $paramKeys[$paramName] + 1;
159
        $format = substr_replace($format, $paramOffset, $formatChange + $match[1], strlen($paramName));
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $format. This often makes code more readable.
Loading history...
160
161
        // how much did we shrink / grow the format string by?
162
        $formatChange = $formatChange - strlen($paramName) + strlen($paramOffset);
163
    }
164
165
    // all done
166
    return vsprintf($format, $messageData);
167
}
168
169
}
170