Commit | Line | Data |
---|---|---|
f344f1e3 TO |
1 | <?php |
2 | ||
12b478ef | 3 | use Psr\Http\Message\ResponseInterface; |
f344f1e3 TO |
4 | use Psr\Http\Message\RequestInterface; |
5 | ||
6 | /** | |
7 | * Additional helpers/utilities for use as Guzzle middleware. | |
8 | */ | |
9 | class CRM_Utils_GuzzleMiddleware { | |
10 | ||
11 | /** | |
12 | * Add this as a Guzzle handler/middleware if you wish to simplify | |
13 | * the construction of Civi-related URLs. It enables URL schemes for: | |
14 | * | |
15 | * - route://ROUTE_NAME (aka) route:ROUTE_NAME | |
1c5f00b3 TO |
16 | * - backend://ROUTE_NAME (aka) backend:ROUTE_NAME |
17 | * - frontend://ROUTE_NAME (aka) frontend:ROUTE_NAME | |
f344f1e3 TO |
18 | * - var://PATH_EXPRESSION (aka) var:PATH_EXPRESSION |
19 | * - ext://EXTENSION/FILE (aka) ext:EXTENSION/FILE | |
20 | * - assetBuilder://ASSET_NAME?PARAMS (aka) assetBuilder:ASSET_NAME?PARAMS | |
21 | * | |
22 | * Compare: | |
23 | * | |
1c5f00b3 TO |
24 | * $http->get(CRM_Utils_System::url('civicrm/dashboard', NULL, TRUE, NULL, FALSE, ??)) |
25 | * $http->get('route://civicrm/dashboard') | |
26 | * $http->get('frontend://civicrm/dashboard') | |
27 | * $http->get('backend://civicrm/dashboard') | |
f344f1e3 TO |
28 | * |
29 | * $http->get(Civi::paths()->getUrl('[civicrm.files]/foo.txt')) | |
30 | * $http->get('var:[civicrm.files]/foo.txt') | |
31 | * | |
32 | * $http->get(Civi::resources()->getUrl('my.other.ext', 'foo.js')) | |
33 | * $http->get('ext:my.other.ext/foo.js') | |
34 | * | |
35 | * $http->get(Civi::service('asset_builder')->getUrl('my-asset.css', ['a'=>1, 'b'=>2])) | |
36 | * $http->get('assetBuilder:my-asset.css?a=1&b=2') | |
37 | * | |
38 | * Note: To further simplify URL expressions, Guzzle allows you to set a 'base_uri' | |
39 | * option (which is applied as a prefix to any relative URLs). Consider using | |
40 | * `base_uri=auto:`. This allows you to implicitly use the most common types | |
41 | * (routes+variables): | |
42 | * | |
43 | * $http->get('civicrm/dashboard') | |
44 | * $http->get('[civicrm.files]/foo.txt') | |
45 | * | |
46 | * @return \Closure | |
47 | */ | |
48 | public static function url() { | |
49 | return function(callable $handler) { | |
50 | return function (RequestInterface $request, array $options) use ($handler) { | |
51 | $newUri = self::filterUri($request->getUri()); | |
52 | if ($newUri !== NULL) { | |
53 | $request = $request->withUri(\CRM_Utils_Url::parseUrl($newUri)); | |
54 | } | |
55 | ||
56 | return $handler($request, $options); | |
57 | }; | |
58 | }; | |
59 | } | |
60 | ||
61 | /** | |
62 | * @param \Psr\Http\Message\UriInterface $oldUri | |
63 | * | |
64 | * @return string|null | |
65 | * The string formation of the new URL, or NULL for unchanged URLs. | |
66 | */ | |
67 | protected static function filterUri(\Psr\Http\Message\UriInterface $oldUri) { | |
68 | // Copy the old ?query-params and #fragment-params on top of $newBase. | |
69 | $copyParams = function ($newBase) use ($oldUri) { | |
70 | if ($oldUri->getQuery()) { | |
71 | $newBase .= strpos($newBase, '?') !== FALSE ? '&' : '?'; | |
72 | $newBase .= $oldUri->getQuery(); | |
73 | } | |
74 | if ($oldUri->getFragment()) { | |
75 | $newBase .= '#' . $oldUri->getFragment(); | |
76 | } | |
77 | return $newBase; | |
78 | }; | |
79 | ||
80 | $hostPath = urldecode($oldUri->getHost() . $oldUri->getPath()); | |
81 | $scheme = $oldUri->getScheme(); | |
82 | if ($scheme === 'auto') { | |
83 | // Ex: 'auto:civicrm/my-page' ==> Router | |
84 | // Ex: 'auto:[civicrm.root]/js/foo.js' ==> Resource file | |
85 | $scheme = ($hostPath[0] === '[') ? 'var' : 'route'; | |
86 | } | |
87 | ||
1c5f00b3 TO |
88 | if ($scheme === 'route') { |
89 | $menu = CRM_Core_Menu::get($hostPath); | |
90 | $scheme = ($menu && !empty($menu['is_public'])) ? 'frontend' : 'backend'; | |
91 | } | |
92 | ||
f344f1e3 TO |
93 | switch ($scheme) { |
94 | case 'assetBuilder': | |
95 | // Ex: 'assetBuilder:dynamic.css' or 'assetBuilder://dynamic.css?foo=bar' | |
96 | // Note: It's more useful to pass params to the asset-builder than to the final HTTP request. | |
97 | $assetParams = []; | |
98 | parse_str('' . $oldUri->getQuery(), $assetParams); | |
99 | return \Civi::service('asset_builder')->getUrl($hostPath, $assetParams); | |
100 | ||
101 | case 'ext': | |
102 | // Ex: 'ext:other.ext.name/file.js' or 'ext://other.ext.name/file.js' | |
103 | [$ext, $file] = explode('/', $hostPath, 2); | |
104 | return $copyParams(\Civi::resources()->getUrl($ext, $file)); | |
105 | ||
106 | case 'var': | |
107 | // Ex: 'var:[civicrm.files]/foo.txt' or 'var://[civicrm.files]/foo.txt' | |
108 | return $copyParams(\Civi::paths()->getUrl($hostPath, 'absolute')); | |
109 | ||
1c5f00b3 TO |
110 | case 'backend': |
111 | // Ex: 'backend:civicrm/my-page' or 'backend://civicrm/my-page' | |
f344f1e3 TO |
112 | return $copyParams(\CRM_Utils_System::url($hostPath, NULL, TRUE, NULL, FALSE)); |
113 | ||
1c5f00b3 TO |
114 | case 'frontend': |
115 | // Ex: 'frontend:civicrm/my-page' or 'frontend://civicrm/my-page' | |
116 | return $copyParams(\CRM_Utils_System::url($hostPath, NULL, TRUE, NULL, FALSE, TRUE)); | |
117 | ||
f344f1e3 TO |
118 | default: |
119 | return NULL; | |
120 | } | |
121 | } | |
122 | ||
12b478ef TO |
123 | /** |
124 | * This logs the list of outgoing requests in curl format. | |
125 | */ | |
126 | public static function curlLog(\Psr\Log\LoggerInterface $logger) { | |
127 | ||
128 | $curlFmt = new class() extends \GuzzleHttp\MessageFormatter { | |
129 | ||
130 | public function format(RequestInterface $request, ResponseInterface $response = NULL, \Exception $error = NULL) { | |
131 | $cmd = '$ curl'; | |
132 | if ($request->getMethod() !== 'GET') { | |
133 | $cmd .= ' -X ' . escapeshellarg($request->getMethod()); | |
134 | } | |
135 | foreach ($request->getHeaders() as $header => $lines) { | |
136 | foreach ($lines as $line) { | |
137 | $cmd .= ' -H ' . escapeshellarg("$header: $line"); | |
138 | } | |
139 | } | |
140 | $body = (string) $request->getBody(); | |
141 | if ($body !== '') { | |
142 | $cmd .= ' -d ' . escapeshellarg($body); | |
143 | } | |
144 | $cmd .= ' ' . escapeshellarg((string) $request->getUri()); | |
145 | return $cmd; | |
146 | } | |
147 | ||
148 | }; | |
149 | ||
150 | return \GuzzleHttp\Middleware::log($logger, $curlFmt); | |
151 | } | |
152 | ||
f344f1e3 | 153 | } |