Completed
Push — master ( eeb5ec...507cda )
by Josh
04:12
created

XPath::exportString()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 32
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 32
ccs 15
cts 15
cp 1
rs 9.2222
c 0
b 0
f 0
cc 6
nc 7
nop 1
crap 6
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2019 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Utils;
9
10
use InvalidArgumentException;
11
12
abstract class XPath
13
{
14
	/**
15
	* Export a literal as an XPath expression
16
	*
17
	* @param  mixed  $value Literal, e.g. "foo"
18
	* @return string        XPath expression, e.g. "'foo'"
19
	*/
20 10
	public static function export($value)
21
	{
22 10
		if (!is_scalar($value) || self::isIrrational($value))
23
		{
24 1
			throw new InvalidArgumentException(__METHOD__ . '() cannot export non-scalar values');
25
		}
26 9
		if (is_int($value))
27
		{
28 1
			return (string) $value;
29
		}
30 8
		if (is_float($value))
31
		{
32
			// Avoid locale issues by using sprintf()
33 2
			return preg_replace('(\\.?0+$)', '', sprintf('%F', $value));
34
		}
35 6
		if (is_bool($value))
36
		{
37 2
			return ($value) ? 'true()' : 'false()';
38
		}
39
40 4
		return self::exportString((string) $value);
41
	}
42
43
	/**
44
	* Export a string as an XPath expression
45
	*
46
	* @param  string $str Literal, e.g. "foo"
47
	* @return string      XPath expression, e.g. "'foo'"
48
	*/
49 4
	protected static function exportString($str)
50
	{
51
		// foo becomes 'foo'
52 4
		if (strpos($str, "'") === false)
53
		{
54 1
			return "'" . $str . "'";
55
		}
56
57
		// d'oh becomes "d'oh"
58 3
		if (strpos($str, '"') === false)
59
		{
60 1
			return '"' . $str . '"';
61
		}
62
63
		// This string contains both ' and ". XPath 1.0 doesn't have a mechanism to escape quotes,
64
		// so we have to get creative and use concat() to join chunks in single quotes and chunks
65
		// in double quotes
66 2
		$toks = [];
67 2
		$c    = '"';
68 2
		$pos  = 0;
69 2
		while ($pos < strlen($str))
70
		{
71 2
			$spn = strcspn($str, $c, $pos);
72 2
			if ($spn)
73
			{
74 2
				$toks[] = $c . substr($str, $pos, $spn) . $c;
75 2
				$pos   += $spn;
76
			}
77 2
			$c = ($c === '"') ? "'" : '"';
78
		}
79
80 2
		return 'concat(' . implode(',', $toks) . ')';
81
	}
82
83
	/**
84
	* Test whether given value is an irrational number
85
	*
86
	* @param  mixed $value
87
	* @return bool
88
	*/
89 9
	protected static function isIrrational($value)
90
	{
91 9
		return is_float($value) && !is_finite($value);
92
	}
93
}