externalvideo: Added support for various media sources
[mahara:mahara.git] / htdocs / blocktype / externalvideo / lib.php
1 <?php
2 /**
3  * Mahara: Electronic portfolio, weblog, resume builder and social networking
4  * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
5  *                         http://wiki.mahara.org/Contributors
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  * @package    mahara
21  * @subpackage blocktype-externalvideo
22  * @author     Catalyst IT Ltd
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24  * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25  *
26  */
27
28 defined('INTERNAL') || die();
29
30 /**
31  * todos before this block type can be considered complete
32  *  - document this class and methods
33  *  - correct category
34  *  - more video url sources, and good default behaviour
35  *  - block title editable
36  *  - i18n
37  *  - minvalue/maxvalue rules
38  */
39 class PluginBlocktypeExternalvideo extends SystemBlocktype {
40
41     private static $media_sources = array(
42         'youtube',
43         'teachertube',
44         'scivee',
45         'googlevideo',
46         'glogster',
47         'slideshare',
48         'voicethread',
49         'wikieducator',
50         'prezi',
51     );
52
53     public static function get_title() {
54         return get_string('title', 'blocktype.externalvideo');
55     }
56
57     public static function get_description() {
58         return get_string('description', 'blocktype.externalvideo');
59     }
60
61     public static function get_categories() {
62         return array('external');
63     }
64
65     private static function load_media_sources() {
66         static $loaded_sources = array();
67
68         if (!empty($loaded_sources)) {
69             return $loaded_sources;
70         }
71
72         foreach (self::$media_sources as $source) {
73             include_once('media_sources/' . $source . '/mediasource.php');
74             $sourcename = 'Media_' . $source;
75             $loaded_sources[$source] = new $sourcename;
76         }
77         return $loaded_sources;
78     }
79
80     public static function render_instance(BlockInstance $instance, $editing=false) {
81         $configdata = $instance->get('configdata');
82         $result = '';
83         $width  = (!empty($configdata['width'])) ? hsc($configdata['width']) : 0;
84         $height = (!empty($configdata['height'])) ? hsc($configdata['height']) : 0;
85
86         if (isset($configdata['videoid'])) {
87             $url = hsc($configdata['videoid']);
88
89             // IE seems to wait for all elements on the page to load
90             // fully before the onload event goes off.  This means the
91             // view editor isn't initialised until all videos have
92             // finished loading, and an invalid video URL can stop the
93             // editor from loading and result in an uneditable view.
94
95             // Therefore, when this block appears on first load of the
96             // view editing page, keep the embed code out of the page
97             // initially and add it in after the page has loaded.
98
99             $embed = '';
100
101             if (isset($configdata['type']) && $configdata['type'] == 'embed') {
102                 $embed  = '<object width="' . $width . '" height="' . $height . '">';
103                 $embed .= '<param name="movie" value="' . $url . '"></param>';
104                 $embed .= '<param name="wmode" value="transparent"></param>';
105                 $embed .= '<param name="allowscriptaccess" value="never"></param>';
106                 $embed .= '<embed src="' . $url . '" ';
107                 $embed .= 'type="application/x-shockwave-flash" wmode="transparent" width="' . $width . '" ';
108                 $embed .= 'height="' . $height . '" allowscriptaccess="never"></embed></object>';
109             }
110             else if (isset($configdata['type']) && $configdata['type'] == 'iframe') {
111                 $embed  = '<iframe width="' . $width . '" height="' . $height . '" ';
112                 $embed .= 'src="' . $url . '" frameborder=0></iframe>';
113             }
114
115             $block = $instance->get('id');
116             $configuring = $block == param_integer('blockconfig', 0);
117
118             $result .= '<div class="mediaplayer-container center">';
119             $result .= '<div id="vid_' . $block . '" class="mediaplayer" style="width: ' . $width . 'px; height: ' . $height . 'px; margin: 0 auto;">';
120
121             if (!$editing || $configuring) {
122                 $result .= $embed;
123             }
124
125             $result .= '</div></div>';
126
127             if ($editing && !$configuring) {
128                 $result .= '<script>';
129                 $result .= 'addLoadEvent(function() {$(\'vid_' . $block . "').innerHTML = " . json_encode($embed) . ';});';
130                 $result .= '</script>';
131             }
132         }
133         return $result;
134     }
135
136     public static function has_instance_config() {
137         return true;
138     }
139
140     public static function instance_config_form($instance) {
141         $configdata = $instance->get('configdata');
142
143         return array(
144             'videoid' => array(
145                 'type'  => 'text',
146                 'title' => get_string('videourl','blocktype.externalvideo'),
147                 'description' => get_string('videourldescription2','blocktype.externalvideo') . self::get_html_of_supported_websites(),
148                 'width' => '90%',
149                 'defaultvalue' => isset($configdata['videoid']) ? $configdata['videoid'] : null,
150                 'rules' => array(
151                     'required' => true,
152                 ),
153             ),
154             'width' => array(
155                 'type' => 'text',
156                 'title' => get_string('width','blocktype.externalvideo'),
157                 'size' => 3,
158                 'rules' => array(
159                     'regex'  => '#\d+%?#',
160                     'minvalue' => 0,
161                     'maxvalue' => 2000,
162                 ),
163                 'defaultvalue' => (!empty($configdata['width'])) ? $configdata['width'] : 0,
164             ),
165             'height' => array(
166                 'type' => 'text',
167                 'title' => get_string('height','blocktype.externalvideo'),
168                 'size' => 3,
169                 'rules' => array(
170                     'regex'  => '#\d+%?#',
171                     'minvalue' => 0,
172                     'maxvalue' => 2000,
173                 ),
174                 'defaultvalue' => (!empty($configdata['height'])) ? $configdata['height'] : 0,
175             ),
176         );
177     }
178
179     public static function instance_config_validate(Pieform $form, $values) {
180         if ($values['videoid']) {
181             $sources = self::load_media_sources();
182
183             $valid = false;
184             foreach ($sources as $name => $source) {
185                 if ($valid = $source->validate_url($values['videoid'])) {
186                     break;
187                 }
188             }
189             if (!$valid) {
190                 $form->set_error('videoid', get_string('invalidurl', 'blocktype.externalvideo'));
191             }
192         }
193     }
194
195     public static function instance_config_save($values) {
196         $title = $values['title'];
197         $values = self::process_url($values['videoid'], $values['width'], $values['height']);
198         $values['title'] = $title;
199         return $values;
200     }
201
202     private static function process_url($url, $width=0, $height=0) {
203         $sources = self::load_media_sources();
204
205         foreach ($sources as $name => $source) {
206             if ($result = $source->process_url($url, $width, $height)) {
207                 return $result;
208             }
209         }
210         return false;
211     }
212
213     /**
214      * Returns a block of HTML that the external video block can use to list
215      * which video sites are supported.
216      */
217     private static function get_html_of_supported_websites() {
218         $source_instances = self::load_media_sources();
219
220         $wwwroot = get_config('wwwroot');
221         $html    = '<ul style="list-style-type: none;" class="inlinelist">';
222
223         foreach ($source_instances as $name => $source) {
224             $sourcestr = get_string($name, 'blocktype.externalvideo');
225             $html .= '<li><a href="' . $source->get_base_url() . '" target="_blank"><img src="' . $wwwroot . 'blocktype/externalvideo/media_sources/' . $name . '/favicon.png" alt="' . $sourcestr . '" title="' . $sourcestr . '"></a></li>';
226         }
227         $html .= '</ul>';
228
229         return $html;
230     }
231
232     public static function default_copy_type() {
233         return 'full';
234     }
235
236 }