Добавлен alexprey,
опубликован
Программирование
Язык:
php
Hello XGM!
Давно не писал я в своем бложике, но вот мне что-то захотелось.
Давно не писал я в своем бложике, но вот мне что-то захотелось.
Введение
Написали в тех. поддержку сайта с просьбой добавить интеграцию со SketchFab'ом для отображения моделей прямо на сайте.
Начал изучать, что и как можно было сделать. Так как форматирование txt2 основано на простоте и удобстве форматирования, то использование bb-кодов и html-вставок было не возможным. Классически все интеграции делаются по принципу - вижу ссылку, заменил.
Этап первый
Первым делом пошел по накатанной, начал смотреть как строится код для отображения проигрывателя моделей. Способ для отображения моделей из голой ссылки нашел, а вот для плейлистов - увы...
Почему так? А потому что ссылка модели содержит нужный идентификатор, который потом используется в отображении самой модели. А вот для плейлиста были случаи, когда указывался либо идентификатор, либо имя плейлиста. Из-за этого возникали проблемы, первое что пришло в голову - надо запрашивать этот самый айдишник через Data API, который я нашел на SketchFab'е.
Почему так? А потому что ссылка модели содержит нужный идентификатор, который потом используется в отображении самой модели. А вот для плейлиста были случаи, когда указывался либо идентификатор, либо имя плейлиста. Из-за этого возникали проблемы, первое что пришло в голову - надо запрашивать этот самый айдишник через Data API, который я нашел на SketchFab'е.
Этап второй
Думая дальше, анализируя примеры, нашел в документации сервиса для девелоперов такой вот интересный пункт - oEmbed. Открыл, смотрю:
- Сделайте запрос на наш сервис с параметром в виде ссылки
- Получите в ответ html код для вставки на сайте, а так же дополнительную информацию о предоставляемом контенте
Причем поддерживается не только отображение моделей, но и каталогов с моделями, а значит это то, что мне надо. Немного пошаманив с кодом парсера txt2, выделил ссылку на модель сайта SketchFab, отправил запрос ждя получение контента, используя cURL. И все стало выглядеть примерно так:
function txt2_sketchfab_link($url) {
$targetUrl = 'https://sketchfab.com/oembed?url=' . $url;
// Request a oEmbed content
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $targetUrl);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
// Verify response
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code != 200) {
return null;
}
// Parse json response
$response = json_decode($result);
if ($response == null) {
return null;
}
return $response['html];
}
После этого все ссылки ведущие на SketchFab стали заменяться на плеер моделей. И смотрелось это так:
Этап третий
Немного еще погуглив на тему oEmbed протокола оказалось, что этот протокол был специально разработан для вставки медиа контента в виде ссылок. На официальном сайте данного протокола я нашел большой список поставщиков контента, таких как (sketchfab.com, devianart.com, soundcloud.com). И я подумал, раз все так просто, то почему бы и не прикрутить обработку других поставщиков медиа-контента. Для этого пришлось немного поработать над решением получения медиа контента, сделать его более универсальным. По спецификации все было достаточно просто:
- Провайдер имеет свой уникальный идентификатор
- Провайдер имеет точку вызова для получения данных (EndPoint)
- Провайдер имеет список правил для ссылок, которые он может обрабатывать
И поэтому для создания универсального решения требовалось реализовать небольшую библиотечку, в которой бы были реализованы следующие функции:
- Получение кода Embed компонента для указанный ссылки с использованием определенного провайдера (OEmbedProvider)
- Получение провайдера по ссылке (OEmbedProviderFactory)
Класс OEmbedProviderFactory будет заниматься созданием определенного провайдера медиа-контента, чтобы потом в итоге мы могли бы получить данные для конкретной ссылки. Информацию о разрешенных провайдерах будет храниться в специальном конфиге, где будет содержаться вся необходимая информация, указанная выше.
Ну и для этого конечно же написал немного кода, примерно такого
<?php
/**
* @author Alexey Prey Mulyukin
* Date: 08.09.2015
* Time: 0:42
*/
class OEmbedData {
public $html;
}
/**
* Class OEmbedProviderFactory
*
* Provider configuration Example:
* {
* 'name': string,
* 'endpoint': endpoint,
* 'schemas': [
* url-schema,
* url-schema
* ]
* }
*/
class OEmbedProviderFactory {
private static $instance;
public static function &GetInst() {
return self::$instance;
}
private $schemaRegexStorage = array();
private $providerStorage = array();
private $providerConfiguration;
public function __construct($providerConfiguration) {
if (self::$instance != null) {
throw new ErrorException("OEmbedProviderFactory already exists in this application context!");
}
$this->providerConfiguration = $providerConfiguration;
self::$instance = &$this;
}
private function GetSchemaRegex($schema) {
if (is_null($this->schemaRegexStorage[$schema])) {
$regex = preg_replace(
array("/\*/", "/\//", "/\.\*\./"),
array(".*", "\/", ".*"),
$schema
);
$regex = "/" . $regex . "/";
$this->schemaRegexStorage[$schema] = $regex;
}
return $this->schemaRegexStorage[$schema];
}
private function ValidateSchema($schema, $url) {
$regex = self::GetSchemaRegex($schema);
return preg_match($regex, $url);
}
private function ValidateProviderSchemas($provider, $url) {
$schemas = $provider['schemas'];
foreach ($schemas as $schema) {
if ($this->ValidateSchema($schema, $url)) {
return true;
}
}
return false;
}
/**
* Create new or find exists @see OEmbedProvider which can process this $url
* @param $url
* @return OEmbedProvider|null
*/
public function GetProvider($url) {
foreach($this->providerConfiguration as $provider) {
if ($this->ValidateProviderSchemas($provider, $url)) {
$name = $provider['name'];
if ($this->providerStorage[$name] == null) {
$this->providerStorage[$name] = new OEmbedProvider($provider['endpoint']);
}
return $this->providerStorage[$name];
}
}
}
/**
* Return a @see OEmbedData for this $url is possible
* @param $url
* @return OEmbedData|null
*/
public function GetEmbedData($url) {
$provider = $this->GetProvider($url);
if ($provider == null) {
return null;
}
return $provider->GetEmbedData($url);
}
}
class OEmbedProvider {
private $contentProviderEndpoint;
public function __construct($contentProviderEndpoint) {
$this->contentProviderEndpoint = $contentProviderEndpoint;
}
/**
* @param $url
* @return OEmbedData
*/
public function GetEmbedData($url) {
$targetUrl = $this->contentProviderEndpoint . '?format=json&url=' . $url;
// Request a oEmbed content
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $targetUrl);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
// Verify response
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code != 200) {
return null;
}
// Parse json response
$response = json_decode($result);
if ($response == null) {
return null;
}
// Build information about links
$embedData = new OEmbedData();
// Да, да, да, я знаю, что тут костыль
if ($response->type == "photo") {
$embedData->html =
'<a href="' . $response->url . '" title="by ' . $response->author_name . '">' .
'<img src="' . $response->thumbnail_url . '" />' .
'</a>';
;
} else {
$embedData->html = $response->html;
}
return $embedData;
}
}
А работать с этим примерно так:
// Инициализация
$config['OEmbedProviders'] = array(
array(
'name' => 'sketchfab',
'endpoint' => 'https://sketchfab.com/oembed',
'schemas' => array(
'https://sketchfab.com/models/*',
'https://sketchfab.com/*/folders/*',
'http://sketchfab.com/*/folders/*',
'http://sketchfab.com/models/*'
)
),
);
new OEmbedProviderFactory($config['OEmbedProviders']);
// Применяемс на деле
$url = "....";
$factory = &OEmbedProviderFactory::GetInst();
echo $factory->GetEmbedData($url);
В будущем хочу развивать эту библиотечку ^^ Сейчас она в очень плохом и сыром виде.
В ближайшее время мы подготовим патч для сайта, где добавится поддержка данного протокола для SketchFab'а. Ждите)
В ближайшее время мы подготовим патч для сайта, где добавится поддержка данного протокола для SketchFab'а. Ждите)
Спасибо за внимание!
Дополнительно:
- oEmbed official site - официальный сайт протокола oEmbed
- SketchFab - каталог 3д моделей с возможностью интерактивного просмотра
- GitHub: aphp-oembed - библиотека для работы с oEmbed провайдерами. Подключайтесь)
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
prog:
Отредактирован prog