Skip to content

Commit 0450aec

Browse files
committed
Merge pull request #46 from ianbarber/master
URITemplate level 4 and README/Version update
2 parents 8f1e731 + 3d9b815 commit 0450aec

4 files changed

Lines changed: 308 additions & 25 deletions

File tree

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ See the examples/ directory for examples of the key client features.
2828
}
2929
```
3030

31+
## Frequently Asked Questions ##
32+
33+
### What do I do if something isn't woring? ###
34+
35+
For support with the library the best place to ask is via the google-api-php-client tag on StackOverflow: http://stackoverflow.com/questions/tagged/google-api-php-client
36+
37+
If there is a specific bug with the library, please file a issue in the Github issues tracker, including a (minimal) example of the failing code and any specific errors retrieved. Feature requests can also be filed, as long as they are core library requests, and not-API specific: for those, refer to the documentation for the individual APIs for the best place to file requests. Please try to provide a clear statement of the problem that the feature would address.
38+
39+
### How do I contribute? ###
40+
41+
We accept contributions via Github Pull Requests, but all contributors need to be covered by the standard Google Contributor License Agreement. You can find links, and more instructions, in the documentation: https://developers.google.com/api-client-library/php/contribute
42+
43+
### Why do you still support 5.2? ###
44+
45+
When we started working on the 1.0.0 branch we knew there were several fundamental issues to fix with the 0.6 releases of the library. At that time we looked at the usage of the library, and other related projects, and determined that there was still a large and active base of PHP 5.2 installs. You can see this in statistics such as the PHP versions chart in the Wordpress stats: http://wordpress.org/about/stats/. We will keep looking at the types of usage we see, and try to take advantage of newer PHP features where possible.
46+
47+
### Why does Google_..._Service have weird names? ###
48+
49+
The _Service classes are generally automatically generated from the API discovery documents: https://developers.google.com/discovery/. Sometimes new features are added to APIs with unusual names, which can cause some unexpected or non-standard style naming in the PHP classes.
50+
3151
## Code Quality ##
3252

3353
Copy the ruleset.xml in style/ into a new directory named GAPI/ in your

src/Google/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
*/
3636
class Google_Client
3737
{
38-
const LIBVER = "1.0.1-alpha";
38+
const LIBVER = "1.0.1-beta";
3939
const USER_AGENT_SUFFIX = "google-api-php-client/";
4040
const GZIP_UA = " (gzip)";
4141
/**

src/Google/Utils/URITemplate.php

Lines changed: 182 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
*/
2222
class Google_Utils_URITemplate
2323
{
24+
const TYPE_MAP = "1";
25+
const TYPE_LIST = "2";
26+
const TYPE_SCALAR = "4";
27+
2428
/**
2529
* @var $operators array
2630
* These are valid at the start of a template block to
@@ -86,36 +90,53 @@ private function replace($string, $start, $end, $parameters)
8690
if (isset($this->operators[$data[0]])) {
8791
$op = $this->operators[$data[0]];
8892
$data = substr($data, 1);
93+
$prefix = "";
94+
$prefix_on_missing = false;
95+
8996
switch ($op) {
9097
case "reserved":
9198
// Reserved means certain characters should not be URL encoded
9299
$data = $this->replaceVars($data, $parameters, ",", null, true);
93100
break;
94101
case "fragment":
95102
// Comma separated with fragment prefix. Bare values only.
96-
$data = "#" . $this->replaceVars($data, $parameters, ",", null, true);
103+
$prefix = "#";
104+
$prefix_on_missing = true;
105+
$data = $this->replaceVars($data, $parameters, ",", null, true);
97106
break;
98107
case "segments":
99108
// Slash separated data. Bare values only.
100-
$data = "/" . $this->replaceVars($data, $parameters, "/");
109+
$prefix = "/";
110+
$data =$this->replaceVars($data, $parameters, "/");
101111
break;
102112
case "dotprefix":
103113
// Dot separated data. Bare values only.
104-
$data = "." . $this->replaceVars($data, $parameters, ".");
114+
$prefix = ".";
115+
$prefix_on_missing = true;
116+
$data = $this->replaceVars($data, $parameters, ".");
105117
break;
106118
case "semicolon":
107119
// Semicolon prefixed and separated. Uses the key name
108-
$data = ";" . $this->replaceVars($data, $parameters, ";", "=", false, true);
120+
$prefix = ";";
121+
$data = $this->replaceVars($data, $parameters, ";", "=", false, true, false);
109122
break;
110123
case "form":
111124
// Standard URL format. Uses the key name
112-
$data = "?" . $this->replaceVars($data, $parameters, "&", "=");
125+
$prefix = "?";
126+
$data = $this->replaceVars($data, $parameters, "&", "=");
113127
break;
114128
case "continuation":
115129
// Standard URL, but with leading ampersand. Uses key name.
116-
$data = "&" . $this->replaceVars($data, $parameters, "&", "=");
130+
$prefix = "&";
131+
$data = $this->replaceVars($data, $parameters, "&", "=");
117132
break;
118133
}
134+
135+
// Add the initial prefix character if data is valid.
136+
if ($data || ($data !== false && $prefix_on_missing)) {
137+
$data = $prefix . $data;
138+
}
139+
119140
} else {
120141
// If no operator we replace with the defaults.
121142
$data = $this->replaceVars($data, $parameters);
@@ -130,45 +151,183 @@ private function replaceVars(
130151
$sep = ",",
131152
$combine = null,
132153
$reserved = false,
133-
$tag_empty = false
154+
$tag_empty = false,
155+
$combine_on_empty = true
134156
) {
135157
if (strpos($section, ",") === false) {
136158
// If we only have a single value, we can immediately process.
137-
return $this->combine($section, $parameters, $combine, $reserved, $tag_empty);
159+
return $this->combine(
160+
$section,
161+
$parameters,
162+
$sep,
163+
$combine,
164+
$reserved,
165+
$tag_empty,
166+
$combine_on_empty
167+
);
138168
} else {
139169
// If we have multiple values, we need to split and loop over them.
140170
// Each is treated individually, then glued together with the
141171
// separator character.
142172
$vars = explode(",", $section);
143-
$ret = array();
144-
foreach ($vars as $var) {
145-
$ret[] = $this->combine($var, $parameters, $combine, $reserved, $tag_empty);
146-
}
147-
return implode($sep, $ret);
173+
return $this->combineList(
174+
$vars,
175+
$sep,
176+
$parameters,
177+
$combine,
178+
$reserved,
179+
false, // Never emit empty strings in multi-param replacements
180+
$combine_on_empty
181+
);
148182
}
149183
}
184+
185+
public function combine(
186+
$key,
187+
$parameters,
188+
$sep,
189+
$combine,
190+
$reserved,
191+
$tag_empty,
192+
$combine_on_empty
193+
) {
194+
$length = false;
195+
$explode = false;
196+
$skip_final_combine = false;
197+
$value = false;
150198

151-
public function combine($key, $parameters, $combine, $reserved, $tag_empty)
152-
{
153-
if (!empty($parameters[$key])) {
154-
// For an individual value, we need to URL encode the data.
155-
$value = rawurlencode($parameters[$key]);
199+
// Check for length restriction.
200+
if (strpos($key, ":") !== false) {
201+
list($key, $length) = explode(":", $key);
202+
}
203+
204+
// Check for explode parameter.
205+
if ($key[strlen($key) - 1] == "*") {
206+
$explode = true;
207+
$key = substr($key, 0, -1);
208+
$skip_final_combine = true;
209+
}
210+
211+
// Define the list separator.
212+
$list_sep = $explode ? $sep : ",";
213+
214+
if (isset($parameters[$key])) {
215+
$data_type = $this->getDataType($parameters[$key]);
216+
switch($data_type) {
217+
case self::TYPE_SCALAR:
218+
$value = $this->getValue($parameters[$key], $length);
219+
break;
220+
case self::TYPE_LIST:
221+
$values = array();
222+
foreach ($parameters[$key] as $pkey => $pvalue) {
223+
$pvalue = $this->getValue($pvalue, $length);
224+
if ($combine && $explode) {
225+
$values[$pkey] = $key . $combine . $pvalue;
226+
} else {
227+
$values[$pkey] = $pvalue;
228+
}
229+
}
230+
$value = implode($list_sep, $values);
231+
if ($value == '') {
232+
return '';
233+
}
234+
break;
235+
case self::TYPE_MAP:
236+
$values = array();
237+
foreach ($parameters[$key] as $pkey => $pvalue) {
238+
$pvalue = $this->getValue($pvalue, $length);
239+
if ($explode) {
240+
$pkey = $this->getValue($pkey, $length);
241+
$values[] = $pkey . "=" . $pvalue; // Explode triggers = combine.
242+
} else {
243+
$values[] = $pkey;
244+
$values[] = $pvalue;
245+
}
246+
}
247+
$value = implode($list_sep, $values);
248+
if ($value == '') {
249+
return false;
250+
}
251+
break;
252+
}
156253
} else if ($tag_empty) {
157254
// If we are just indicating empty values with their key name, return that.
158255
return $key;
159256
} else {
160-
// Otherwise we can return empty string.
161-
$value = "";
257+
// Otherwise we can skip this variable due to not being defined.
258+
return false;
162259
}
260+
163261
if ($reserved) {
164262
$value = str_replace($this->reservedEncoded, $this->reserved, $value);
165263
}
264+
166265
// If we do not need to include the key name, we just return the raw
167266
// value.
168-
if (!$combine) {
267+
if (!$combine || $skip_final_combine) {
169268
return $value;
170269
}
171-
// Else we combine the key name: foo=bar
172-
return $key . $combine . $value;
270+
271+
// Else we combine the key name: foo=bar, if value is not the empty string.
272+
return $key . ($value != '' || $combine_on_empty ? $combine . $value : '');
273+
}
274+
275+
/**
276+
* Return the type of a passed in value
277+
*/
278+
private function getDataType($data)
279+
{
280+
if (is_array($data)) {
281+
reset($data);
282+
if (key($data) !== 0) {
283+
return self::TYPE_MAP;
284+
}
285+
return self::TYPE_LIST;
286+
}
287+
return self::TYPE_SCALAR;
288+
}
289+
290+
/**
291+
* Utility function that merges multiple combine calls
292+
* for multi-key templates.
293+
*/
294+
private function combineList(
295+
$vars,
296+
$sep,
297+
$parameters,
298+
$combine,
299+
$reserved,
300+
$tag_empty,
301+
$combine_on_empty
302+
) {
303+
$ret = array();
304+
foreach ($vars as $var) {
305+
$response = $this->combine(
306+
$var,
307+
$parameters,
308+
$sep,
309+
$combine,
310+
$reserved,
311+
$tag_empty,
312+
$combine_on_empty
313+
);
314+
if ($response === false) {
315+
continue;
316+
}
317+
$ret[] = $response;
318+
}
319+
return implode($sep, $ret);
320+
}
321+
322+
/**
323+
* Utility function to encode and trim values
324+
*/
325+
private function getValue($value, $length)
326+
{
327+
if ($length) {
328+
$value = substr($value, 0, $length);
329+
}
330+
$value = rawurlencode($value);
331+
return $value;
173332
}
174333
}

0 commit comments

Comments
 (0)