video_embed_field.field.inc 13 KB

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