video_embed_field.field.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. /**
  3. * @file
  4. * Implement a video field.
  5. */
  6. /**
  7. * Implements hook_field_info().
  8. */
  9. function video_embed_field_field_info() {
  10. return array(
  11. 'video_embed_field' => array(
  12. 'label' => 'Video Embed',
  13. 'description' => 'Embed videos from youtube or vimeo',
  14. 'settings' => array(),
  15. 'instance_settings' => array(
  16. 'description_field' => 0,
  17. 'description_length' => 128,
  18. ),
  19. 'default_widget' => 'video_embed_field_video',
  20. 'default_formatter' => 'video_embed_field',
  21. ),
  22. );
  23. }
  24. /**
  25. * Implements hook_field_instance_settings_form().
  26. */
  27. function video_embed_field_field_instance_settings_form($field, $instance) {
  28. $settings = $instance['settings'];
  29. $form['description_field'] = array(
  30. '#type' => 'checkbox',
  31. '#title' => t('Enable <em>Description</em> field'),
  32. '#default_value' => isset($settings['description_field']) ? $settings['description_field'] : '',
  33. '#description' => t('The description field allows users to enter a description about the video.'),
  34. '#parents' => array('instance', 'settings', 'description_field'),
  35. '#weight' => 11,
  36. );
  37. $form['description_length'] = array(
  38. '#type' => 'textfield',
  39. '#title' => t('Max description length'),
  40. '#default_value' => isset($settings['description_length']) ? $settings['description_length'] : 128,
  41. '#parents' => array('instance', 'settings', 'description_length'),
  42. '#weight' => 12,
  43. '#size' => 5,
  44. '#maxlength' => 5,
  45. );
  46. return $form;
  47. }
  48. /**
  49. * Implements hook_field_widget_info().
  50. */
  51. function video_embed_field_field_widget_info() {
  52. return array(
  53. 'video_embed_field_video' => array(
  54. 'label' => 'Video',
  55. 'description' => 'Provides a video embed field',
  56. 'field types' => array('video_embed_field'),
  57. 'settings' => array(),
  58. 'behaviors' => array(
  59. 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
  60. 'default value' => FIELD_BEHAVIOR_DEFAULT,
  61. ),
  62. ),
  63. );
  64. }
  65. /**
  66. * Implements hook_field_widget_form().
  67. */
  68. function video_embed_field_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  69. // Don't need to check the type right now because we're only defining one
  70. $element += array(
  71. '#type' => 'fieldset',
  72. );
  73. $element['video_url'] = array(
  74. '#type' => 'textfield',
  75. '#title' => t('Video URL'),
  76. '#attributes' => array('class' => array('video_embed_url')),
  77. '#attached' => array(
  78. 'css' => array(
  79. drupal_get_path('module', 'video_embed_field') . '/video_embed_field.form.css',
  80. ),
  81. ),
  82. '#default_value' => isset($items[$delta]['video_url']) ? $items[$delta]['video_url'] : '',
  83. '#required' => $element['#required'],
  84. );
  85. // Add the description field if enabled.
  86. if (!empty($instance['settings']['description_field'])) {
  87. $element['description'] = array(
  88. '#type' => 'textfield',
  89. '#title' => t('Description'),
  90. '#default_value' => isset($items[$delta]['description']) ? $items[$delta]['description'] : '',
  91. '#description' => t('The description which may be used as a label.'),
  92. '#maxlength' => $instance['settings']['description_length'],
  93. );
  94. }
  95. return $element;
  96. }
  97. /**
  98. * Validates video URL.
  99. */
  100. function video_embed_field_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
  101. foreach ($items as $delta => $item) {
  102. if (!empty($item['video_url'])) {
  103. $item['video_url'] = trim($item['video_url']);
  104. if (stristr($item['video_url'], '.') && !stristr($item['video_url'], 'http://') && !stristr($item['video_url'], 'https://')) {
  105. $item['video_url'] = 'http://' . $item['video_url'];
  106. }
  107. $parts = parse_url($item['video_url']);
  108. if (!$parts || !isset($parts['host'])) {
  109. $errors[$field['field_name']][$langcode][$delta][] = array(
  110. 'error' => t('Invalid Url'),
  111. 'message' => t('Video: Invalid Video URL.', array('%name' => $instance['label'])),
  112. );
  113. }
  114. else {
  115. $host = $parts['host'];
  116. if (stripos($host, 'www.') > -1) {
  117. $host = substr($host, 4);
  118. }
  119. $domains = _video_embed_field_get_provider_domains();
  120. if (!array_key_exists($host, $domains)) {
  121. $errors[$field['field_name']][$langcode][$delta][] = array(
  122. 'error' => t('Unsupported Video Provider'),
  123. 'message' => t('%name: This video provider is not currently supported.', array('%name' => $instance['label'])),
  124. );
  125. }
  126. }
  127. }
  128. }
  129. }
  130. /**
  131. * Implementation of hook_field_presave().
  132. *
  133. * Download and save the thumbnail if it hasn't already been stored.
  134. * Get video data.
  135. */
  136. function video_embed_field_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  137. foreach ($items as $delta => $item) {
  138. //Trim whitespace from the video URL.
  139. $items[$delta]['video_url'] = trim($item['video_url']);
  140. // Try to load thumbnail URL
  141. $info = video_embed_field_thumbnail_url($item['video_url']);
  142. if (isset($info['url']) && $info['url']) {
  143. $thumb_url = $info['url'];
  144. $local_path = 'public://video_embed_field_thumbnails/' . $info['handler'] . '/' . $info['id'] . '.jpg';
  145. $dirname = drupal_dirname($local_path);
  146. file_prepare_directory($dirname, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
  147. $response = drupal_http_request($thumb_url);
  148. if (!isset($response->error)) {
  149. file_save_data($response->data, $local_path, TRUE);
  150. }
  151. else {
  152. @copy($thumb_url, $local_path);
  153. }
  154. $items[$delta]['thumbnail_path'] = $local_path;
  155. } //couldn't get the thumbnail for whatever reason
  156. else {
  157. $items[$delta]['thumbnail_path'] = '';
  158. }
  159. // Try to load video data
  160. $data = video_embed_field_get_video_data($item['video_url']);
  161. if (is_array($data) && !empty($data)) {
  162. $items[$delta]['video_data'] = serialize($data);
  163. }
  164. else {
  165. $items[$delta]['video_data'] = NULL;
  166. }
  167. }
  168. }
  169. /**
  170. * Implements hook_field_is_empty().
  171. */
  172. function video_embed_field_field_is_empty($item, $field) {
  173. return empty($item) || empty($item['video_url']) || $item['video_url'] === '';
  174. }
  175. /**
  176. * Implements hook_field_formatter_info().
  177. */
  178. function video_embed_field_field_formatter_info() {
  179. $info = array(
  180. 'video_embed_field' => array(
  181. 'label' => t('Video Player'),
  182. 'field types' => array('video_embed_field'),
  183. 'settings' => array(
  184. 'video_style' => 'normal',
  185. 'description' => 1,
  186. 'description_position' => 'bottom'
  187. ),
  188. ),
  189. 'video_embed_field_thumbnail' => array(
  190. 'label' => t('Thumbnail Preview'),
  191. 'field types' => array('video_embed_field'),
  192. 'settings' => array(
  193. 'image_style' => 'none',
  194. 'description' => 1,
  195. 'description_position' => 'bottom',
  196. 'image_link' => 'none',
  197. ),
  198. ),
  199. );
  200. if ( module_exists('colorbox') ) {
  201. $info['video_embed_field_thumbnail_colorbox'] = array(
  202. 'label' => t('Thumbnail Preview w/Colorbox'),
  203. 'field types' => array('video_embed_field'),
  204. 'settings' => array(
  205. 'video_style' => 'normal',
  206. 'image_style' => 'none',
  207. 'description' => 1,
  208. 'description_position' => 'bottom',
  209. ),
  210. );
  211. }
  212. return $info;
  213. }
  214. /**
  215. * Implements hook_field_formatter_settings_form().
  216. */
  217. function video_embed_field_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  218. $display = $instance['display'][$view_mode];
  219. $settings = $display['settings'];
  220. $element = array();
  221. if ($display['type'] == 'video_embed_field' || $display['type'] == 'video_embed_field_thumbnail_colorbox') {
  222. $video_styles = video_embed_field_video_style_options(FALSE);
  223. $element['video_style'] = array(
  224. '#title' => t('Video style'),
  225. '#type' => 'select',
  226. '#default_value' => $settings['video_style'],
  227. '#options' => $video_styles,
  228. );
  229. }
  230. if ($display['type'] == 'video_embed_field_thumbnail' || $display['type'] == 'video_embed_field_thumbnail_colorbox') {
  231. $element['image_style'] = array(
  232. '#title' => t('Image style'),
  233. '#type' => 'select',
  234. '#options' => image_style_options(FALSE),
  235. '#default_value' => $settings['image_style'],
  236. '#empty_option' => t('None (original image)'),
  237. );
  238. }
  239. if ($display['type'] == 'video_embed_field_thumbnail') {
  240. $link_types = array(
  241. 'node' => t('Node'),
  242. 'source' => t('Video Source'),
  243. );
  244. $element['image_link'] = array(
  245. '#title' => t('Link thumbnail to'),
  246. '#type' => 'select',
  247. '#default_value' => $settings['image_link'],
  248. '#empty_option' => t('Nothing'),
  249. '#options' => $link_types,
  250. );
  251. }
  252. if ($instance['settings']['description_field']) {
  253. $element['description'] = array(
  254. '#title' => t('Show description'),
  255. '#type' => 'checkbox',
  256. '#default_value' => $settings['description'],
  257. );
  258. $element['description_position'] = array(
  259. '#title' => t('Description Position'),
  260. '#type' => 'select',
  261. '#options' => array(
  262. 'top' => t('Top'),
  263. 'bottom' => t('Bottom')
  264. ),
  265. '#default_value' => $settings['description_position'],
  266. );
  267. }
  268. return $element;
  269. }
  270. /**
  271. * Implements hook_field_formatter_settings_summary().
  272. */
  273. function video_embed_field_field_formatter_settings_summary($field, $instance, $view_mode) {
  274. $display = $instance['display'][$view_mode];
  275. $settings = $display['settings'];
  276. $summary = array();
  277. if ($display['type'] == 'video_embed_field' || $display['type'] == 'video_embed_field_thumbnail_colorbox') {
  278. $video_styles = video_embed_field_video_style_options(FALSE);
  279. // Styles could be lost because of enabled/disabled modules that defines
  280. // their styles in code.
  281. if (isset($video_styles[$settings['video_style']])) {
  282. $summary[] = t('Video style: @style', array('@style' => $video_styles[$settings['video_style']]));
  283. }
  284. }
  285. if ($display['type'] == 'video_embed_field_thumbnail' || $display['type'] == 'video_embed_field_thumbnail_colorbox') {
  286. $image_styles = image_style_options(FALSE);
  287. if (isset($image_styles[$settings['image_style']])) {
  288. $summary[] = t('Image style: @style', array('@style' => $image_styles[$settings['image_style']]));
  289. } //No Image style (original image)
  290. else {
  291. $summary[] = t('Original Image.');
  292. }
  293. if (isset($settings['image_link'])) {
  294. $summary[] = t('Image link: ' . $settings['image_link']);
  295. }
  296. else {
  297. $summary[] = t('Image link: none');
  298. }
  299. }
  300. if ($settings['description'] && $instance['settings']['description_field']) {
  301. $summary[] = t('Show description');
  302. }
  303. elseif ($instance['settings']['description_field']) {
  304. $summary[] = t('Hide description');
  305. }
  306. return implode('<br />', $summary);
  307. }
  308. /**
  309. * Implements hook_field_formatter_view().
  310. */
  311. function video_embed_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  312. $element = array();
  313. $settings = $display['settings'];
  314. foreach ($items as $delta => $item) {
  315. //create the render array for the description
  316. if (isset($item['description']) && $item['description'] && $settings['description'] && $instance['settings']['description_field']) {
  317. $description = array(
  318. '#prefix' => '<div class="video-embed-description">',
  319. '#markup' => $item['description'],
  320. '#suffix' => '</div>',
  321. );
  322. }
  323. else {
  324. $description = array();
  325. }
  326. //Render the field
  327. if ($display['type'] == 'video_embed_field') {
  328. $element[$delta] = array(
  329. array(
  330. '#theme' => 'video_embed_field_embed_code',
  331. '#url' => $item['video_url'],
  332. '#style' => $settings['video_style'],
  333. '#video_data' => !empty($item['video_data']) ? unserialize($item['video_data']) : array(),
  334. ),
  335. );
  336. }
  337. elseif ($display['type'] == 'video_embed_field_thumbnail') {
  338. if (isset($item['thumbnail_path'])) {
  339. if (empty($settings['image_style']) || $settings['image_style'] == 'none') {
  340. $element[$delta] = array(
  341. array(
  342. '#theme' => 'image',
  343. '#path' => $item['thumbnail_path'],
  344. ),
  345. );
  346. }
  347. else {
  348. $element[$delta] = array(
  349. array(
  350. '#theme' => 'image_style',
  351. '#path' => $item['thumbnail_path'],
  352. '#style_name' => $settings['image_style'],
  353. ),
  354. );
  355. }
  356. if ($settings['image_link'] == 'source') {
  357. $link = explode('|||', l('|||', $item['video_url']));
  358. $element[$delta]['#prefix'] = $link[0];
  359. $element[$delta]['#suffix'] = $link[1];
  360. }
  361. elseif ($settings['image_link'] == 'node') {
  362. $nid = $entity->nid;
  363. $link = explode('|||', l('|||', 'node/' . $nid));
  364. $element[$delta]['#prefix'] = $link[0];
  365. $element[$delta]['#suffix'] = $link[1];
  366. }
  367. } //incase no thumbnail was downloaded / provider doesn't support thumbnails
  368. else {
  369. $element[$delta] = array(
  370. );
  371. }
  372. }
  373. elseif ($display['type'] == 'video_embed_field_thumbnail_colorbox') {
  374. if (isset($item['thumbnail_path'])) {
  375. $element[$delta] = array(
  376. array(
  377. '#theme' => 'video_embed_field_colorbox_code',
  378. '#image_url' => $item['thumbnail_path'],
  379. '#image_style' => $display['settings']['image_style'],
  380. '#video_url' => $item['video_url'],
  381. '#video_style' => $display['settings']['video_style'],
  382. '#video_data' => unserialize($item['video_data']),
  383. ),
  384. );
  385. }
  386. //incase no thumbnail was downloaded / provider doesn't support thumbnails
  387. else {
  388. $element[$delta] = array(
  389. );
  390. }
  391. }
  392. //Get the HTML instead of the array, because we append it to the suffix.
  393. //This way, the thumbnail link wrapper doesn't make the description a link as well.
  394. $description_html = drupal_render($description);
  395. $pos = isset($settings['description_position']) ? $settings['description_position'] : 'bottom';
  396. if ($pos == 'top') {
  397. $element[$delta]['#prefix'] = isset($element[$delta]['#prefix']) ? $element[$delta]['#prefix'] : '';
  398. $element[$delta]['#prefix'] = $description_html . $element[$delta]['#prefix'];
  399. }
  400. else {
  401. $element[$delta]['#suffix'] = isset($element[$delta]['#suffix']) ? $element[$delta]['#suffix'] : '';
  402. $element[$delta]['#suffix'] .= $description_html;
  403. }
  404. }
  405. return $element;
  406. }