-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOEmbedService.php
234 lines (215 loc) · 7.61 KB
/
OEmbedService.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
<?php
namespace OEmbed;
use OEmbed\BaseClient;
use OEmbed\Response;
use OEmbed\Exceptions;
/**
* Allows to get resource information form oembed services.
* Check http://http://oembed.com/ for more information about oembed format specification.
* It allows discovery: if no endpoints match (or no enpoints provided),
* then the service will get the resource url and try to find the oembed <link> tag
*
* It only supports oembed services that accept json format (I didn't find
*
* @link http://oembed.com/
*
* Example:
* <code>
* $service = new OEmbedService(
* // oembed andpoints that will be used by the service
* array(
* array(
* 'pattern' => '/http:\/\/www\.flickr\.com/',
* 'url' => 'http://www.flickr.com/oembed',
* 'params' => array('width' => 200, 'token'=> 'MY_TOKEN', 'anyotherparam' =>'yes')
* )
* ),
* // discovery option: true is not recommended (because it will do 2 requests per call)
* false,
* // allowed resource url pattern
* array(
* '/http:\/\/www\.flickr\.com/'
* )
*
* ));
* $response = $service->get($this->getTestUrl('discovery'));
* </code>
*/
class OEmbedService {
/**
*
* endPoints:
* array of array:
* - key: int (non-associative)
* - value: array of
* pattern
* url: embed url (mandatory)
* params (optional): additional params passed to embed url to fetch the oEmbed
* The order is important: the first matching endPoint found is used
*
* @var array
*/
protected $endPoints;
/**
* an array of regexp patterns of allowed resource urls
* if empty, then all urls are allowed
*
* @var array
*/
protected $allowedUrlPatterns;
/**
* if true, and if no endPoint is found, then the resource URL will be fetched
* and the oembed url will be fetched (link tag)
* @link http://oembed.com/#section4
* @var boolean
*/
protected $discovery;
/**
*
* @param array $endPoints
* @param boolean $discovery
* @paramO array $allowedUrlPatterns
*/
public function __construct($endPoints = array(), $discovery = false, $allowedUrlPatterns = array()) {
//var_dump($endPoints);//die();
$this->endPoints = $endPoints;
foreach ($endPoints as $key => $params) {
$this->endPoints[$key] = array(
'pattern' => $params['pattern'],
'endPoint' => new OEmbedEndpoint($params['url'], isset($params['params'])? $params['params']: array())
);
}
$this->allowedUrlPatterns = $allowedUrlPatterns;
$this->discovery = $discovery;
}
/**
* performs the http call(s) to retrieve oembed data.
* Can throw a bunch of different exceptions (inherits from OEmbed\Exception\OEmebedException
* @throws Exception\NotAllowedUrlException
* @throws Exception\NoEndPointFoundException
* @throws Exception\NoOEmbedLinkFoundException
* @throws Exception\OEmbedUnauthorizedException
* @throws Exception\OEmbedNotFoundException
* @throws Exception\OEmbedNotImplementedException
* @throws Exception\InvalidResponseException
* @throws Exception\OEmbedResourceNotFoundException
*
* @param string $resourceUrl
* @param array $params params
* @return stdClass
*/
public function get($resourceUrl, $params = array()) {
// resourceUrl allowed or not?
if (!$this->isAllowed($resourceUrl)) {
throw new Exception\NotAllowedUrlException();
}
// try to find an endPoint
$endPoint = $this->findEndPoint($resourceUrl);
if ($endPoint) {
// got one... cool
$resp = $endPoint->get($resourceUrl, $params);
} else {
// are we allowed to get the oembedurl from the resourceurl (meta tag)?
if (!$this->discovery) {
throw new Exception\NoEndPointFoundException();
} else {
$url = $this->fetchOEmbedUrl($resourceUrl);
if (!$url) {
throw new Exception\NoOEmbedLinkFoundException();
} else {
// ok, we have a url now... so call it directly
$resp = OEmbedEndpoint::getUrl($url, $params);
}
}
}
return $resp;
}
/**
* find a valid endpoint form the array of endpoints (from constructor)
* stops when one endpoint is found
* @see OEmbedService::__construct()
*
* @param string $resourceUrl
* @return OEmbedEndpoint one endpoint object
*/
public function findEndPoint($resourceUrl) {
$matchingEndPoint = false;
foreach ($this->endPoints as $endPoint) {
if (self::match($endPoint['pattern'], $resourceUrl)) {
$matchingEndPoint = $endPoint['endPoint'];
break;
}
}
return $matchingEndPoint;
}
/**
* Checks if the resource URL is allowed
* returns true is no $allowedUrlPatterns is
* @param string $resourceUrl
* @return boolean
*/
public function isAllowed($resourceUrl) {
// if empty, then all urls are allowed
if (count($this->allowedUrlPatterns) < 1) {
return true;
}
// is it part of the allowed patterns
foreach ($this->allowedUrlPatterns as $pattern) {
if (self::match($pattern, $resourceUrl)) {
return true;
}
}
// if we're here, then not allowed
return false;
}
/**
* Just a preg_match wrapper...
* @param string $pattern regexp pattern
* @param string $url
* @return boolean
*/
public static function match($pattern, $url) {
return (preg_match($pattern, $url) > 0);
}
/**
* fetch and return the oembed url form the resource url itself (<link>)
* @param string $resourceUrl
* @return string|false the oembed url or false if not found
*/
public function fetchOEmbedUrl($resourceUrl) {
$oembedUrl = false;
$client = new Client();
$resp = $client->get($resourceUrl);
if ($resp->getHttpCode() == 404) {
throw new Exception\OEmbedResourceNotFoundException();
}
// fetch all the <link> tags using regular expression
$nb = preg_match_all("/<link[^>]+>/i",
$resp->content,
$out);
if ($out[0]) {
foreach ($out[0] as $link) {
if (strpos($link, 'application/json+oembed') !== false) {
$oembedLinkPos = strpos($link, 'href="') + 6;
$oembedEndLinkPos = strpos($link, '"', $oembedLinkPos + 7) - 1;
//echo $oembedLinkPos . ', ' . $oembedEndLinkPos . "\n";
$oembedUrl = substr($link, $oembedLinkPos, $oembedEndLinkPos - $oembedLinkPos + 1);
break;
}
}
}
return $oembedUrl;
}
/**
* @param string $name
* @return OEmbedEndpoint
*/
public function getEndpoint($name) {
if (!isset($this->endPoints[$name])) {
if (!isset($this->endPoints[$name]['endPoint'])) {
throw new Exception\NoEndPointFoundException();
}
}
return $this->endPoints[$name]['endPoint'];
}
}