PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/PayPal/Core/PPUtils.php

https://gitlab.com/CORP-RESELLER/sdk-core-php
PHP | 333 lines | 184 code | 36 blank | 113 comment | 34 complexity | 971530513ce73405f8a46738016bf7e4 MD5 | raw file
  1. <?php
  2. namespace PayPal\Core;
  3. class PPUtils
  4. {
  5. /**
  6. *
  7. * Convert a Name Value Pair (NVP) formatted string into
  8. * an associative array taking care to urldecode array values
  9. *
  10. * @param string $nvpString
  11. *
  12. * @return array
  13. */
  14. public static function nvpToMap($nvpString)
  15. {
  16. $ret = array();
  17. $params = explode("&", $nvpString);
  18. foreach ($params as $p) {
  19. list($k, $v) = explode("=", $p);
  20. $ret[$k] = urldecode($v);
  21. }
  22. return $ret;
  23. }
  24. /**
  25. * Returns true if the array contains a key like $key
  26. *
  27. * @param array $map
  28. * @param string $key
  29. *
  30. * @return bool
  31. */
  32. public static function array_match_key($map, $key)
  33. {
  34. $replace = str_replace(array(
  35. '(',
  36. ')',
  37. '.'
  38. ), array(
  39. '\(',
  40. '\)',
  41. '\.'
  42. ), $key);
  43. $pattern = "/$replace*/";
  44. foreach ($map as $k => $v) {
  45. preg_match($pattern, $k, $matches);
  46. if (count($matches) > 0) {
  47. return true;
  48. }
  49. }
  50. return false;
  51. }
  52. /**
  53. * Get the local IP address. The client address is a required
  54. * request parameter for some API calls
  55. */
  56. public static function getLocalIPAddress()
  57. {
  58. if (array_key_exists("SERVER_ADDR", $_SERVER) && self::isIPv4($_SERVER['SERVER_ADDR'])) {
  59. // SERVER_ADDR is available only if we are running the CGI SAPI
  60. return $_SERVER['SERVER_ADDR'];
  61. } else if (function_exists("gethostname") && self::isIPv4(gethostbyname(gethostname()))) {
  62. return gethostbyname(gethostname());
  63. } else {
  64. // fallback if nothing works
  65. return "127.0.0.1";
  66. }
  67. }
  68. /**
  69. * Determines if valid IPv4 or not
  70. *
  71. * @param $ip
  72. *
  73. * @return bool
  74. */
  75. public static function isIPv4($ip)
  76. {
  77. return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
  78. }
  79. /**
  80. * Convert xml string to an intermediate nested array
  81. * representation that can be iterated
  82. *
  83. * @param string $xmlInput XML string to convert
  84. */
  85. public static function xmlToArray($xmlInput)
  86. {
  87. $doc = new \DOMDocument();
  88. $doc->preserveWhiteSpace = false;
  89. $doc->loadXML($xmlInput);
  90. $results = $doc->getElementsByTagName("Body");
  91. if ($results->length > 0) {
  92. $node = $results->item(0);
  93. return PPUtils::xmlNodeToArray($node);
  94. } else {
  95. throw new \Exception("Unrecognized response payload ");
  96. }
  97. }
  98. /**
  99. * Convert a DOM node to an intermediate nested array
  100. * representation that can be iterated
  101. *
  102. * @param DOMNode $node DOM node to convert
  103. */
  104. private static function xmlNodeToArray($node)
  105. {
  106. $result = array();
  107. $children = $node->childNodes;
  108. if (!empty($children)) {
  109. for ($i = 0; $i < (int)$children->length; $i++) {
  110. $child = $children->item($i);
  111. if ($child !== null) {
  112. if ($child->childNodes->item(0) instanceof \DOMText) {
  113. $result[$i]['name'] = $child->nodeName;
  114. $result[$i]['text'] = $child->childNodes->item(0)->nodeValue;
  115. if ($child->hasAttributes()) {
  116. foreach ($child->attributes as $k => $v) {
  117. if ($v->namespaceURI != 'http://www.w3.org/2001/XMLSchema-instance') {
  118. $result[$i]['attributes'][$v->name] = $v->value;
  119. }
  120. }
  121. }
  122. } else if (!in_array($child->nodeName, $result)) {
  123. $result[$i]['name'] = $child->nodeName;
  124. $result[$i]['children'] = PPUtils::xmlNodeToArray($child);
  125. if ($child->hasAttributes()) {
  126. $attrs = $child->attributes;
  127. foreach ($attrs as $k => $v) {
  128. if ($v->namespaceURI != 'http://www.w3.org/2001/XMLSchema-instance') {
  129. $result[$i]['attributes'][$v->name] = $v->value;
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }
  136. }
  137. return $result;
  138. }
  139. /**
  140. * Escapes invalid xml characters
  141. *
  142. * @param $textContent = xml data to be escaped
  143. *
  144. * @return string
  145. */
  146. public static function escapeInvalidXmlCharsRegex($textContent)
  147. {
  148. return htmlspecialchars($textContent, (1 | 2), 'UTF-8', false);
  149. }
  150. /**
  151. * Filter an array based on keys that match given prefix
  152. *
  153. * @param array $map
  154. * @param string $keyPrefix
  155. *
  156. * @return array
  157. */
  158. public static function filterKeyPrefix(array $map, $keyPrefix)
  159. {
  160. $filtered = array();
  161. foreach ($map as $key => $val) {
  162. if (($pos = stripos($key, $keyPrefix)) !== 0) {
  163. continue;
  164. }
  165. $filtered[substr_replace($key, '', 0, strlen($keyPrefix))] = $val;
  166. }
  167. return $filtered;
  168. }
  169. /**
  170. * @var array|ReflectionProperty[]
  171. */
  172. private static $propertiesRefl = array();
  173. /**
  174. * @var array|string[]
  175. */
  176. private static $propertiesType = array();
  177. /**
  178. * Get property annotations for a certain property in a class
  179. *
  180. * @param string $class
  181. * @param string $propertyName
  182. *
  183. * @throws RuntimeException
  184. * @return string
  185. */
  186. public static function propertyAnnotations($class, $propertyName)
  187. {
  188. $class = is_object($class) ? get_class($class) : $class;
  189. if (!class_exists('ReflectionProperty')) {
  190. throw new \RuntimeException("Property type of " . $class . "::{$propertyName} cannot be resolved");
  191. }
  192. if ($annotations =& self::$propertiesType[$class][$propertyName]) {
  193. return $annotations;
  194. }
  195. if (!($refl =& self::$propertiesRefl[$class][$propertyName])) {
  196. $refl = new \ReflectionProperty($class, $propertyName);
  197. }
  198. // todo: smarter regexp
  199. if (!preg_match_all('~\@([^\s@\(]+)[\t ]*(?:\(?([^\n@]+)\)?)?~i', $refl->getDocComment(), $annots,
  200. PREG_PATTERN_ORDER)
  201. ) {
  202. return null;
  203. }
  204. foreach ($annots[1] as $i => $annot) {
  205. $annotations[strtolower($annot)] = empty($annots[2][$i]) ? true : rtrim($annots[2][$i], " \t\n\r)");
  206. }
  207. return $annotations;
  208. }
  209. /**
  210. * Determine if a property in a given class is a
  211. * attribute type.
  212. *
  213. * @param string $class
  214. * @param string $propertyName
  215. *
  216. * @return string
  217. */
  218. public static function isAttributeProperty($class, $propertyName)
  219. {
  220. if (($annotations = self::propertyAnnotations($class, $propertyName))) {
  221. return array_key_exists('attribute', $annotations);
  222. }
  223. return false;
  224. }
  225. /**
  226. * Determine if a property in a given class is a
  227. * collection type.
  228. *
  229. * @param string $class
  230. * @param string $propertyName
  231. *
  232. * @return string
  233. */
  234. public static function isPropertyArray($class, $propertyName)
  235. {
  236. if (($annotations = self::propertyAnnotations($class, $propertyName))) {
  237. if (isset($annotations['var']) && substr($annotations['var'], -2) === '[]') {
  238. return true;
  239. } elseif (isset($annotations['array'])) {
  240. return true;
  241. }
  242. }
  243. return false;
  244. }
  245. /**
  246. * Get data type of a property in a given class
  247. *
  248. * @param string $class
  249. * @param string $propertyName
  250. *
  251. * @throws RuntimeException
  252. * @return string
  253. */
  254. public static function propertyType($class, $propertyName)
  255. {
  256. if (($annotations = self::propertyAnnotations($class, $propertyName)) && isset($annotations['var'])) {
  257. if (substr($annotations['var'], -2) === '[]') {
  258. return substr($annotations['var'], 0, -2);
  259. }
  260. return $annotations['var'];
  261. }
  262. return 'string';
  263. }
  264. /**
  265. *
  266. * @param object $object
  267. *
  268. * @return array
  269. */
  270. public static function objectProperties($object)
  271. {
  272. $props = array();
  273. foreach (get_object_vars($object) as $property => $default) {
  274. $annotations = self::propertyAnnotations($object, $property);
  275. if (isset($annotations['name'])) {
  276. $props[strtolower($annotations['name'])] = $property;
  277. }
  278. $props[strtolower($property)] = $property;
  279. }
  280. return $props;
  281. }
  282. /**
  283. * Convert all array keys to lowercase
  284. *
  285. * @param array $array
  286. *
  287. * @return array
  288. */
  289. public static function lowerKeys(array $array)
  290. {
  291. $ret = array();
  292. foreach ($array as $key => $value) {
  293. $ret[strtolower($key)] = $value;
  294. }
  295. return $ret;
  296. }
  297. }