/[drupal]/contributions/modules/flashnode/flashnode.module
ViewVC logotype

Contents of /contributions/modules/flashnode/flashnode.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.48 - (show annotations) (download) (as text)
Wed Nov 12 21:36:17 2008 UTC (12 months, 2 weeks ago) by stuartgreenfield
Branch: MAIN
CVS Tags: DRUPAL-6--3-0, HEAD
Branch point for: DRUPAL-6--3
Changes since 1.47: +4 -2 lines
File MIME type: text/x-php
Basic and display options not working as expected meaning it was not possible to see just the display settings. Fixed so you can see just basic settings or just the display settings.
1 <?php
2 // $Id: flashnode.module,v 1.47 2008/11/12 21:23:49 stuartgreenfield Exp $
3
4 // Some constant definitions to make later code clearer
5 define('FLASHNODE_TEASER_AND_BODY', 0);
6 define('FLASHNODE_TEASER_ONLY', 1);
7 define('FLASHNODE_BODY_ONLY', 2);
8 define('FLASHNODE_DO_NOT_DISPLAY', 3);
9 define('FLASHNODE_DEFAULT_HTML_ALT', 'You are missing some Flash content that should appear here! Perhaps your browser cannot display it, or maybe it did not initialise correctly.');
10 define('FLASHNODE_DEFAULT_WEIGHT', -0.1);
11 define('FLASHNODE_DEFAULT_IMPORT_STATUS', 0);
12 define('FLASHNODE_DEFAULT_PATH', 'flash');
13 define('FLASHNODE_DEFAULT_EXTENSIONS', 'swf flv mp3');
14
15 /**
16 * Implementation of hook_help
17 */
18 function flashnode_help($path, $arg) {
19 switch ($path) {
20 case 'admin/settings/flashnode':
21 return '<p>'.t('Flash node lets you create nodes that store a piece of Flash animation. You can use it in a basic mode, where the Flash item is always displayed at the start of the node, or you can enable the flash filter to incorporate Flash content in to other nodes.').'</p>';
22 case 'admin/help#flashnode':
23 $flash_test = '';
24 if (defined('SWFTOOLS_INSTALLED')) {
25 $flash_test = '<p>'. theme('flashnode', array(
26 'filepath' => url(drupal_get_path('module', 'flashnode') .'/flashnode_test_file.swf', array('absolute' => TRUE)),
27 'width' => 100,
28 'height' => 100,
29 'substitution' => t('<span class="error">If you can see this text instead of an animation then JavaScript insertion failed. Check that your browser has JavaScript enabled, and if it does check your SWF Tools settings.</span>'),
30 )) .'</p>';
31 }
32 return t('
33 <p>Flash node lets you create nodes that store a piece of <a href="@flash">Flash</a> animation. You can use it in a basic mode, where the Flash item is always displayed at the start of the node, but you can choose whether to have the Flash element displayed in both the teaser and the body, just the teaser, or just the body. You can define the height and width of the Flash element, or you can let the node use the Flash content\'s original settings.</p>
34
35 <p>The module also defines a new input filter called <strong>flashnode</strong> that you can use. This lets you re-use Flash content in other nodes by using the format <strong>[flashnode|nid=&lt;nid&gt;]</strong> in the body of a node. You can pass optional parameters to manipulate the display of the Flash content by including them in the macro. Parameters that are used by flash node are as follows:
36
37 <ul>
38 <li>
39 <strong>width</strong> - set a specific width, in pixels
40 </li><li>
41 <strong>height</strong> - set a specific height, in pixels
42 </li><li>
43 <strong>scale</strong> - scale both width and height to a multiple of the original size
44 </li><li>
45 <strong>xscale</strong> - scale just the width to a multiple of the original size
46 </li><li>
47 <strong>yscale</strong> - scale just the height to a multiple of the original size
48 </li><li>
49 <strong>scalewidth</strong> - set a specific width, in pixels, and automatically adjust the height to maintain the aspect ratio
50 </li><li>
51 <strong>scaleheight</strong> - set a specific height, in pixels, and automatically adjust the width to maintain the aspect ratio
52 </li><li>
53 <strong>flashvars</strong> - set a Flashvars string to pass to the Flash movie
54 </li>
55 </ul>
56
57 For example, to use Flash content from node 10, scaled to 50% of its original size you would use <strong>[flashnode|nid=10|scale=0.5]</strong></p>
58
59 <p>You can include other parameters. These will not be interpreted by flash node, but will be passed on to SWF Tools which may choose to use them.</p>
60
61 <p>Flash node outputs content using HTML embedding and this allows flash node to work without installing any other modules. Using this basic method will result in the \'Click to activate and use this control\' message under Internet Explorer.</p>
62 <p>It is recommended to also install <a href="@swftools">SWF Tools</a> as flash node will then use that to output content instead. This lets you take advantage of JavaScript insertion methods. Installing SWF Tools also enables flash node to play back mp3 and flv files via the players that SWF Tools offers. <em>Note - at this time SWF Tools is not available for Drupal 6. Check the SWF Tools project page for the latest information.</em></p>
63 <p>Flash node will automatically detect SWF Tools when it is installed and content will then be inserted using the method that you specify in the SWF Tools configuration pages. If you have installed SWF Tools and can see an animation playing below then your installation is working properly and you are ready to use flash node with SWF Tools! If you can\'t see it then double check your SWF Tools settings. In particular check that you have downloaded and installed the necessary JavaScript packages. Refer to the SWF Tools documentation for more details.</p>
64 !flashtest
65 <p>For more help refer to the <a href="@documentation">flash node documentation</a> on drupal.org.',
66 array(
67 '@flash' => 'http://www.adobe.com/products/flashplayer',
68 '@swftools' => 'http://drupal.org/project/swftools',
69 '@documentation' => 'http://drupal.org/node/214846',
70 '!flashtest' => $flash_test,
71 )
72 );
73 }
74 }
75
76
77 /**
78 * Implementation of hook_node_info
79 */
80 function flashnode_node_info() {
81 return array(
82 'flashnode' => array(
83 'name' => t('Flash'),
84 'module' => 'flashnode',
85 'description' => t('Allows you to easily upload and display a Flash file. You can choose whether the movie appears in the teaser, the body, or both.'),
86 )
87 );
88 }
89
90
91 /**
92 * Implementation of hook_perm
93 */
94 function flashnode_perm() {
95 return array(
96 'administer flash node',
97 'create flash nodes',
98 'edit own flash nodes',
99 'edit any flash node',
100 'delete own flash nodes',
101 'delete any flash node',
102 'use display options',
103 'use basic options',
104 'use advanced options',
105 'import flash',
106 );
107 }
108
109
110 /**
111 * Implementation of hook_access
112 */
113 function flashnode_access($op, $node, $account) {
114
115 if ($op == 'create') {
116 return user_access('create flash nodes', $account);
117 }
118
119 if ($op == 'update') {
120 if (user_access('edit any flash node', $account) || (user_access('edit own flash nodes', $account) && ($account->uid == $node->uid))) {
121 return TRUE;
122 }
123 }
124
125 if ($op == 'delete') {
126 if (user_access('delete any flash node', $account) || (user_access('delete own flash nodes', $account) && ($account->uid == $node->uid))) {
127 return TRUE;
128 }
129 }
130 }
131
132
133 /**
134 * Implementation of hook_menu
135 */
136 function flashnode_menu() {
137
138 $items = array();
139
140 $items['admin/settings/flashnode'] = array(
141 'title' => 'Flash node',
142 'description' => 'Set various flash node default options.',
143 'page callback' => 'drupal_get_form',
144 'page arguments' => array('flashnode_admin_settings'),
145 'access arguments' => array('administer flash node'),
146 'file' => 'flashnode.admin.inc',
147 );
148
149 $items['admin/content/flashnode'] = array(
150 'title' => 'Import Flash',
151 'description' => 'Import and create nodes from files that have been uploaded directly to the server.',
152 'page callback' => 'drupal_get_form',
153 'page arguments' => array('flashnode_import'),
154 'access arguments' => array('import flash'),
155 'file' => 'flashnode.import.inc',
156 );
157
158 return $items;
159 }
160
161
162 /**
163 * Implementation of hook_validate
164 */
165 function flashnode_validate(&$node) {
166
167 // Check a file has been uploaded
168 if (!$_FILES['files']['name']['flashfile'] && !$node->flashnode['filepath']) {
169 form_set_error('flashfile', t('You must upload a file.'));
170 }
171
172 // Check width is valid (if not empty it must be numeric)
173 if (!empty($node->flashnode['width']) && !is_numeric($node->flashnode['width'])) {
174 form_set_error('flashnode][width', t('You must enter a valid width.'));
175 }
176
177 // Check height is valid (if not empty it must be numeric)
178 if (!empty($node->flashnode['height']) && !is_numeric($node->flashnode['height'])) {
179 form_set_error('flashnode][height', t('You must enter a valid height.'));
180 }
181
182 return;
183 }
184
185
186 /**
187 * Implementation of hook_form
188 */
189 function flashnode_form(&$node) {
190
191 // Need to access user object later to determine if some sections of node form are visible
192 global $user;
193
194 // Check flash directory exists and is writable
195 _flashnode_check_settings();
196
197 // Begin form construct
198 $form['#attributes'] = array('enctype' => 'multipart/form-data');
199
200 // Flash node items require their parents
201 $form['flashnode']['#tree'] = TRUE;
202
203 // Lifted from image.module to handle upload and previews
204 if ($node->new_file) {
205 $form['new_file'] = array('#type' => 'value', '#value' => TRUE);
206 }
207
208 $form['flashnode']['filepath'] = array('#type' => 'value', '#value' => $node->flashnode['filepath']);
209 $form['flashnode']['filename'] = array('#type' => 'value', '#value' => $node->flashnode['filename']);
210 $form['flashnode']['fid'] = array('#type' => 'value', '#value' => $node->flashnode['fid']);
211 $form['flashnode']['_height'] = array('#type' => 'value', '#value' => $node->flashnode['_height']);
212 $form['flashnode']['_width'] = array('#type' => 'value', '#value' => $node->flashnode['_width']);
213
214 // Add title and body fields as required
215 $type = node_get_types('type', $node);
216
217 // Add title if required
218 if ($type->has_title) {
219 $form['title'] = array(
220 '#type' => 'textfield',
221 '#title' => check_plain($type->title_label),
222 '#required' => TRUE,
223 '#default_value' => $node->title,
224 '#weight' => -5,
225 );
226 }
227
228 // Add body area if required
229 if ($type->has_body) {
230 $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
231 }
232
233 // Flash node upload field
234 $form['flashnode']['flashfile'] = array(
235 '#type' => 'file',
236 '#title' => t('Flash file'),
237 '#description' => $node->flashnode['fid'] ? t('Current file is %filename. Click "Browse..." to upload a different file.', array('%filename' => basename($node->flashnode['filepath']))) : t('Click "Browse..." to select a file to upload.'),
238 '#tree' => FALSE,
239 );
240
241 // Put other settings in a collapsible set for a clean input form
242 // We create two sections - basic and advanced
243 // Access to these settings is controlled via user permissions
244
245 // Basic settings
246 $form['flashnode']['basic'] = array(
247 '#type' => 'fieldset',
248 '#title' => t('Basic flash node options'),
249 '#collapsible' => TRUE,
250 '#collapsed' => TRUE,
251 '#tree' => FALSE,
252 '#access' => user_access('use basic options') || user_access('use display options') || ($user->uid == 1),
253 );
254
255 // We over-ride the #parents setting here to strip out ['options']
256 $form['flashnode']['basic']['display'] = array(
257 '#type' => 'radios',
258 '#title' => t('Display in'),
259 '#default_value' => isset($node->flashnode['display']) ? $node->flashnode['display'] : variable_get('flashnode_default_display', FLASHNODE_TEASER_AND_BODY),
260 '#options' => array(
261 FLASHNODE_TEASER_AND_BODY => t('Teaser and body'),
262 FLASHNODE_TEASER_ONLY => t('Teaser only'),
263 FLASHNODE_BODY_ONLY => t('Body only'),
264 FLASHNODE_DO_NOT_DISPLAY => t('Do not display'),
265 ),
266 '#parents' => array('flashnode', 'display'),
267 '#access' => user_access('use display options') || ($user->uid == 1),
268 );
269
270 // We over-ride the #parents setting here to strip out ['options']
271 $form['flashnode']['basic']['width'] = array(
272 '#type' => 'textfield',
273 '#title' => t('Width'),
274 '#default_value' => $node->flashnode['width'],
275 '#size' => 5,
276 '#maxlength' => 5,
277 '#description' => t('The width of the movie, in pixels. Leave blank to use the file\'s own settings.'),
278 '#parents' => array('flashnode', 'width'),
279 '#access' => user_access('use basic options') || ($user->uid == 1),
280 );
281
282 // We over-ride the #parents setting here to strip out ['options']
283 $form['flashnode']['basic']['height'] = array(
284 '#type' => 'textfield',
285 '#title' => t('Height'),
286 '#default_value' => $node->flashnode['height'],
287 '#size' => 5,
288 '#maxlength' => 5,
289 '#description' => t('The height of the movie, in pixels. Leave blank to use the file\'s own settings.'),
290 '#parents' => array('flashnode', 'height'),
291 '#access' => user_access('use basic options') || ($user->uid == 1),
292 );
293
294 // Advanced settings
295 $form['flashnode']['advanced'] = array(
296 '#type' => 'fieldset',
297 '#title' => t('Advanced flash node options'),
298 '#collapsible' => TRUE,
299 '#collapsed' => TRUE,
300 '#tree' => FALSE,
301 '#access' => user_access('use advanced options') || ($user->uid == 1),
302 );
303
304 // We over-ride the #parents setting here to strip out ['options']
305 $form['flashnode']['advanced']['substitution'] = array(
306 '#type' => 'textarea',
307 '#title' => t('Substitution content'),
308 '#rows' => 5,
309 '#default_value' => isset($node->flashnode['substitution']) ? $node->flashnode['substitution'] : '!default',
310 '#parents' => array('flashnode', 'substitution'),
311 '#description' => t('If a javascript method is used to embed flash then this is the content that users will see if they are unable to, or choose not to, display the flash content. This content uses the same input format as the body. The default content may be used by entering @default.', array('@default' => '!default')),
312 );
313
314 // We over-ride the #parents setting here to strip out ['options']
315 $form['flashnode']['advanced']['flashvars'] = array(
316 '#type' => 'textarea',
317 '#title' => t('Flashvars'),
318 '#rows' => 5,
319 '#default_value' => $node->flashnode['flashvars'],
320 '#parents' => array('flashnode', 'flashvars'),
321 '#description' => t('Specify any flashvars that need to be passed to the movie. If the input format allows PHP code you may use PHP to create a dynamic flashvars string.')
322 );
323
324 // We over-ride the #parents setting here to strip out ['options']
325 $form['flashnode']['advanced']['base'] = array(
326 '#type' => 'textfield',
327 '#title' => t('Base'),
328 '#default_value' => isset($node->flashnode['base']) ? $node->flashnode['base'] : variable_get('flashnode_default_base', ''),
329 '#parents' => array('flashnode', 'base'),
330 '#description' => t('Over-ride the default setting with a different base path here if necessary. This setting is needed for movies that use ActionScription functions such as %loadmovie with unqualified paths. Leave blank to let flash node generate a default that points to %defaultbase.', array('%loadmovie' => 'loadMovie()', '%defaultbase' => file_create_url(''))),
331 );
332
333 // We over-ride the #parents setting here to strip out ['options']
334 $form['flashnode']['advanced']['params'] = array(
335 '#type' => 'textfield',
336 '#title' => t('Parameters'),
337 '#default_value' => $node->flashnode['params'],
338 '#parents' => array('flashnode', 'params'),
339 '#description' => t('An optional list of parameters to pass to the flash player when the file is rendered. Refer to !technote for details of parameters that can be used. Note - this feature requires SWF Tools to be used to embed flash content.', array('!technote' => l('Adobe TechNote 12701', 'http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12701'))),
340 );
341
342 // Return form
343 return $form;
344 }
345
346
347 /**
348 * Implementation of hook_load
349 */
350 function flashnode_load(&$node) {
351
352 if ($node->vid) {
353
354 // Retrieve data for this node from combination of {flash} and {files}
355 $result = db_query("SELECT filepath, filename, {flashnode}.* FROM {files} INNER JOIN {flashnode} ON {files}.fid = {flashnode}.fid WHERE {flashnode}.vid = %d", $node->vid);
356 $data = db_fetch_object($result);
357
358 // If no object was retrieved then make $data array empty and output a message
359 if ($data === FALSE) {
360 $data = array();
361 drupal_set_message(t('Unable to load flash node data for node @node.', array('@node' => $node->nid)), 'error');
362 }
363
364 // Store all the settings in to the $node->flashnode object
365 foreach ($data as $parameter => $value) {
366 $node->flashnode[$parameter] = $value;
367 }
368
369 // Generate default base path if not set
370 if (!$flashnode['base']) {
371 $flashnode['base'] = file_create_url('');
372 }
373 }
374 }
375
376
377 /**
378 * Implementation of hook_insert
379 */
380 function flashnode_insert($node) {
381
382 // flashnode_update calls flash_insert, but _update already moved the file
383 // Also, don't move the file if we are running an import - it is already where we want it
384 if (!$node->revision && !$node->flashnode['import']) {
385 // Move the flash file to flash directory
386 _flashnode_file_move($node);
387 }
388
389 // Insert data into {flashnode}
390 db_query("INSERT INTO {flashnode} (nid, height, width, display, substitution, flashvars, base, fid, vid, params) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, '%s')", $node->nid, $node->flashnode['height'], $node->flashnode['width'], $node->flashnode['display'], $node->flashnode['substitution'], $node->flashnode['flashvars'], $node->flashnode['base'], $node->flashnode['fid'], $node->vid, $node->flashnode['params']);
391
392 }
393
394
395 /**
396 * Helper function: Move a new flash file flash directory
397 * Called by flashnode_insert and flashnode_update
398 */
399 function _flashnode_file_move(&$node) {
400
401 // Space can cause problems, so replace them with underscores
402 $filename = str_replace(' ', '_', $node->flashnode['filename']);
403
404 // Create the destination path and filename from the filename
405 $destination = variable_get('flashnode_default_path', FLASHNODE_DEFAULT_PATH) . '/' . $filename;
406
407 // Try to move the flash file to the flash directory, auto renames if it already exists
408 file_move($node->flashnode['filepath'], $destination, FILE_EXISTS_RENAME);
409
410 // Update {files} with new filepath and set status to permanent
411 db_query("UPDATE {files} SET status = %d, filepath = '%s' WHERE fid = %d", FILE_STATUS_PERMANENT, $node->flashnode['filepath'], $node->flashnode['fid']);
412
413 }
414
415
416 /**
417 * Implementation of hook_update
418 */
419 function flashnode_update($node) {
420
421 // Get original vid, but vid to use is different depending if this is a revision or not
422 if ($node->revision) {
423 $vid = $node->old_vid;
424 }
425 else {
426 $vid = $node->vid;
427 }
428
429 // Get the fid and filepath of the original Flash file for this node
430 $old_fid = db_result(db_query("SELECT {flashnode}.fid FROM {flashnode} INNER JOIN {files} ON {flashnode}.fid = {files}.fid WHERE {flashnode}.vid = %d", $vid));
431
432 // If the current fid and existing fid don't match then we have a new file so move it
433 if ($old_fid != $node->flashnode['fid']) {
434 $new_file = TRUE;
435 _flashnode_file_move($node);
436 }
437
438 // If creating a new revision call flashnode_insert, otherwise process update
439 if ($node->revision) {
440 flashnode_insert($node);
441 }
442 else {
443
444 // If a new file was uploaded remove the old file if no longer needed
445 if ($new_file) {
446 _flashnode_delete_file_if_no_longer_needed($old_fid);
447 }
448
449 // Update {flashnode} and {files} with new data
450 db_query("UPDATE {flashnode} SET nid = %d, height = %d, width = %d, display = %d, substitution = '%s', flashvars = '%s', base = '%s', fid = %d, params = '%s' WHERE vid = %d", $node->nid, $node->flashnode['height'], $node->flashnode['width'], $node->flashnode['display'], $node->flashnode['substitution'], $node->flashnode['flashvars'], $node->flashnode['base'], $node->flashnode['fid'], $node->flashnode['params'], $node->vid);
451 db_query("UPDATE {files} SET status = %d, filepath = '%s' WHERE fid = %d", FILE_STATUS_PERMANENT, $node->flashnode['filepath'], $node->flashnode['fid']);
452
453 }
454
455 }
456
457
458 /**
459 * Implementation of hook_delete.
460 */
461 function flashnode_delete($node) {
462
463 // Get all files currently used by this node
464 $result = db_query("SELECT DISTINCT {files}.* FROM {flashnode} INNER JOIN {files} ON {flashnode}.fid = {files}.fid WHERE {flashnode}.nid = %d", $node->nid);
465
466 // Iterate through results and delete file and entry in {files}
467 while ($file = db_fetch_object($result)) {
468 // Delete all files associated with the node
469 db_query("DELETE FROM {files} WHERE fid = %d", $file->fid);
470 file_delete($file->filepath);
471 }
472
473 // Delete the entry from {flashnode}
474 db_query("DELETE FROM {flashnode} WHERE nid = %d", $node->nid);
475
476 }
477
478
479 /**
480 * Implementation of hook_view
481 */
482 function flashnode_view($node, $teaser, $page = 0) {
483
484 // Run through the filters before adding in code, so that markup for Flash is not intercepted
485 $node = node_prepare($node, $teaser);
486
487 // Prepare markup of substitution content by running through node filter
488 $node->flashnode['substitution'] = check_markup($node->flashnode['substitution'], $node->format, FALSE);
489
490 // Check if PHP processing of flashvars is needed
491 $node->flashnode['flashvars'] = _flashnode_php_flashvars($node->flashnode['flashvars'], $node->format);
492
493 // Generate the array to add to the node for display
494 $flash_content = array(
495 '#value' => theme('flashnode', $node->flashnode, $teaser),
496 '#weight' => variable_get('flashnode_weight', FLASHNODE_DEFAULT_WEIGHT),
497 );
498
499 // If we're not in body only mode add flash if a teaser was requested
500 //if ($node->flashnode['display'] != FLASHNODE_BODY_ONLY && $teaser) {
501 if ($node->flashnode['display'] != FLASHNODE_BODY_ONLY && $node->flashnode['display'] != FLASHNODE_DO_NOT_DISPLAY && $teaser) {
502 $node->content['flashnode'] = $flash_content;
503 }
504
505 // If we're not in teaser only mode add flash if the body was requested
506 if ($node->flashnode['display'] != FLASHNODE_TEASER_ONLY && $node->flashnode['display'] != FLASHNODE_DO_NOT_DISPLAY && !$teaser) {
507 $node->content['flashnode'] = $flash_content;
508 }
509
510 // Return the amended node
511 return $node;
512
513 }
514
515
516 /**
517 * Implementation of hook_theme
518 */
519 function flashnode_theme() {
520 return array(
521 'flashnode' => array(
522 'arguments' => array('flashnode' => NULL, 'teaser' => FALSE, 'options' => array()),
523 ),
524 'flashnode_markup' => array(
525 'arguments' => array('flashnode' => NULL, 'options' => array()),
526 ),
527 'flashnode_import_form' => array(
528 'arguments' => array('form' => NULL),
529 'file' => 'flashnode.import.inc',
530 ),
531 );
532 }
533
534
535 /**
536 * Given a flash node nid and option parameters return the HTML string required to
537 * generate the required flash content (this is used by the macro system)
538 *
539 * The substitution content is filtered according to the specified format, and
540 * if no format is specified use the default. This function is called by the
541 * macro filter, but may also be called directly from PHP.
542 *
543 * @param $args
544 * Key Required? Comment
545 * nid Yes nid of the node containing the swf to display
546 * scaleheight No Scale the movie height/width to get requested height
547 * scalewidth No Scale the movie height/width to get the requested width
548 * xscale No Scale movie width by the specified factor
549 * yscale No Scale movie height by the specified factor
550 * scale No Scale height and width by the specified factor
551 * height No Over-ride stored height with the given value
552 * width No Over-ride stored width with the given value
553 * class No Include the given class in the $flash array
554 * flashvars No Include the specified flashvars string in the $flash array
555 * substitution No Over-ride stored substitution markup
556 * @param $format
557 * The filter format to apply to the substitution content. If no format is given
558 * then apply the default format.
559 * @return
560 * Returns the HTML mark up for inserting the flash content, or returns nothing
561 * if the specified nid is not valid
562 */
563 function flashnode_content($args = array(), $format = FILTER_FORMAT_DEFAULT ) {
564
565 // If no $args['nid'], or $arg['nid'] not numeric then set an error
566 if (!is_numeric($args['nid'])) {
567 $error = t('Incorrectly specified macro - <em>nid</em> not specified, or not numeric.');
568 }
569 else {
570 // Try loading via node_load
571 $node = node_load($args['nid']);
572
573 // If type isn't flashnode we can't do anything with this node so set an error
574 if ($node->type != 'flashnode') {
575 $error = t('Macro tried to load node @nid which is not a flash node.', array('@nid' => $args['nid']));
576 }
577 }
578
579 // If the initial phase failed display a message and log in watchdog for admin
580 if ($error) {
581 //drupal_set_message($error, 'error');
582 watchdog('flashnode', $error, NULL, WATCHDOG_ERROR);
583 return;
584 }
585
586 /**
587 * Process flashvars for PHP. To make the site flexible we can choose to let the
588 * parent node use PHP format to create a dynamic flashvar. However, we might
589 * want to allow other nodes to use that dynamic flash, but without letting
590 * them have wider access to the PHP format. So we process flashvars against
591 * the input format of the *parent* node, not this node. If the parent allows
592 * PHP then the flashvars will be processed via the PHP filter. If the user
593 * supplies new flashvars via the macro format then we process again later,
594 * but this time against the format of the node where the macro is running.
595 * This is so that the user doesn't get access to the PHP format via the macro!
596 */
597
598 // Call the _flashnode_php_flashvars function to do the work
599 $node->flashnode['flashvars'] = _flashnode_php_flashvars($node->flashnode['flashvars'], $node->format);
600
601 // Remove $args['nid'] from the array as this isn't a flash modifying parameter
602 unset($args['nid']);
603
604 // Set default scaling parameters
605 $xscale = $yscale = 1;
606
607 // Initialise options array
608 $options = array();
609
610 // Process the arguments array to modify the flash before rendering it
611 if ($args) {
612 foreach ($args as $parameter => $value) {
613
614 switch ($parameter) {
615
616 // Adjust to given width, maintaining aspect ratio
617 case 'scalewidth':
618 if (is_numeric($value) && $node->flashnode['width'] > 0) {
619 $xscale = $yscale = $value / $node->flashnode['width'];
620 }
621 break;
622
623 // Adjust to given height, maintaining aspect ratio
624 case 'scaleheight':
625 if (is_numeric($value) && $node->flashnode['height'] > 0) {
626 $xscale = $yscale = $value / $node->flashnode['height'];
627 }
628 break;
629
630 // Scale width by given factor
631 case 'xscale':
632 if (is_numeric($value)) {
633 $xscale = $value;
634 }
635 break;
636
637 // Scale height by given factor
638 case 'yscale':
639 if (is_numeric($value)) {
640 $yscale = $value;
641 }
642 break;
643
644 // Scale both width and height by given factor
645 case 'scale':
646 if (is_numeric($value)) {
647 $xscale = $yscale = $value;
648 }
649 break;
650
651 // Set height or width to specific value
652 case 'height':
653 case 'width':
654 if (is_numeric($value)) {
655 $node->flashnode[$parameter] = $value;
656 }
657 break;
658
659 // Add class to $node->flashnode array (this is from flashnode 5.1)
660 // This will need updating when SWFTools is finalised.
661 // May no longer be supported / relevant
662 case 'class':
663 $node->flashnode['class'] = $value;
664 break;
665
666 // Over-ride stored flashvars with alternatives
667 case 'flashvars':
668 // If flashvars was set by the macro this over-rides the stored values
669 // this is to allow flash to be re-used. If & has been replaced by &amp;
670 // by another filter then we need to reverse that first
671 $value = str_replace('&amp;', '&', $value);
672 $node->flashnode['flashvars'] = $value;
673
674 // Process for PHP content
675 $node->flashnode['flashvars'] = _flashnode_php_flashvars($node->flashnode['flashvars'], $format);
676 break;
677
678 // Over-ride stored substitution text with alternatives
679 // Can use !default to retrieve default content
680 case 'substitution':
681 $node->flashnode['substitution'] = $value;
682 break;
683
684 // If none of the above, add the parameter and value to $options array
685 default:
686 $options[$parameter] = $value;
687 }
688 }
689 }
690
691 // Apply scaling
692 $node->flashnode['height'] = $node->flashnode['height'] * $yscale;
693 $node->flashnode['width'] = $node->flashnode['width'] * $xscale;
694
695 // Process substitution content through filters for this node
696 $node->flashnode['substitution'] = check_markup($node->flashnode['substitution'], $format, FALSE);
697
698 // Return markup
699 return theme('flashnode', $node->flashnode, FALSE, $options) ;
700
701 }
702
703
704 /**
705 * Process a macro string in to an array of keys and values. Pass the array to
706 * flashnode_content for processing and rendering in to an HTML string
707 */
708 function flashnode_get_macros($text) {
709 $m = array();
710 preg_match_all('/ \[ ([^\[\]]+)* \] /x', $text, $matches);
711 $tag_match = (array) array_unique($matches[1]); // Don't process duplicates.
712
713 foreach ($tag_match as $macro) {
714 $current_macro = '['. $macro .']';
715 $param = array_map('trim', explode('|', $macro));
716
717 // The first macro param is assumed to be the function name.
718 $func_name = array_shift($param);
719
720 // If flash macro found, extra other settings
721 if ($func_name == 'flashnode') {
722 $vars = array();
723 foreach($param as $p) {
724 $pos = strpos($p, '=');
725 $varname = substr($p, 0, $pos);
726 $varvalue = substr($p, $pos + 1);
727 $vars[$varname] = $varvalue;
728 }
729
730 $m[$current_macro] = $vars;
731 }
732 }
733
734 return $m;
735 }
736
737
738 /**
739 * Implementation of hook_filter()
740 */
741 function flashnode_filter($op, $delta = 0, $format = -1, $text = '') {
742
743 switch ($op) {
744
745 case 'list':
746 return array(0 => t('Flash node filter'));
747
748 case 'description':
749 return t('Add Flash from a flash node to your posts using a flash node macro.');
750
751 case 'process':
752 foreach(flashnode_get_macros($text) as $unexpanded_macro => $macro) {
753 $replace = flashnode_content($macro, $format);
754 $search = '@(<p>)?'.preg_quote($unexpanded_macro).'(</p>)?@';
755 $text = preg_replace($search, $replace, $text);
756 }
757 return $text;
758
759 default:
760 return $text;
761 }
762 }
763
764
765 /**
766 * Implementation of hook_filter_tips().
767 */
768 function flashnode_filter_tips($delta, $format, $long = FALSE) {
769 return t('Flash node macros can be added to this post.');
770 }
771
772
773 /**
774 * Check to see if PHP is allowed in this format, and if it is process the flashvars
775 * string through the PHP filter in case there is some code to be handled. Then
776 * the string for safe handling, but turn &amp; back in to & as that is what
777 * flash needs to define the variables in a flashvars string. Return the result.
778 */
779 function _flashnode_php_flashvars($flashvars, $format = -1) {
780
781 // Get the list of filters for this node
782 $filters = filter_list_format($format);
783
784 // Look for module == php to see if we have PHP allowed for this node
785 foreach ($filters as $filter) {
786 if ($filter->module == 'php') {
787 $flashvars = module_invoke($filter->module, 'filter', 'process', $filter->delta, $format, $flashvars);
788 }
789 }
790
791 // Encode flashvars to make it safe for inclusion on the page
792 $flashvars = check_plain($flashvars);
793
794 // But we need to undo conversion of & to &amp;
795 $flashvars = str_replace('&amp;', '&', $flashvars);
796
797 return $flashvars;
798
799 }
800
801
802 /**
803 * Verify that the flash and flash/temp directories exist and create them if they don't
804 * flash/temp is required to make the node preview function work correctly
805 */
806 function _flashnode_check_settings() {
807
808 // Build the relevant paths
809 $flashnode_path = file_create_path(variable_get('flashnode_default_path', FLASHNODE_DEFAULT_PATH));
810 $flashnode_temp_path = $flashnode_path.'/temp';
811
812 // Check if directories exist, create them if not
813 file_check_directory($flashnode_path, FILE_CREATE_DIRECTORY, 'flashnode_default_path');
814 file_check_directory($flashnode_temp_path, FILE_CREATE_DIRECTORY);
815
816 }
817
818
819 /**
820 * Perform some post-processing on submitted form to populate node with data from the uploaded file
821 */
822 function flashnode_node_form_submit($form, &$form_state) {
823
824 // Get upload filesize limits
825 global $user;
826 $limits = _flashnode_file_limits($user);
827
828 // Use file validators to confirm upload size and extensions
829 $validators = array(
830 'file_validate_size' => array($limits['file_size'], $limits['user_size']),
831 'file_validate_extensions' => array($limits['extensions']),
832 );
833
834 // Check if the upload is valid and move to the temporary folder
835 if ($file = file_save_upload('flashfile', $validators, file_create_path(variable_get('flashnode_default_path', FLASHNODE_DEFAULT_PATH).'/temp'))) {
836
837 // Add needed file data to the $form_state['values'] array
838 $form_state['values']['flashnode']['filepath'] = $file->filepath;
839 $form_state['values']['flashnode']['filename'] = $file->filename;
840 $form_state['values']['flashnode']['fid'] = $file->fid;
841 $form_state['values']['new_file'] = TRUE;
842
843 // Reset default height so we force defaults to be repopulated in a few moments
844 unset($form_state['values']['flashnode']['_height']);
845
846 // If the height and width settings are not available to this user then reset them everytime we get a new file
847 // Otherwise the height/width will be locked to the first file that is uploaded
848 global $user;
849 if (!user_access('use basic options') && ($user->uid != 1)) {
850 unset($form_state['values']['flashnode']['height']);
851 unset($form_state['values']['flashnode']['width']);
852 }
853
854 // If upload is not swf remind user to set movie size
855 if (!preg_match('@swf$@i', $file->filename)) {
856 drupal_set_message(t('Remember you might have to set the movie size for flv or mp3 files as flash node cannot always automatically determine the player size!'), 'warning');
857 }
858 }
859
860 // See if the default height and width need to be populated (previewing an existing node, or a new file)
861 if (!$form_state['values']['flashnode']['_height']) {
862 // Try to get the file settings for this file, using image_get_info
863 $info = image_get_info($form_state['values']['flashnode']['filepath']);
864 $form_state['values']['flashnode']['_height'] = $info['height'];
865 $form_state['values']['flashnode']['_width'] = $info['width'];
866 }
867
868 // If width field is empty then reset it to the default width
869 if (empty($form_state['values']['flashnode']['width'])) {
870 $form_state['values']['flashnode']['width'] = $form_state['values']['flashnode']['_width'];
871 $form_state['rebuild'] = TRUE;
872 }
873
874 // If height field is empty then reset it to the default height
875 if (empty($form_state['values']['flashnode']['height'])) {
876 $form_state['values']['flashnode']['height'] = $form_state['values']['flashnode']['_height'];
877 $form_state['rebuild'] = TRUE;
878 }
879
880 }
881
882
883 /**
884 * Implementation of hook_nodeapi().
885 */
886 function flashnode_nodeapi(&$node, $op, $teaser) {
887 switch ($op) {
888
889 case 'delete revision':
890
891 // Only take action if deleting a flashnode revision
892 if ($node->type == 'flashnode') {
893 flashnode_delete_revision($node);
894 }
895 break;
896
897 case 'rss item':
898 if ($node->type == 'flashnode') {
899 $link = '<p>'. t('Click <a href="@url">here</a> to view Flash content.', array('@url' => url("node/$node->nid", array('absolute' => TRUE)))) . '</p>';
900 $node->body = $node->body . $link;
901 $node->teaser = $node->teaser . $link;
902 }
903 return array();
904 }
905 }
906
907
908 /**
909 * Delete a flashnode revision
910 */
911 function flashnode_delete_revision($node) {
912
913 // Delete the file if it is no longer needed when this revision is removed
914 _flashnode_delete_file_if_no_longer_needed($node->flashnode['fid']);
915
916 // Delete this revision from {flashnode}
917 db_query("DELETE FROM {flashnode} WHERE vid = %d", $node->vid);
918
919 }
920
921
922 /**
923 * Helper function: Remove a flash file from the file table and file system if it is
924 * no longer needed as a result of revision deletion or update
925 */
926 function _flashnode_delete_file_if_no_longer_needed($fid) {
927
928 // Check how many times the file is listed in {flashnode}
929 $result = db_result(db_query("SELECT COUNT(fid) FROM {flashnode} WHERE fid = %d", $fid));
930
931 // If only one occurrence then it is no longer needed because this revision is
932 // about to be deleted, or this revision is about to get a new upload
933 if ($result == 1) {
934
935 // Get the file path from the files table
936 $filepath = db_result(db_query("SELECT filepath FROM {files} WHERE fid = %d", $fid));
937
938 // Delete from the file system and {files}
939 db_query("DELETE FROM {files} WHERE fid = %d", $fid);
940 file_delete($filepath);
941
942 }
943
944 }
945
946
947 /**
948 * Create the HTML for insertion of Flash
949 * This theme function will constrain the size of the content according to the limits
950 * set on the configuration page. It then calls a secondary theme function to produce
951 * the actual HTML markup.
952 *
953 * @param $flashnode
954 * A structured array that defines an item of Flash content. Must include
955 * keys filepath (path to the file), width, height, substitution (string containing
956 * HTML mark up for the substitution content), and optionally flashvars. Other keys
957 * may be included and they will be passed through to SWFTools.
958 * Key Comment
959 * filepath path to an swf file to theme
960 * width display width of the swf file
961 * height display height of the movie
962 * substitution substitution content to use if using JavaScript insertion
963 * flashvars flashvars string to pass to the swf file
964 * base base parameter to pass to the swf fil
965 * @param $teaser
966 * Flag to indicate whether teaser content is being generated. Not used by flash node
967 * but could be used by other themers to provide different output depending on mode
968 * @param $options
969 * Optional array of other parameters that will passed through to swf tools theme function
970 * @return
971 * An HTML string for rendering the flash content
972 */
973 function theme_flashnode($flashnode, $teaser = FALSE, $options = array()) {
974
975 // Get height and width limits according to view mode, and if in teaser mode then apply teaser scaling
976 if ($teaser) {
977 $max_width = variable_get('flashnode_max_teaser_width', 0);
978 $max_height = variable_get('flashnode_max_teaser_height', 0);
979 $teaser_scale = variable_get('flashnode_teaser_scale', 1);
980 $flashnode['width'] = $flashnode['width'] * $teaser_scale;
981 $flashnode['height'] = $flashnode['height'] * $teaser_scale;
982 }
983 else {
984 $max_width = variable_get('flashnode_max_width', 0);
985 $max_height = variable_get('flashnode_max_height', 0);
986 }
987
988 // Check width does not exceed defined maximum, and scale if required
989 if ($max_width) {
990 if ($flashnode['width'] > $max_width) {
991 $scale = $max_width / $flashnode['width'];
992 $flashnode['width'] = $flashnode['width'] * $scale;
993 $flashnode['height'] = $flashnode['height'] * $scale;
994 }
995 }
996
997 // Now check height does not exceed defined maximum, and scale if required
998 if ($max_height) {
999 if ($flashnode['height'] > $max_height) {
1000 $scale = $max_height / $flashnode['height'];
1001 $flashnode['width'] = $flashnode['width'] * $scale;
1002 $flashnode['height'] = $flashnode['height'] * $scale;
1003 }
1004 }
1005
1006 // Generate output
1007 $output .= theme('flashnode_markup', $flashnode, $options);
1008
1009 // Return the HTML
1010 return $output;
1011
1012 }
1013
1014
1015 /**
1016 * Generate HTML mark for flash content, using SWF Tools if it is available
1017 *
1018 * Flash node uses SWF Tools to handle JavaScript replacement but this isn't
1019 * always easy to set up. To assist users flash node will fall back to direct
1020 * HTML embedding if it can't find SWF Tools. This means flash node will work
1021 * 'out of the box' in a basic fashion, and is extended when SWF Tools is available
1022 * rather than being entirely dependent upon it.
1023 *
1024 * This function is called with an array of parameters that define a flashnode and an
1025 * optional array of parameters for swf tools.
1026 *
1027 * See the description of theme_flashnode for details.
1028 */
1029 function theme_flashnode_markup($flashnode, $options = array()) {
1030
1031 // Generate HTML markup, using SWF Tools if available, fallback if not
1032 if (defined('SWFTOOLS_INSTALLED')) {
1033
1034 // Add width, height and base to $params for SWF Tools, rounding width and height to integers
1035 $params = array(
1036 'width' => round($flashnode['width']),
1037 'height' => round($flashnode['height']),
1038 'base' => $flashnode['base'],
1039 );
1040
1041 // Create additional parameters if any are provided, and merge
1042 $params = array_merge($params, flashnode_get_params($flashnode['params']));
1043
1044 // Retrieve default substitution content if required
1045 // Note we are bypassing the filters here, so we assume the administrator
1046 // created valid mark-up that everyone else can use!
1047 $preview = t($flashnode['substitution'], array('!default' => variable_get('flashnode_default_html_alt', FLASHNODE_DEFAULT_HTML_ALT)));
1048 $othervars = array_merge($options, array('html_alt' => $preview));
1049
1050 // Get HTML from SWF Tools
1051 $options = array(
1052 'params' => $params,
1053 'flashvars' => $flashnode['flashvars'],
1054 'othervars' => $othervars,
1055 );
1056
1057 $file = $flashnode['filepath'];
1058
1059 // If using public download then encoding spaces that the upload module may have allowed
1060 // Private downloads will do this for us
1061 if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) {
1062 $file = str_replace(' ', '%20', $file);
1063 }
1064
1065 $output .= swf(file_create_url($file), $options);
1066
1067 // Return result
1068 return $output;
1069 }
1070
1071 // Initialise variable to ensure we only show error once if trying to render mp3 or flv with basic embedding
1072 static $markup_error_shown = false;
1073
1074 // If file type is flv or mp3 we can't show it without SWF Tools
1075 if (preg_match('@flv|mp3$@i', $flashnode['filepath'])) {
1076 if (!$markup_error_shown) {
1077 drupal_set_message(t('Flash node needs <a href="@swftools">SWF Tools</a> in order to play mp3 or flv files.', array('@swftools' => 'http://drupal.org/project/swftools')), 'warning');
1078 $markup_error_shown = true;
1079 }
1080 return;
1081 }
1082
1083 // Use t() to substitute parameters in to basic Flash markup
1084 $output = t('<div class="flashnode"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="!width" height="!height" id="myMovieName"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="true" /><param name="movie" value="!filepath" /><param name="quality" value="high" /><param name="flashvars" value="!flashvars" /><param name="base" value="!base" /><embed src="!filepath" allowScriptAccess="sameDomain" allowFullScreen="true" quality="high" width="!width" height="!height" flashvars="!flashvars" name="myMovieName" align="" type="application/x-shockwave-flash" base="!base" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object></div>',
1085 array(
1086 '!height' => $flashnode['height'],
1087 '!width' => $flashnode['width'],
1088 '!filepath' => file_create_url($flashnode['filepath']),
1089 '!flashvars' => $flashnode['flashvars'],
1090 '!base' => $flashnode['base'],
1091 )
1092 );
1093
1094 return $output;
1095
1096 }
1097
1098
1099 /**
1100 * Helper function to return array of permitted file sizes and extensions for the specified user
1101 * Note - this basically replicates an equivalent function from upload.module
1102 */
1103 function _flashnode_file_limits($user) {
1104
1105 // Get default upload limits
1106 $file_limit = variable_get('upload_uploadsize_default', 1);
1107 $user_limit = variable_get('upload_usersize_default', 1);
1108
1109 // Get default allowable extensions and initialise extensions array for results
1110 $flashnode_default_extensions = variable_get('flashnode_default_extensions', FLASHNODE_DEFAULT_EXTENSIONS);
1111 $all_extensions = array();
1112
1113 // Collect permissions for all roles this user belongs to
1114 foreach ($user->roles as $rid => $name) {
1115 $extensions = variable_get("flashnode_extensions_$rid", $flashnode_default_extensions);
1116 $all_extensions = array_merge($all_extensions, explode(' ', $extensions));
1117
1118 // A zero value indicates no limit, take the least restrictive limit.
1119 $file_size = variable_get("upload_uploadsize_$rid", variable_get('upload_uploadsize_default', 1)) * 1024 * 1024;
1120 $file_limit = ($file_limit && $file_size) ? max($file_limit, $file_size) : 0;
1121
1122 $user_size = variable_get("upload_usersize_$rid", variable_get('upload_usersize_default', 1)) * 1024 * 1024;
1123 $user_limit = ($user_limit && $user_size) ? max($user_limit, $user_size) : 0;
1124 }
1125 $all_extensions = implode(' ', array_unique($all_extensions));
1126
1127 // Return results as an array
1128 return array(
1129 'extensions' => $all_extensions,
1130 'file_size' => $file_limit,
1131 'user_size' => $user_limit,
1132 );
1133 }
1134
1135
1136 /**
1137 * Implementation of hook_file_download
1138 * To allow flash node to work with a private file system
1139 */
1140 function flashnode_file_download($file) {
1141
1142 // See if this file belongs to flash node by querying database
1143 $file = file_create_path($file);
1144 $result = db_query("SELECT fi.*, fl.nid FROM {files} fi INNER JOIN {flashnode} fl ON fi.fid = fl.fid WHERE filepath = '%s'", $file);
1145
1146 // See if we got a result
1147 if ($file = db_fetch_object($result)) {
1148
1149 // Check if the user is allowed to view this node, and if they are, return headers, else return access denied
1150 $node = node_load($file->nid);
1151 if (node_access('view', $node)) {
1152 return array(
1153 'Content-Type: '. $file->filemime,
1154 'Content-Length: '. $file->filesize,
1155 );
1156 }
1157 else {
1158 return -1;
1159 }
1160 }
1161 }
1162
1163
1164 /**
1165 * Convert a string in the form parameter=value in to an array
1166 */
1167 function flashnode_get_params($parameters_string) {
1168 // parse query string into associative array
1169 $params = array();
1170 if ($parameters_string != '')
1171 {
1172 foreach (explode(' ', $parameters_string) as $kvpair)
1173 {
1174 list($key, $value) = explode('=', $kvpair);
1175 $params[$key] = $value;
1176 }
1177 }
1178
1179 return $params;
1180 }
1181
1182 /**
1183 * Register flash node with Views
1184 */
1185 function flashnode_views_api() {
1186 return array(
1187 'api' => 2.000,
1188 'path' => drupal_get_path('module', 'flashnode') . '/views',
1189 );
1190 }

  ViewVC Help
Powered by ViewVC 1.1.2