| 1 |
<?php
|
| 2 |
// $Id: transformer.module,v 1.18 2008/03/04 15:24:17 dopry Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
@file
|
| 6 |
provides an api for file transforms and batch file transforms.
|
| 7 |
|
| 8 |
Glossary:
|
| 9 |
transform - a file processing function or batch of file
|
| 10 |
processing functions.(Scale, Rotate, Crop)
|
| 11 |
|
| 12 |
macro - a collection of transforms
|
| 13 |
|
| 14 |
@todo - hook_transform_update/hook_macro_update
|
| 15 |
allow modules like imagecache to react to macro changes, like
|
| 16 |
regenerating output.
|
| 17 |
|
| 18 |
*/
|
| 19 |
|
| 20 |
function transformer_perm() {
|
| 21 |
return array('transform files');
|
| 22 |
}
|
| 23 |
|
| 24 |
|
| 25 |
function transformer_menu($may_cache) {
|
| 26 |
$items = array();
|
| 27 |
if ($may_cache) {
|
| 28 |
$items[] = array( 'path' => 'transformer/macro',
|
| 29 |
'access' => user_access('transform files'),
|
| 30 |
'type' => MENU_CALLBACK,
|
| 31 |
'callback' => 'transform_files',
|
| 32 |
);
|
| 33 |
}
|
| 34 |
return $items;
|
| 35 |
}
|
| 36 |
|
| 37 |
/**
|
| 38 |
* load transforms from hook_transform
|
| 39 |
*/
|
| 40 |
function transformer_transforms() {
|
| 41 |
static $transforms = array();
|
| 42 |
if (empty($transforms)) {
|
| 43 |
$transforms = module_invoke_all('transformer');
|
| 44 |
foreach ($transforms as $base => $transform) {
|
| 45 |
$transforms[$base] = $transform;
|
| 46 |
}
|
| 47 |
}
|
| 48 |
return $transforms;
|
| 49 |
}
|
| 50 |
|
| 51 |
|
| 52 |
/**
|
| 53 |
* Load All Macros.
|
| 54 |
*/
|
| 55 |
|
| 56 |
function transformer_macros() {
|
| 57 |
static $macros = array();
|
| 58 |
if (empty($macros)) {
|
| 59 |
$result = db_query('SELECT macro_id, macro_name FROM {transformer_macro} ORDER BY macro_name');
|
| 60 |
while($row = db_fetch_array($result)) {
|
| 61 |
$macros[$row['macro_id']] = $row['macro_name'];
|
| 62 |
}
|
| 63 |
}
|
| 64 |
return $macros;
|
| 65 |
}
|
| 66 |
|
| 67 |
function transformer_macro($macro) {
|
| 68 |
$macro = (is_numeric($macro)) ? transformer_macro_id($macro) : transformer_macro_name($macro);
|
| 69 |
if ($macro) {
|
| 70 |
$macro['transforms'] = transformer_macro_transforms($macro['macro_id']);
|
| 71 |
}
|
| 72 |
return $macro;
|
| 73 |
}
|
| 74 |
|
| 75 |
// Load a macro by id.
|
| 76 |
function transformer_macro_id($macro_id) {
|
| 77 |
$result = db_query('SELECT macro_id, macro_name FROM {transformer_macro} WHERE macro_id = %d', $macro_id);
|
| 78 |
return db_fetch_array($result);
|
| 79 |
}
|
| 80 |
|
| 81 |
// Load a macro by name
|
| 82 |
function transformer_macro_name($name) {
|
| 83 |
$result = db_query('SELECT macro_id, macro_name FROM {transformer_macro} WHERE macro_name = \'%s\'', $name);
|
| 84 |
return db_fetch_array($result);
|
| 85 |
}
|
| 86 |
|
| 87 |
//get composite transform info for macro
|
| 88 |
function transformer_macro_info($macro) {
|
| 89 |
$info = array();
|
| 90 |
|
| 91 |
// catch macros with no transforms.
|
| 92 |
if (!count($macro['transforms']) || !is_array($macro['transforms'])) {
|
| 93 |
return $info;
|
| 94 |
}
|
| 95 |
|
| 96 |
// merge the transform info into the macro info.
|
| 97 |
foreach ($macro['transforms'] as $id => $transform) {
|
| 98 |
$transform_info = transformer_transform_info($transform);
|
| 99 |
// initialize $info array with first transform
|
| 100 |
if (empty($info)) {
|
| 101 |
$info = array(
|
| 102 |
);
|
| 103 |
continue;
|
| 104 |
}
|
| 105 |
}
|
| 106 |
return $info;
|
| 107 |
}
|
| 108 |
|
| 109 |
// Load transforms for a macro
|
| 110 |
function transformer_macro_transforms($macro_id) {
|
| 111 |
$transforms = array();
|
| 112 |
$result = db_query('SELECT transform_id, weight, base, data FROM {transformer_transform} where macro_id=%d order by weight',$macro_id);
|
| 113 |
while($row = db_fetch_array($result)) {
|
| 114 |
$row['data'] = unserialize($row['data']);
|
| 115 |
$transforms[$row['transform_id']] = $row;
|
| 116 |
}
|
| 117 |
return $transforms;
|
| 118 |
}
|
| 119 |
|
| 120 |
function transformer_macro_create($name) {
|
| 121 |
$id = db_next_id('transformer_macros');
|
| 122 |
if (!db_query('INSERT INTO {transformer_macro} (macro_id, macro_name) VALUES (%d, \'%s\')', $id, $name)) {
|
| 123 |
drupal_set_message('Error creating macro.', 'error');
|
| 124 |
return FALSE;
|
| 125 |
}
|
| 126 |
return $id;
|
| 127 |
}
|
| 128 |
|
| 129 |
function transformer_macro_update($macro) {
|
| 130 |
$name = check_plain($macro['macro_name']);
|
| 131 |
$id = (int)$macro['macro_id'];
|
| 132 |
db_query('UPDATE {transformer_macro} SET macro_name =\'%s\' WHERE macro_id = %d', $name, $id);
|
| 133 |
drupal_set_message('Updated macro '. $id);
|
| 134 |
}
|
| 135 |
|
| 136 |
function transformer_macro_delete($id) {
|
| 137 |
$macro = transformer_macro($id);
|
| 138 |
db_query('DELETE FROM {transformer_transform} where macro_id = %d', $macro['macro_id']);
|
| 139 |
db_query('DELETE FROM {transformer_macro} where macro_id = %d', $macro['macro_id']);
|
| 140 |
drupal_set_message(t('Macro \'%macro_name\' deleted.', array('%macro_name' => $macro['macro_name'])));
|
| 141 |
}
|
| 142 |
|
| 143 |
/**
|
| 144 |
* transform crud functions
|
| 145 |
*/
|
| 146 |
|
| 147 |
function transformer_transform($id) {
|
| 148 |
$result = db_query('SELECT transform_id, macro_id, weight, base, data FROM {transformer_transform} WHERE transform_id = %d', $id);
|
| 149 |
$transform = db_fetch_array($result);
|
| 150 |
$transform['data'] = unserialize($transform['data']);
|
| 151 |
return $transform;
|
| 152 |
}
|
| 153 |
|
| 154 |
function transformer_transform_create($transform) {
|
| 155 |
//debug_msg($transform);
|
| 156 |
$id = db_next_id('transformer_transform');
|
| 157 |
if (!db_query('INSERT INTO {transformer_transform} (transform_id, macro_id, weight, base, data) VALUES (%d, %d, %d, "%s", "%s")', $id, $transform['macro_id'], $transform['weight'], $transform['base'], serialize($transform['data']))) {
|
| 158 |
//drupal_set_message('Error creating transform','error');
|
| 159 |
return FALSE;
|
| 160 |
}
|
| 161 |
return $id;
|
| 162 |
}
|
| 163 |
|
| 164 |
function transformer_transform_update($transform) {
|
| 165 |
//debug_msg($transform);
|
| 166 |
db_query('UPDATE {transformer_transform} SET weight = %d, data = \'%s\' WHERE transform_id = %d', $transform['weight'], serialize($transform['data']), $transform['transform_id']);
|
| 167 |
}
|
| 168 |
|
| 169 |
function transformer_transform_delete($transform) {
|
| 170 |
//drupal_set_message('transformer_macro_transform_delete_form_submit: <pre>'. $transform .'</pre>');
|
| 171 |
db_query('DELETE FROM {transformer_transform} WHERE transform_id = %d', $transform['transform_id']);
|
| 172 |
}
|
| 173 |
|
| 174 |
function transformer_transform_info($transform) {
|
| 175 |
$transforms = transformer_transforms();
|
| 176 |
return $transforms[$transform['base']];
|
| 177 |
}
|
| 178 |
|
| 179 |
/**
|
| 180 |
* transformer_macro_perform()
|
| 181 |
* @param macro
|
| 182 |
* transformer macro array
|
| 183 |
* @param src
|
| 184 |
* src for the macro
|
| 185 |
* @param dst
|
| 186 |
* dst for the final product of the macro
|
| 187 |
* @return bool
|
| 188 |
*/
|
| 189 |
|
| 190 |
function transformer_macro_perform($macro, $src, $dst) {
|
| 191 |
// This function should always recieve a src files.
|
| 192 |
if (!is_file($src)) {
|
| 193 |
watchdog('transformer', t('macro_perform: %src is not a file.', array('%src' => $src)), WATCHDOG_ERROR);
|
| 194 |
return FALSE;
|
| 195 |
}
|
| 196 |
|
| 197 |
// This function should only recieve a destination directory. The file may be renamed by processing.
|
| 198 |
// It will return the final path to the file if it succeeds. It is up to the calling module to update
|
| 199 |
// any paths properly.
|
| 200 |
if (!is_dir($dst)) {
|
| 201 |
watchdog('transformer', t('macro_perform: %dst is not a directory.', array('%dst' => $dst)), WATCHDOG_ERROR);
|
| 202 |
return FALSE;
|
| 203 |
}
|
| 204 |
|
| 205 |
// Load a macro just in case we were passed a macro id, Derivative is guilty of this...
|
| 206 |
if (is_numeric($macro)) {
|
| 207 |
$macro = transformer_macro($macro);
|
| 208 |
}
|
| 209 |
|
| 210 |
// watchdog('transformer', 'macro_perform('. print_r($macro,1) .", $src, $dst)");
|
| 211 |
// validate that there are transforms with this macro.
|
| 212 |
if (!count($macro['transforms'])) {
|
| 213 |
watchdog( 'transformer', t('macro_perform: Macro(%m) has no Transforms.', array('%m' => print_r($macro,1))), WATCHDOG_ERROR);
|
| 214 |
return FALSE;
|
| 215 |
}
|
| 216 |
|
| 217 |
// Initialize media object.
|
| 218 |
// @todo: finish abstract class for media and remove hardwire to ffmpeg_movie class.
|
| 219 |
if(!$media = new ffmpeg_movie($src)) {
|
| 220 |
watchdog('transformer', t('macro_perform: could not open %s', array('%s' => $src)), WATCHDOG_ERROR);
|
| 221 |
return FALSE;
|
| 222 |
}
|
| 223 |
|
| 224 |
foreach($macro['transforms'] as $transform) {
|
| 225 |
if (!transformer_transform_perform($media, $transform)) {
|
| 226 |
watchdog( 'transformer', t('Transform failed: %t.', array('%t' => print_r($transform,1))), WATCHDOG_ERROR);
|
| 227 |
return FALSE;
|
| 228 |
}
|
| 229 |
}
|
| 230 |
|
| 231 |
$srcparts = explode('.', basename($src));
|
| 232 |
array_pop($srcparts); // trash that extension.
|
| 233 |
$filebase = implode('.', $srcparts);
|
| 234 |
|
| 235 |
if (!$dst = $media->write($dst .'/'. $filebase)) {
|
| 236 |
watchdog( 'transformer', t('transformer_macro_perform: Failed to write transformed media to destination.'), WATCHDOG_ERROR);
|
| 237 |
return FALSE;
|
| 238 |
}
|
| 239 |
|
| 240 |
// hackery for video thumbnails..
|
| 241 |
$thumb = $dst .'.thumb.png';
|
| 242 |
$media->seek('00:00:02');
|
| 243 |
$media->cut_frames(1);
|
| 244 |
$media->set_output_format('mjpeg');
|
| 245 |
$thumb = $media->write($thumb, true);
|
| 246 |
|
| 247 |
return $dst;
|
| 248 |
}
|
| 249 |
|
| 250 |
/**
|
| 251 |
* perform a transformation.
|
| 252 |
* @param src
|
| 253 |
* source file
|
| 254 |
* @param dst
|
| 255 |
* destination file
|
| 256 |
* @param transform
|
| 257 |
* transform to perform
|
| 258 |
* @param priority
|
| 259 |
* highest priority level to execute
|
| 260 |
* @return
|
| 261 |
* success = dst
|
| 262 |
* fail = src
|
| 263 |
*/
|
| 264 |
|
| 265 |
function transformer_transform_perform($media, $transform) {
|
| 266 |
//watchdog('transformer', 'transform_perform('. print_r($media,1) .','. print_r($transform,1) .')');
|
| 267 |
$info = transformer_transform_info($transform);
|
| 268 |
|
| 269 |
$mime = mimedetect_mime($media->res);
|
| 270 |
|
| 271 |
$extension = array_pop(explode('.', $src));
|
| 272 |
|
| 273 |
// transforms should bool, success. Their default behavior should be to create a
|
| 274 |
// modified copy of src at dst.
|
| 275 |
if(!call_user_func($transform['base'] .'_perform', $media, $transform['data'])) {
|
| 276 |
watchdog('transformer',
|
| 277 |
t('transformer_transform_perform: Failed %t(media: %media, transform: %transform)',
|
| 278 |
array('%t' => print_r($transform['base'], 1), '%media' => print_r($media,1), '%transform' => print_r($transform,1))),
|
| 279 |
WATCHDOG_ERROR);
|
| 280 |
return FALSE;
|
| 281 |
}
|
| 282 |
return TRUE;
|
| 283 |
}
|
| 284 |
|
| 285 |
|
| 286 |
|
| 287 |
|
| 288 |
|