06.07.2019
Видео с YouTube на сайт
Иногда встречаются необычные задачи. Одной из таких задач, на моей практике была:
На сайте имеется раздел "Медиа". В него добавляются видео с YouTube про наш продукт. В дальнейшем видео связывается с товарами на сайте.
На данный момент приходится в ручную искать видео, и добавлять на сайт. Это очень не удобно. Так же в ручном режиме можно что то пропустить.
Для решения данное задачи можно использовать YouTube Data API v3.
По ссылке "Get started" есть отличный мануал о том как начать использовать данное api.
В YouTube Data API v3 есть отличный отладчик API
- Создать Google аккаунт (если у Вас его еще нет)
- Создать проект в Google Developers Console
- Получить учетные данные для авторизации. Нам необходим вариант с Api Key
- После создания проекта убедитесь, что API данных YouTube является одной из служб, для которой ваше приложение зарегистрировано для использования. Для этого перейдите в консоль API и выберите проект, который вы только что зарегистрировали. Посетите страницу Enabled APIs. В списке API убедитесь, что для YouTube Data API v3 включен
- Выберите клиентскую библиотеку, чтобы упростить реализацию API. В нашем случае это Google APIs Client Library for PHP
- Остально только написать бизнес логику, используя полученные ключи и клиентскую библиотеку
Под свою задачу я написал следующий php класс
<?php
namespace Gricuk\Youtube;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Error;
use Bitrix\Main\Loader;
use Bitrix\Main\Result;
use Bitrix\Main\Type\DateTime;
class Controller
{
protected $siteId = NULL;
protected $API_KEY = NULL;
protected $iblockId = 0;
protected $query = false;
public function __construct($params)
{
Loader::includeModule("iblock");
$this->siteId = $params["SITE_ID"];
$this->API_KEY = $params["API_KEY"];
$this->iblockId = $params["IBLOCK_MEDIA"];
$this->query = $params["QUERY"];
if (strlen($this->API_KEY) == 0) {
throw new \Exception("API_KEY не задан");
}
if (intval($this->iblockId) == 0) {
throw new \Exception("IBLOCK_MEDIA не задан");
}
if (strlen($this->query) == 0) {
throw new \Exception("QUERY не задан");
}
}
public function importVideos()
{
Loader::includeModule("iblock");
$result = new Result();
$resultArray = [];
$client = new \Google_Client();
$client->setDeveloperKey($this->API_KEY);
$youtube = new \Google_Service_YouTube($client);
$arParams = array("replace_space" => "-", "replace_other" => "-");
$arSelect = Array("ID", "NAME", "PROPERTY_PUBLISHET_DATE");
$arFilter = Array(
"IBLOCK_ID" => $this->iblockId,
);
$lastLoadedItem = \CIBlockElement::GetList(array("PROPERTY_PUBLISHET_DATE" => "DESC"), $arFilter, false, ["nTopCount" => 1], $arSelect)->Fetch();
$nexPageToken = false;
do {
$searchParams = array(
"order" => 'date',
'type' => 'video',
'q' => $this->query,
'maxResults' => 50
);
if ($lastLoadedItem) {
$time = new DateTime($lastLoadedItem["PROPERTY_PUBLISHET_DATE_VALUE"]);
$searchParams["publishedAfter"] = $time->format(\DateTime::ISO8601);
}
if ($nexPageToken) {
$searchParams["pageToken"] = $nexPageToken;
}
$searchResponse = $youtube->search->listSearch('id,snippet', $searchParams);
$nexPageToken = $searchResponse->nextPageToken;
$videoResults = array();
foreach ($searchResponse['items'] as $searchResult) {
array_push($videoResults, $searchResult['id']['videoId']);
}
if (!empty($videoResults)) {
$arSelect = Array("ID", "NAME", "IBLOCK_ID", "PROPERTY_VIDEO_ID");
$arFilter = Array(
"IBLOCK_ID" => $this->iblockId,
"PROPERTY_VIDEO_ID" => $videoResults
);
$res = \CIBlockElement::GetList(array("ID" => "ASC"), $arFilter, false, false, $arSelect);
$iblockItems = [];
while ($arItem = $res->Fetch()) {
$iblockItems[$arItem["PROPERTY_VIDEO_ID_VALUE"]] = $arItem["ID"];
}
$videoIds = join(',', $videoResults);
$videosResponse = $youtube->videos->listVideos('snippet, recordingDetails', array(
'id' => $videoIds,
));
foreach ($videosResponse["items"] as $item) {
if (isset($iblockItems[$item['id']])) {
$resultArray[] = [
"youtubeVideoId" => $item['id'],
"bitrixId" => $iblockItems[$item['id']],
"error" => "Видео уже загружено"
];
} else {
$clearTitle = trim(preg_replace('/[^\p{L}\s]/u', ' ', $item['snippet']['title']));
$arFields = [
"IBLOCK_SECTION_ID" => false,
"IBLOCK_ID" => \Gricuk\Main\Conf::ID_IBLOCK_MEDIA,
"ACTIVE" => "N",
"NAME" => $clearTitle,
"CODE" => \Cutil::translit($clearTitle, "ru", $arParams),
"PROPERTY_VALUES" => [
"VIDEO_ID" => $item['id'],
"CHANEL_ID" => $item['snippet']['channelId'],
"CHANEL_NAME" => $item['snippet']['channelTitle'],
"PUBLISHET_DATE" => \Bitrix\Main\Type\DateTime::createFromPhp(new \DateTime($item['snippet']['publishedAt'])),
]
];
$el = new \CIBlockElement();
$addResult = $el->Add($arFields);
if ($addResult) {
$resultArray[] = [
"youtubeVideoId" => $item['id'],
"bitrixId" => $addResult
];
$arEventFields = array(
"NAME" => "$clearTitle",
"VIDEO_ID" => $item['id'],
"CHANEL_NAME" => $item['snippet']['channelTitle'],
);
\CEvent::Send("YOUTUBE_NEW_VIDEO", $this->siteId, $arEventFields);
} else {
$result->addError(new Error($el->LAST_ERROR));
$resultArray[] = [
"name" => $clearTitle,
"youtubeVideoId" => $item['id'],
"bitrixId" => NULL,
"error" => $el->LAST_ERROR
];
}
}
}
}
} while ($nexPageToken);
$result->setData($resultArray);
return $result;
}
public static function loadYoutubeVideosAgent($siteId)
{
try {
$youtubeController = new Controller([
"SITE_ID" => $siteId,
"API_KEY" => "XXXXXXXXXXX",
"IBLOCK_MEDIA" => 1,
"QUERY" => "строка для поиска",
]);
$importResult = $youtubeController->importVideos();
} catch (\Exception $e) {
}
return '\\' . __CLASS__ . "::loadYoutubeVideosAgent('{$siteId}');";
}
}
Перед использованием необходимо будет создать инфоблок с таким набором свойств
После этого еобходимо подключить клиентскую библиотеку и сам скрипт. Создать агента, и в методе loadYoutubeVideosAgent указать необходимые настройки:
- API_KEY - Ключ API из Google Console
- IBLOCK_MEDIA - ID инфоблока в который будут добавляться элементы
- QUERY - Строка которую будет искать скрипт на youtube