| 1 |
<?php
|
| 2 |
// $Id: render.module,v 1.11 2009/01/17 20:13:55 sun Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Implements an administrative interface for various CSS/JS-based rendering
|
| 7 |
* technologies.
|
| 8 |
*
|
| 9 |
* @todo Implement generic download handler for all generated files.
|
| 10 |
* @todo Allow different rules for each site.
|
| 11 |
*/
|
| 12 |
|
| 13 |
/**
|
| 14 |
* Implementation of hook_menu().
|
| 15 |
*/
|
| 16 |
function render_menu() {
|
| 17 |
$items['admin/config/media/render'] = array(
|
| 18 |
'title' => 'Dynamic Rendering',
|
| 19 |
'description' => 'Configure which elements in a theme are rendered.',
|
| 20 |
'access arguments' => array('administer site configuration'),
|
| 21 |
'page callback' => 'render_rules',
|
| 22 |
);
|
| 23 |
$items['admin/config/media/render/rules'] = array(
|
| 24 |
'title' => 'Rules',
|
| 25 |
'access arguments' => array('administer site configuration'),
|
| 26 |
'page callback' => 'render_rules',
|
| 27 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 28 |
'weight' => -2,
|
| 29 |
);
|
| 30 |
$items['admin/config/media/render/addrule'] = array(
|
| 31 |
'title' => 'Add rule',
|
| 32 |
'access arguments' => array('administer site configuration'),
|
| 33 |
'page callback' => 'drupal_get_form',
|
| 34 |
'page arguments' => array('render_add_rule'),
|
| 35 |
'type' => MENU_LOCAL_ACTION,
|
| 36 |
'weight' => -1,
|
| 37 |
);
|
| 38 |
$items['admin/config/media/render/manage'] = array(
|
| 39 |
'title' => 'Manage fonts',
|
| 40 |
'access arguments' => array('administer site configuration'),
|
| 41 |
'page callback' => 'render_manage',
|
| 42 |
'type' => MENU_LOCAL_TASK,
|
| 43 |
'weight' => 2,
|
| 44 |
);
|
| 45 |
$items['admin/config/media/render/cache-clear'] = array(
|
| 46 |
'title' => 'Clear cache',
|
| 47 |
'access arguments' => array('administer site configuration'),
|
| 48 |
'page callback' => 'render_flush_caches',
|
| 49 |
'page arguments' => array(TRUE),
|
| 50 |
'type' => MENU_LOCAL_TASK,
|
| 51 |
'weight' => 10,
|
| 52 |
);
|
| 53 |
$items['render/download'] = array(
|
| 54 |
'title' => 'Download font file',
|
| 55 |
'page callback' => 'render_octet_download',
|
| 56 |
'access arguments' => array('administer site configuration'),
|
| 57 |
'type' => MENU_CALLBACK,
|
| 58 |
);
|
| 59 |
$items['admin/config/media/render/edit/%'] = array(
|
| 60 |
'title' => 'Edit',
|
| 61 |
'access arguments' => array('administer site configuration'),
|
| 62 |
'page callback' => 'render_edit_rule',
|
| 63 |
'page arguments' => array(5),
|
| 64 |
);
|
| 65 |
$items['admin/config/media/render/duplicate'] = array(
|
| 66 |
'access arguments' => array('administer site configuration'),
|
| 67 |
'page callback' => 'render_duplicate_rule',
|
| 68 |
'type' => MENU_CALLBACK,
|
| 69 |
'weight' => 5,
|
| 70 |
);
|
| 71 |
$items['admin/config/media/render/rules/delete/%'] = array(
|
| 72 |
'title' => 'Delete rule',
|
| 73 |
'access arguments' => array('administer site configuration'),
|
| 74 |
'page callback' => 'drupal_get_form',
|
| 75 |
'page arguments' => array('render_delete_rule_form', 6),
|
| 76 |
);
|
| 77 |
$items['admin/config/media/render/deletefont'] = array(
|
| 78 |
'title' => 'Delete font',
|
| 79 |
'access arguments' => array('administer site configuration'),
|
| 80 |
'page callback' => 'render_fontdelete_confirm',
|
| 81 |
'type' => MENU_CALLBACK,
|
| 82 |
'weight' => 6,
|
| 83 |
);
|
| 84 |
return $items;
|
| 85 |
}
|
| 86 |
|
| 87 |
/**
|
| 88 |
* Implementation of hook_init().
|
| 89 |
*/
|
| 90 |
function render_init() {
|
| 91 |
render_all_pages();
|
| 92 |
}
|
| 93 |
|
| 94 |
/**
|
| 95 |
* Retrieve all available plugins.
|
| 96 |
*/
|
| 97 |
function render_plugins() {
|
| 98 |
static $plugins;
|
| 99 |
|
| 100 |
if (isset($plugins)) {
|
| 101 |
return $plugins;
|
| 102 |
}
|
| 103 |
|
| 104 |
$dir = drupal_get_path('module', 'render') .'/plugins';
|
| 105 |
$listing = file_scan_directory($dir, '/.+\.inc/', array('nomask' => '/(\.\.?|CVS|\.svn)$/', 'recurse' => FALSE));
|
| 106 |
$plugins = array();
|
| 107 |
foreach ($listing as $key => $file) {
|
| 108 |
include_once $file->uri;
|
| 109 |
$function = $file->name .'_render_info';
|
| 110 |
if (function_exists($function)) {
|
| 111 |
$plugin = $function();
|
| 112 |
$plugins[$plugin['name']] = $plugin;
|
| 113 |
}
|
| 114 |
}
|
| 115 |
|
| 116 |
return $plugins;
|
| 117 |
}
|
| 118 |
|
| 119 |
/**
|
| 120 |
* List the rules.
|
| 121 |
*/
|
| 122 |
function render_rules() {
|
| 123 |
$plugins = render_plugins();
|
| 124 |
$rules = render_get_rules();
|
| 125 |
$renderdir = drupal_get_path('module', 'render');
|
| 126 |
$header = array(t('Plugin'), t('Rule Name'), t('CSS Selector'), t('Font'), t('Colors'), t('Weight'), t('Operations'));
|
| 127 |
$rows = array();
|
| 128 |
$img_edit = theme('image', $renderdir .'/images/editor.png');
|
| 129 |
$img_duplicate = theme('image', $renderdir .'/images/copy.png');
|
| 130 |
$img_delete = theme('image', $renderdir .'/images/delete.png');
|
| 131 |
foreach ($rules as $r) {
|
| 132 |
$function = $r['plugin'] .'_render_rules';
|
| 133 |
if (function_exists($function)) {
|
| 134 |
$fontstyle = $function($r);
|
| 135 |
}
|
| 136 |
$color_names = array(
|
| 137 |
'color' => t('Font color'),
|
| 138 |
'linkcolor' => t('Link color'),
|
| 139 |
'hovercolor' => t('Hover color'),
|
| 140 |
'bgcolor' => t('Background color'),
|
| 141 |
);
|
| 142 |
$colors = '';
|
| 143 |
foreach ($fontstyle['colors'] as $key => $color) {
|
| 144 |
$colors .= '<div class="render-font-color" style="background-color: '. $color .';" title="'. $color_names[$key] .'"> </div>';
|
| 145 |
}
|
| 146 |
$operations = array(
|
| 147 |
l($img_edit, 'admin/config/media/render/edit/'. $r['rid'], array('attributes' => array('title' => t('Edit'), 'class' => array('render-rule-op')), 'html' => TRUE)),
|
| 148 |
l($img_duplicate, 'admin/config/media/render/duplicate/'. $r['rid'], array('attributes' => array('title' => t('Duplicate'), 'class' => array('render-rule-op')), 'html' => TRUE)),
|
| 149 |
l($img_delete, 'admin/config/media/render/rules/delete/'. $r['rid'], array('attributes' => array('title' => t('Delete'), 'class' => array('render-rule-op')), 'html' => TRUE)),
|
| 150 |
);
|
| 151 |
$rows[] = array(
|
| 152 |
$plugins[$r['plugin']]['title'],
|
| 153 |
$r['name'],
|
| 154 |
$r['selector'],
|
| 155 |
$fontstyle['font'],
|
| 156 |
$colors,
|
| 157 |
$r['weight'],
|
| 158 |
implode('', $operations),
|
| 159 |
);
|
| 160 |
}
|
| 161 |
$output = theme('table', $header, $rows, array('class' => array('render-rules')));
|
| 162 |
|
| 163 |
// Display logos of supported plugins.
|
| 164 |
$output .= '<h4>'. t('Supported plugins') .'</h4>';
|
| 165 |
$plugin_links = array();
|
| 166 |
foreach ($plugins as $plugin) {
|
| 167 |
$logo = $renderdir .'/plugins/'. $plugin['name'] .'.png';
|
| 168 |
if (file_exists($logo)) {
|
| 169 |
$plugin_links[] = l(theme('image', $logo, $plugin['title'], $plugin['title'], array()), $plugin['url'], array('html' => TRUE));
|
| 170 |
}
|
| 171 |
else {
|
| 172 |
$plugin_links[] = l($plugin['title'], $plugin['url']);
|
| 173 |
}
|
| 174 |
}
|
| 175 |
$output .= implode(' | ', $plugin_links);
|
| 176 |
|
| 177 |
drupal_add_css($renderdir .'/render.css');
|
| 178 |
|
| 179 |
return $output;
|
| 180 |
}
|
| 181 |
|
| 182 |
/**
|
| 183 |
* Clear cache after module is enabled.
|
| 184 |
*/
|
| 185 |
function render_enable() {
|
| 186 |
render_flush_caches();
|
| 187 |
}
|
| 188 |
|
| 189 |
/**
|
| 190 |
* Clear dynamic rendering cache.
|
| 191 |
*/
|
| 192 |
function render_flush_caches($redirect = FALSE) {
|
| 193 |
// Re-scan plugin directories.
|
| 194 |
render_find_render(NULL, TRUE);
|
| 195 |
|
| 196 |
// Regenerate list of active plugins.
|
| 197 |
render_get_rules();
|
| 198 |
|
| 199 |
// Regenerate all JavaScript and Stylesheet files for all plugins and rules.
|
| 200 |
$active_plugins = variable_get('render_plugins', array());
|
| 201 |
foreach ($active_plugins as $plugin) {
|
| 202 |
render_render_rules_js($plugin);
|
| 203 |
render_css_screen($plugin);
|
| 204 |
}
|
| 205 |
|
| 206 |
if ($redirect) {
|
| 207 |
drupal_goto('admin/config/media/render');
|
| 208 |
}
|
| 209 |
}
|
| 210 |
|
| 211 |
/**
|
| 212 |
* Manage font files page; menu callback.
|
| 213 |
*/
|
| 214 |
function render_manage() {
|
| 215 |
$delimg = theme('image', drupal_get_path('module', 'render') .'/images/delete.png');
|
| 216 |
$header = array(t('Font'), t('Location'), '');
|
| 217 |
$rows = array();
|
| 218 |
foreach (render_get_fonts() as $file => $name) {
|
| 219 |
$rows[] = array(
|
| 220 |
$name,
|
| 221 |
$file,
|
| 222 |
l($delimg .' '. t('delete'), 'admin/config/media/render/deletefont/'. urlencode($file), array('html' => TRUE)),
|
| 223 |
);
|
| 224 |
}
|
| 225 |
$output = theme('table', $header, $rows, array('style' => 'width:100%'));
|
| 226 |
$output .= drupal_render(drupal_get_form('render_upload'));
|
| 227 |
return $output;
|
| 228 |
}
|
| 229 |
|
| 230 |
/**
|
| 231 |
* Render a form to upload a new font file.
|
| 232 |
*/
|
| 233 |
function render_upload($form, &$form_state) {
|
| 234 |
$form['#attributes'] = array('enctype' => 'multipart/form-data');
|
| 235 |
|
| 236 |
// Display help for each plugin.
|
| 237 |
$form['help'] = array(
|
| 238 |
'#markup' => '<p />',
|
| 239 |
);
|
| 240 |
$plugins = render_plugins();
|
| 241 |
foreach ($plugins as $plugin) {
|
| 242 |
$function = $plugin['name'] .'_render_help';
|
| 243 |
if (function_exists($function) && $plugin_help = $function()) {
|
| 244 |
$form['help'][$plugin['name']] = array(
|
| 245 |
'#type' => 'fieldset',
|
| 246 |
'#collapsible' => TRUE,
|
| 247 |
'#collapsed' => TRUE,
|
| 248 |
'#title' => t('@plugin instructions', array('@plugin' => $plugin['title'])),
|
| 249 |
);
|
| 250 |
$form['help'][$plugin['name']]['help'] = array(
|
| 251 |
'#markup' => $plugin_help,
|
| 252 |
);
|
| 253 |
}
|
| 254 |
}
|
| 255 |
$form['renderfile'] = array(
|
| 256 |
'#type' => 'file',
|
| 257 |
'#title' => t('Upload font file'),
|
| 258 |
'#description' => t('Select the font file that you created using the instructions above.'),
|
| 259 |
'#size' => 40,
|
| 260 |
);
|
| 261 |
$form['submit'] = array(
|
| 262 |
'#type' => 'submit',
|
| 263 |
'#value' => t('Save'),
|
| 264 |
);
|
| 265 |
|
| 266 |
return $form;
|
| 267 |
}
|
| 268 |
|
| 269 |
/**
|
| 270 |
* Form validation callback for render_upload form.
|
| 271 |
*/
|
| 272 |
function render_upload_validate($form, &$form_state) {
|
| 273 |
// @todo Implement file mime type info in render plugins and return FALSE
|
| 274 |
// here, if the uploaded file is not supported by at least one plugin.
|
| 275 |
}
|
| 276 |
|
| 277 |
/**
|
| 278 |
* Form submit callback for render_upload form.
|
| 279 |
*/
|
| 280 |
function render_upload_submit($form, &$form_state) {
|
| 281 |
$dir = 'public://render';
|
| 282 |
// Creates directory if needed.
|
| 283 |
if (file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
|
| 284 |
if ($file = file_save_upload('renderfile', array(), $dir)) {
|
| 285 |
$file->status = FILE_STATUS_PERMANENT;
|
| 286 |
file_save($file);
|
| 287 |
drupal_set_message(t('New font file uploaded.'));
|
| 288 |
}
|
| 289 |
else {
|
| 290 |
drupal_set_message(t('File could not be saved.'), 'error');
|
| 291 |
}
|
| 292 |
}
|
| 293 |
else {
|
| 294 |
drupal_set_message(t('Cannot create render directory in files.'), 'error');
|
| 295 |
}
|
| 296 |
}
|
| 297 |
|
| 298 |
/**
|
| 299 |
* Create a new rendering rule.
|
| 300 |
*
|
| 301 |
* Since multiple rendering plugins can support the same font file types
|
| 302 |
* we need to ask for the plugin to use before a rule can be created.
|
| 303 |
*/
|
| 304 |
function render_add_rule($form, &$form_state) {
|
| 305 |
$form['plugin_select'] = array(
|
| 306 |
'#type' => 'fieldset',
|
| 307 |
'#title' => t('Available plugins'),
|
| 308 |
);
|
| 309 |
$form['plugin'] = array(
|
| 310 |
'#type' => 'value',
|
| 311 |
'#required' => TRUE,
|
| 312 |
);
|
| 313 |
foreach (render_plugins() as $plugin) {
|
| 314 |
$function = $plugin['name'] .'_render_setup';
|
| 315 |
if (function_exists($function)) {
|
| 316 |
if ($function()) {
|
| 317 |
$form['plugin_select'][$plugin['name']] = array(
|
| 318 |
'#type' => 'radio',
|
| 319 |
'#title' => $plugin['title'],
|
| 320 |
'#name' => 'plugin',
|
| 321 |
'#return_value' => $plugin['name'],
|
| 322 |
);
|
| 323 |
}
|
| 324 |
}
|
| 325 |
}
|
| 326 |
$form['submit'] = array(
|
| 327 |
'#type' => 'submit',
|
| 328 |
'#value' => t('Next'),
|
| 329 |
);
|
| 330 |
return $form;
|
| 331 |
}
|
| 332 |
|
| 333 |
/**
|
| 334 |
* Form submit callback for render_add_rule form.
|
| 335 |
*/
|
| 336 |
function render_add_rule_submit($form, &$form_state) {
|
| 337 |
if (isset($form_state['values']['plugin'])) {
|
| 338 |
drupal_goto('admin/config/media/render/edit/'. check_plain($form_state['values']['plugin']));
|
| 339 |
}
|
| 340 |
}
|
| 341 |
|
| 342 |
/**
|
| 343 |
* Edit a rendering rule; menu callback.
|
| 344 |
*
|
| 345 |
* @param $edit
|
| 346 |
* An array or object of rule parameters.
|
| 347 |
*
|
| 348 |
* @return
|
| 349 |
* A form to edit a rule.
|
| 350 |
*/
|
| 351 |
function render_edit_rule($edit = NULL) {
|
| 352 |
if (is_numeric($edit)) {
|
| 353 |
if (isset($_POST['op']) && $_POST['op'] == t('Delete')) {
|
| 354 |
drupal_goto('admin/config/media/render/rules/delete/'. $edit);
|
| 355 |
}
|
| 356 |
else {
|
| 357 |
$rule = render_load_rule($edit);
|
| 358 |
}
|
| 359 |
}
|
| 360 |
else if (is_string($edit)) {
|
| 361 |
$rule['plugin'] = check_plain($edit);
|
| 362 |
}
|
| 363 |
$font_select = $rule = (array)$rule;
|
| 364 |
$rules = array();
|
| 365 |
|
| 366 |
// Override font colors for font selection.
|
| 367 |
$font_select['color'] = '#000000';
|
| 368 |
$font_select['linkcolor'] = '#000000';
|
| 369 |
$font_select['hovercolor'] = '#000000';
|
| 370 |
$font_select['bgcolor'] = '#FFFFFF';
|
| 371 |
$font_select['fontsize'] = '16px';
|
| 372 |
$fonts = render_get_fonts($rule['plugin']);
|
| 373 |
foreach ($fonts as $path => $name) {
|
| 374 |
$font_select['selector'] = '.render-font-'. str_replace(array(' ', '_', '.'), '-', $name);
|
| 375 |
$font_select['font'] = $path;
|
| 376 |
$rules[] = render_render_rule_js($font_select);
|
| 377 |
}
|
| 378 |
|
| 379 |
// Ensure that plugin is properly loaded.
|
| 380 |
$function = $rule['plugin'] .'_render_load';
|
| 381 |
if (function_exists($function)) {
|
| 382 |
$function();
|
| 383 |
}
|
| 384 |
// Certain plugins like sIFR require some basic CSS to work properly. Thus, we
|
| 385 |
// need to create the CSS and JS files, even if there are no rules yet.
|
| 386 |
render_css_screen($rule['plugin'], FALSE);
|
| 387 |
drupal_add_css(file_create_url('public://render/' . $rule['plugin'] . '-screen.css'), array('weight' => CSS_THEME, 'preprocess' => FALSE));
|
| 388 |
drupal_add_js(render_wrap_rules($rule['plugin'], $rules, TRUE), array('type' => 'inline', 'scope' => 'header'));
|
| 389 |
|
| 390 |
drupal_add_css(drupal_get_path('module', 'render') . '/render.css', array('preprocess' => FALSE));
|
| 391 |
|
| 392 |
return drupal_get_form('render_rule', $rule);
|
| 393 |
}
|
| 394 |
|
| 395 |
/**
|
| 396 |
* Form builder function for add/edit rule form.
|
| 397 |
*
|
| 398 |
* @param $edit
|
| 399 |
* An array containing a rendering rule.
|
| 400 |
*/
|
| 401 |
function render_rule($form, &$form_state, $edit) {
|
| 402 |
if (!empty($edit['rid'])) {
|
| 403 |
$form['rid'] = array(
|
| 404 |
'#type' => 'hidden',
|
| 405 |
'#value' => $edit['rid'],
|
| 406 |
);
|
| 407 |
drupal_set_title(t('Edit replacement rule %name', array('%name' => $edit['name'])), PASS_THROUGH);
|
| 408 |
}
|
| 409 |
else {
|
| 410 |
drupal_set_title(t('Add a new rendering rule'));
|
| 411 |
}
|
| 412 |
$edit += array(
|
| 413 |
'name' => '',
|
| 414 |
'selector' => '',
|
| 415 |
'font' => '',
|
| 416 |
'weight' => 0,
|
| 417 |
);
|
| 418 |
|
| 419 |
$form['plugin'] = array(
|
| 420 |
'#type' => 'value',
|
| 421 |
'#value' => $edit['plugin'],
|
| 422 |
'#required' => TRUE,
|
| 423 |
);
|
| 424 |
|
| 425 |
$form['basics'] = array(
|
| 426 |
'#type' => 'fieldset',
|
| 427 |
'#title' => t('Basics'),
|
| 428 |
);
|
| 429 |
$form['basics']['name'] = array(
|
| 430 |
'#type' => 'textfield',
|
| 431 |
'#title' => t('Rule Name'),
|
| 432 |
'#default_value' => $edit['name'],
|
| 433 |
'#required' => TRUE,
|
| 434 |
'#description' => t('The human readable name for this rule.'),
|
| 435 |
);
|
| 436 |
$form['basics']['selector'] = array(
|
| 437 |
'#type' => 'textfield',
|
| 438 |
'#title' => t('Selector'),
|
| 439 |
'#default_value' => $edit['selector'],
|
| 440 |
'#description' => t('A CSS / HTML selector for the elements you want to replace.'),
|
| 441 |
'#required' => TRUE,
|
| 442 |
);
|
| 443 |
$form['basics']['selectorhelp'] = array(
|
| 444 |
'#type' => 'fieldset',
|
| 445 |
'#title' => t('CSS Selector Help'),
|
| 446 |
'#collapsible' => TRUE,
|
| 447 |
'#collapsed' => TRUE,
|
| 448 |
);
|
| 449 |
$form['basics']['selectorhelp']['contents'] = array(
|
| 450 |
'#markup' => '<p>'. t('The supported CSS selectors are !selector1, !selector2 and !selector3. Whitespace is used to select descendants. Whitespace should only be used for this, so instead of !whitespace1 use !whitespace2. Multiple selectors may be used by seperating them with a comma ("!separator").', array(
|
| 451 |
'!selector1' => '<code>#</code>',
|
| 452 |
'!selector2' => '<code>></code>',
|
| 453 |
'!selector3' => '<code>.</code>',
|
| 454 |
'!whitespace1' => '<code>#foo > p</code>',
|
| 455 |
'!whitespace2' => '<code>#foo>p</code>',
|
| 456 |
'!separator' => '<code>,</code>',
|
| 457 |
)) .'</p>',
|
| 458 |
);
|
| 459 |
$form['basics']['selectorhelp']['contents']['#markup'] .= '<p>'. t('Selectors are dependent on your theme. Examine the HTML source to find appropriate classes and ids being output by your current theme. The following are example selectors based on the default Garland theme:') .'</p>';
|
| 460 |
$form['basics']['selectorhelp']['contents']['#markup'] .= '<ul>'. t('!site-title-prefix Site title !suffix
|
| 461 |
!page-title-prefix Page title !suffix
|
| 462 |
!node-titles-prefix Node titles !suffix
|
| 463 |
!block-titles-prefix Block titles !suffix
|
| 464 |
!comment-titles-prefix Comment titles !suffix', array(
|
| 465 |
'!site-title-prefix' => '<li><a href="" onclick="document.getElementById(\'edit-selector\').value = \'#header h1 span\';return false;">',
|
| 466 |
'!page-title-prefix' => '<li><a href="" onclick="document.getElementById(\'edit-selector\').value = \'#tabs-wrapper h2\';return false;">',
|
| 467 |
'!node-titles-prefix' => '<li><a href="" onclick="document.getElementById(\'edit-selector\').value = \' .node h2\';return false;">',
|
| 468 |
'!block-titles-prefix' => '<li><a href="" onclick="document.getElementById(\'edit-selector\').value = \' .block h2\';return false;">',
|
| 469 |
'!comment-titles-prefix' => '<li><a href="" onclick="document.getElementById(\'edit-selector\').value = \' .comment h3\';return false;">',
|
| 470 |
'!suffix' => '</a></li>',
|
| 471 |
)) .'</ul>';
|
| 472 |
|
| 473 |
$form['basics']['weight'] = array(
|
| 474 |
'#type' => 'weight',
|
| 475 |
'#title' => t('Weight'),
|
| 476 |
'#description' => t('You can adjust the order in which the rules are executed by changing their weights. Lighter items are executed before heavier.'),
|
| 477 |
'#delta' => 10,
|
| 478 |
'#default_value' => $edit['weight'],
|
| 479 |
);
|
| 480 |
|
| 481 |
$function = $edit['plugin'] .'_render_rule';
|
| 482 |
if (function_exists($function)) {
|
| 483 |
$function($form, $edit);
|
| 484 |
}
|
| 485 |
|
| 486 |
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
|
| 487 |
if (!empty($edit['rid'])) {
|
| 488 |
$form['actions']['delete'] = array('#type' => 'button', '#value' => t('Delete'));
|
| 489 |
}
|
| 490 |
|
| 491 |
return $form;
|
| 492 |
}
|
| 493 |
|
| 494 |
/**
|
| 495 |
* Form submit callback for render_rule form.
|
| 496 |
*/
|
| 497 |
function render_rule_submit($form, &$form_state) {
|
| 498 |
render_save_rule($form_state['values']);
|
| 499 |
|
| 500 |
// Regenerate list of active plugins.
|
| 501 |
render_get_rules($form_state['values']['plugin'], TRUE);
|
| 502 |
// Create the CSS file.
|
| 503 |
render_css_screen($form_state['values']['plugin']);
|
| 504 |
// Create the JS file.
|
| 505 |
render_render_rules_js($form_state['values']['plugin']);
|
| 506 |
// Change query-strings on CSS/JS files to enforce reload for all users.
|
| 507 |
_drupal_flush_css_js();
|
| 508 |
|
| 509 |
$form_state['redirect'] = 'admin/config/media/render';
|
| 510 |
}
|
| 511 |
|
| 512 |
/**
|
| 513 |
* Form builder function for delete rule form.
|
| 514 |
*/
|
| 515 |
function render_delete_rule_form($form, &$form_state, $rid = NULL) {
|
| 516 |
if (!isset($rid) || !($rule = render_load_rule($rid))) {
|
| 517 |
drupal_goto('admin/config/media/render');
|
| 518 |
}
|
| 519 |
$form['rid'] = array(
|
| 520 |
'#type' => 'hidden',
|
| 521 |
'#value' => $rule['rid'],
|
| 522 |
);
|
| 523 |
return confirm_form($form, t('Are you sure you want to delete the rule %rule?', array('%rule' => $rule['name'])), 'admin/config/media/render');
|
| 524 |
};
|
| 525 |
|
| 526 |
/**
|
| 527 |
* Form submit callback for delete rule form.
|
| 528 |
*/
|
| 529 |
function render_delete_rule_form_submit($form, &$form_state) {
|
| 530 |
if ($form_state['values']['op'] == t('Confirm')) {
|
| 531 |
$rule = render_load_rule($form_state['values']['rid']);
|
| 532 |
db_query('DELETE FROM {render} WHERE rid = :rid', array(':rid' => $form_state['values']['rid']));
|
| 533 |
drupal_set_message(t('Rule %name has been deleted.', array('%name' => $rule['name'])));
|
| 534 |
render_render_rules_js($rule['plugin']);
|
| 535 |
render_css_screen($rule['plugin']);
|
| 536 |
}
|
| 537 |
|
| 538 |
$form_state['redirect'] = 'admin/config/media/render';
|
| 539 |
}
|
| 540 |
|
| 541 |
/**
|
| 542 |
* Delete font page; menu callback.
|
| 543 |
*/
|
| 544 |
function render_fontdelete_confirm() {
|
| 545 |
$args = func_get_args();
|
| 546 |
$fontfile = implode('/', $args);
|
| 547 |
|
| 548 |
if (!$fontfile) {
|
| 549 |
drupal_goto('admin/config/media/render/manage');
|
| 550 |
}
|
| 551 |
return drupal_get_form('render_fontdelete_confirm_form', $fontfile);
|
| 552 |
}
|
| 553 |
|
| 554 |
/**
|
| 555 |
* Form builder function for delete font form.
|
| 556 |
*/
|
| 557 |
function render_fontdelete_confirm_form($form, &$form_state, $fontfile) {
|
| 558 |
$form['render_fontfile'] = array('#type' => 'hidden', '#value' => $fontfile);
|
| 559 |
return confirm_form($form, t("Are you sure you want to delete the file "%fontfile"?", array('%fontfile' => $fontfile)), 'admin/config/media/render/manage');
|
| 560 |
}
|
| 561 |
|
| 562 |
/**
|
| 563 |
* Form submit callback for delete font form.
|
| 564 |
*/
|
| 565 |
function render_fontdelete_confirm_form_submit($form, &$form_state) {
|
| 566 |
if ($form_state['values']['op'] == t('Confirm')) {
|
| 567 |
render_font_delete($form_state['values']['render_fontfile']);
|
| 568 |
}
|
| 569 |
$form_state['redirect'] = 'admin/config/media/render/manage';
|
| 570 |
}
|
| 571 |
|
| 572 |
/**
|
| 573 |
* Delete a font file.
|
| 574 |
*/
|
| 575 |
function render_font_delete($fontfile) {
|
| 576 |
if (file_delete($fontfile)) {
|
| 577 |
drupal_set_message(t('The font %file has been deleted.', array('%file' => $fontfile)));
|
| 578 |
}
|
| 579 |
else {
|
| 580 |
drupal_set_message(t('There was a problem deleting the font file.'), 'error');
|
| 581 |
}
|
| 582 |
}
|
| 583 |
|
| 584 |
/**
|
| 585 |
* Return form radio items for font selection.
|
| 586 |
*
|
| 587 |
* @param array $form
|
| 588 |
* A form array containing rule definitions.
|
| 589 |
* @param string $field
|
| 590 |
* A field name to append the selection.
|
| 591 |
*/
|
| 592 |
function render_font_select($form, $field) {
|
| 593 |
$fonts = render_get_fonts($form['plugin']);
|
| 594 |
|
| 595 |
$font_select = array();
|
| 596 |
foreach ($fonts as $path => $filename) {
|
| 597 |
$name = substr($filename, 0, strrpos($filename, '.'));
|
| 598 |
$font_select[][$field] = array(
|
| 599 |
'#type' => 'radio',
|
| 600 |
'#title' => '<span class="render-font-'. str_replace(array(' ', '_', '.'), '-', $filename) .' render-font">'. $filename .'</span>',
|
| 601 |
'#return_value' => $path,
|
| 602 |
'#default_value' => $form[$field],
|
| 603 |
);
|
| 604 |
}
|
| 605 |
return $font_select;
|
| 606 |
}
|
| 607 |
|
| 608 |
/**
|
| 609 |
* Scan files/render for font files.
|
| 610 |
*
|
| 611 |
* @return array
|
| 612 |
* An array with filepath => filename pairs.
|
| 613 |
*
|
| 614 |
* @todo Additionally search current theme for font files.
|
| 615 |
*/
|
| 616 |
function render_get_fonts($plugin = NULL) {
|
| 617 |
$fonts = array();
|
| 618 |
|
| 619 |
// Build the file mask.
|
| 620 |
$mask = array();
|
| 621 |
$plugins = render_plugins();
|
| 622 |
if (isset($plugin)) {
|
| 623 |
if (isset($plugins[$plugin]) && !empty($plugins[$plugin]['file_masks'])) {
|
| 624 |
$mask = $plugins[$plugin]['file_masks'];
|
| 625 |
}
|
| 626 |
}
|
| 627 |
else {
|
| 628 |
foreach ($plugins as $plugin) {
|
| 629 |
if (!empty($plugin['file_masks'])) {
|
| 630 |
$mask = array_merge($mask, $plugin['file_masks']);
|
| 631 |
}
|
| 632 |
}
|
| 633 |
}
|
| 634 |
$mask = '/' . implode('|', $mask) . '/';
|
| 635 |
|
| 636 |
$files = file_scan_directory('public://render', $mask, array('recurse' => FALSE));
|
| 637 |
foreach ($files as $file) {
|
| 638 |
$fonts[$file->uri] = basename($file->name);
|
| 639 |
}
|
| 640 |
|
| 641 |
return $fonts;
|
| 642 |
}
|
| 643 |
|
| 644 |
/**
|
| 645 |
* Fetch rules from database.
|
| 646 |
*
|
| 647 |
* @param $plugin
|
| 648 |
* An optional plugin name to limit the query.
|
| 649 |
* @param $reset
|
| 650 |
* (optional) TRUE to reload rules from the database.
|
| 651 |
*
|
| 652 |
* @return
|
| 653 |
* An array of rules.
|
| 654 |
*/
|
| 655 |
function render_get_rules($plugin = NULL, $reset = FALSE) {
|
| 656 |
static $rules = array();
|
| 657 |
|
| 658 |
if (!empty($rules) && !$reset) {
|
| 659 |
return $rules;
|
| 660 |
}
|
| 661 |
|
| 662 |
if (isset($plugin)) {
|
| 663 |
$result = db_query("SELECT * FROM {render} WHERE plugin = :plugin ORDER BY weight", array(':plugin' => $plugin), array('fetch' => PDO::FETCH_ASSOC));
|
| 664 |
}
|
| 665 |
else {
|
| 666 |
$result = db_query('SELECT * FROM {render} ORDER BY weight', array(), array('fetch' => PDO::FETCH_ASSOC));
|
| 667 |
}
|
| 668 |
foreach ($result as $rule) {
|
| 669 |
// Unserialize custom plugin properties.
|
| 670 |
$properties = unserialize($rule['properties']);
|
| 671 |
$rule = array_merge($rule, $properties);
|
| 672 |
|
| 673 |
$rules[$rule['rid']] = $rule;
|
| 674 |
}
|
| 675 |
|
| 676 |
// Store active plugins in a variable.
|
| 677 |
if (!isset($plugin)) {
|
| 678 |
$active_plugins = array();
|
| 679 |
foreach ($rules as $rule) {
|
| 680 |
$active_plugins[$rule['plugin']] = $rule['plugin'];
|
| 681 |
}
|
| 682 |
variable_set('render_plugins', $active_plugins);
|
| 683 |
}
|
| 684 |
|
| 685 |
return $rules;
|
| 686 |
}
|
| 687 |
|
| 688 |
/**
|
| 689 |
* Fetch a rule from the database.
|
| 690 |
*/
|
| 691 |
function render_load_rule($rid) {
|
| 692 |
$rule = db_query('SELECT * FROM {render} WHERE rid = :rid', array(':rid' => $rid))->fetchAssoc();
|
| 693 |
|
| 694 |
// Unserialize custom plugin properties.
|
| 695 |
$properties = unserialize($rule['properties']);
|
| 696 |
$rule = array_merge($rule, $properties);
|
| 697 |
|
| 698 |
return $rule;
|
| 699 |
}
|
| 700 |
|
| 701 |
/**
|
| 702 |
* Save a rule in the database.
|
| 703 |
*
|
| 704 |
* @param $edit
|
| 705 |
* An array from the rule add/edit form.
|
| 706 |
*/
|
| 707 |
function render_save_rule($edit) {
|
| 708 |
// Serialize custom plugin properties.
|
| 709 |
$plugins = render_plugins();
|
| 710 |
$fields = array_flip(_render_fields());
|
| 711 |
$properties = array();
|
| 712 |
foreach ($edit as $key => $val) {
|
| 713 |
if (in_array($key, $plugins[$edit['plugin']]['properties'])) {
|
| 714 |
$properties[$key] = $val;
|
| 715 |
unset($edit[$key]);
|
| 716 |
}
|
| 717 |
elseif (!isset($fields[$key])) {
|
| 718 |
unset($edit[$key]);
|
| 719 |
}
|
| 720 |
}
|
| 721 |
$edit['properties'] = serialize($properties);
|
| 722 |
|
| 723 |
db_merge('render')
|
| 724 |
->key(array(
|
| 725 |
'rid' => !empty($edit['rid']) ? $edit['rid'] : NULL,
|
| 726 |
))
|
| 727 |
->fields($edit)
|
| 728 |
->execute();
|
| 729 |
|
| 730 |
drupal_set_message(t('Rule %rule has been saved.', array('%rule' => $edit['name'])));
|
| 731 |
}
|
| 732 |
|
| 733 |
/**
|
| 734 |
* Duplicate an existing render rule.
|
| 735 |
*
|
| 736 |
* @param int $rid
|
| 737 |
* A rule id of an existing rule.
|
| 738 |
*/
|
| 739 |
function render_duplicate_rule($rid) {
|
| 740 |
$rule = render_load_rule($rid);
|
| 741 |
$rule['name'] = $rule['name'] .' ('. t('Dupe') .')';
|
| 742 |
unset($rule['rid']);
|
| 743 |
render_save_rule($rule);
|
| 744 |
|
| 745 |
drupal_goto('admin/config/media/render');
|
| 746 |
}
|
| 747 |
|
| 748 |
/**
|
| 749 |
* Find the directory of each plugin and save locations in a variable.
|
| 750 |
*
|
| 751 |
* Recurses into the render.module's directory to find the shallowest
|
| 752 |
* file dependency of all plugins.
|
| 753 |
*
|
| 754 |
* This removes the need for administrators to rename a plugin's directory
|
| 755 |
* when they place it into the module directory.
|
| 756 |
*
|
| 757 |
* @param string $plugin
|
| 758 |
* An internal name of a plugin. (optional)
|
| 759 |
* @param bool $reset
|
| 760 |
* Whether to clear the plugin directory cache.
|
| 761 |
*
|
| 762 |
* @return array
|
| 763 |
* An array containing the directory for each plugin.
|
| 764 |
*/
|
| 765 |
function render_find_render($plugin_name = NULL, $reset = FALSE) {
|
| 766 |
$plugins = render_plugins();
|
| 767 |
|
| 768 |
if (!$reset) {
|
| 769 |
$dirs = variable_get('render_plugin_dirs', array());
|
| 770 |
}
|
| 771 |
else {
|
| 772 |
variable_del('render_plugin_dirs');
|
| 773 |
$dirs = array();
|
| 774 |
}
|
| 775 |
// If plugin name is given and we already know the directory, return it.
|
| 776 |
if (isset($plugin_name) && isset($dirs[$plugin_name]) && $dirs[$plugin_name]) {
|
| 777 |
return $dirs[$plugin_name];
|
| 778 |
}
|
| 779 |
|
| 780 |
$dirs = array();
|
| 781 |
$renderdir = drupal_get_path('module', 'render');
|
| 782 |
foreach ($plugins as $name => $plugin) {
|
| 783 |
if (!isset($dirs[$name])) {
|
| 784 |
$mask = '/' . preg_quote($plugin['dependencies'][0], '/') . '/';
|
| 785 |
$files = file_scan_directory($renderdir, $mask);
|
| 786 |
// The first one is the shallowest, use it.
|
| 787 |
if ($file = array_shift($files)) {
|
| 788 |
$dirs[$name] = substr($file->uri, 0, strlen($file->uri) - strlen(basename($file->uri)) - 1);
|
| 789 |
}
|
| 790 |
}
|
| 791 |
}
|
| 792 |
|
| 793 |
// Cache the results.
|
| 794 |
if (!empty($dirs)) {
|
| 795 |
variable_set('render_plugin_dirs', $dirs);
|
| 796 |
}
|
| 797 |
|
| 798 |
// If plugin name is given, return only that plugin directory.
|
| 799 |
if (isset($plugin_name)) {
|
| 800 |
if (isset($dirs[$plugin_name])) {
|
| 801 |
return $dirs[$plugin_name];
|
| 802 |
}
|
| 803 |
else {
|
| 804 |
// Plugin is malformed, directory was not found, or name does not exist.
|
| 805 |
return FALSE;
|
| 806 |
}
|
| 807 |
}
|
| 808 |
else {
|
| 809 |
return !empty($dirs) ? $dirs : FALSE;
|
| 810 |
}
|
| 811 |
}
|
| 812 |
|
| 813 |
/**
|
| 814 |
* Add JavaScripts and Stylesheets for all active plugins to all pages.
|
| 815 |
*/
|
| 816 |
function render_all_pages() {
|
| 817 |
static $done;
|
| 818 |
if ($done) {
|
| 819 |
return;
|
| 820 |
}
|
| 821 |
$plugins = render_plugins();
|
| 822 |
$active_plugins = variable_get('render_plugins', array());
|
| 823 |
foreach ($plugins as $plugin) {
|
| 824 |
if (in_array($plugin['name'], $active_plugins)) {
|
| 825 |
$function = $plugin['name'] .'_render_load';
|
| 826 |
if (function_exists($function)) {
|
| 827 |
$function();
|
| 828 |
}
|
| 829 |
drupal_add_css('public://render/' . $plugin['name'] .'-screen.css', array('weight' => CSS_THEME));
|
| 830 |
drupal_add_js('public://render/' . $plugin['name'] .'-rules.js');
|
| 831 |
}
|
| 832 |
}
|
| 833 |
$done = true;
|
| 834 |
}
|
| 835 |
|
| 836 |
/**
|
| 837 |
* Save rendering JavaScript files for each plugin.
|
| 838 |
*/
|
| 839 |
function render_render_rules_js($edited_plugin = NULL) {
|
| 840 |
// Hide messages from other users.
|
| 841 |
$verbose = user_access('administer site configuration') ? TRUE : FALSE;
|
| 842 |
|
| 843 |
$dir = 'public://render';
|
| 844 |
if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
|
| 845 |
if ($verbose) {
|
| 846 |
drupal_set_message(t('Cannot create directory %render.', array('%render' => $dir)), 'error');
|
| 847 |
}
|
| 848 |
return FALSE;
|
| 849 |
}
|
| 850 |
|
| 851 |
$rules = array();
|
| 852 |
|
| 853 |
// Render JavaScript rules for each plugin.
|
| 854 |
foreach (render_get_rules($edited_plugin) as $rule) {
|
| 855 |
$rules[$rule['plugin']][] = render_render_rule_js($rule);
|
| 856 |
}
|
| 857 |
|
| 858 |
// Wrap rules with execution handler and save to files.
|
| 859 |
foreach ($rules as $plugin => $plugin_rules) {
|
| 860 |
$plugin_js = render_wrap_rules($plugin, $plugin_rules);
|
| 861 |
$filename = $plugin .'-rules.js';
|
| 862 |
if ($file = file_unmanaged_save_data($plugin_js, $dir .'/'. $filename, FILE_EXISTS_REPLACE)) {
|
| 863 |
if ($verbose) {
|
| 864 |
drupal_set_message(t('JavaScript file !file has been saved.', array('!file' => l($filename, file_create_url($dir .'/'. $filename)))));
|
| 865 |
}
|
| 866 |
}
|
| 867 |
elseif ($verbose) {
|
| 868 |
drupal_set_message(t('JavaScript file !file could not be saved.', array('!file' => $dir .'/'. $filename)), 'error');
|
| 869 |
}
|
| 870 |
}
|
| 871 |
}
|
| 872 |
|
| 873 |
/**
|
| 874 |
* Return a single JavaScript rendering rule.
|
| 875 |
*/
|
| 876 |
function render_render_rule_js($rule) {
|
| 877 |
$plugins = render_plugins();
|
| 878 |
$function = $rule['plugin'] .'_render_render_rule_js';
|
| 879 |
if (function_exists($function)) {
|
| 880 |
return $function($rule);
|
| 881 |
}
|
| 882 |
else {
|
| 883 |
$message = t("Error: @plugin does not provide a method to build JavaScript rendering invocations.", array('@plugin' => $rule['plugin']));
|
| 884 |
drupal_set_message($message, 'error');
|
| 885 |
return ' /* '. $message ." */\n";
|
| 886 |
}
|
| 887 |
}
|
| 888 |
|
| 889 |
/**
|
| 890 |
* Wrap execution handler around JavaScript rules.
|
| 891 |
*/
|
| 892 |
function render_wrap_rules($plugin, $rules, $inline = FALSE) {
|
| 893 |
$output = '';
|
| 894 |
if (is_array($rules)) {
|
| 895 |
$plugins = render_plugins();
|
| 896 |
$function = $plugin .'_render_wrap_rules';
|
| 897 |
if (function_exists($function)) {
|
| 898 |
$output .= $function($rules);
|
| 899 |
}
|
| 900 |
}
|
| 901 |
return $output;
|
| 902 |
}
|
| 903 |
|
| 904 |
/**
|
| 905 |
* Create a stylesheet file for a plugin.
|
| 906 |
*
|
| 907 |
* @param string $plugin
|
| 908 |
* A plugin name.
|
| 909 |
* @param bool $verbose
|
| 910 |
* Whether to output positive status messages, defaults to TRUE.
|
| 911 |
* @param bool $print
|
| 912 |
* Whehter to output the contents directly, defaults to FALSE.
|
| 913 |
*/
|
| 914 |
function render_css_screen($plugin, $verbose = TRUE, $print = FALSE) {
|
| 915 |
// Hide messages from other users.
|
| 916 |
if (!user_access('administer site configuration')) {
|
| 917 |
$verbose = FALSE;
|
| 918 |
}
|
| 919 |
|
| 920 |
if ($print) {
|
| 921 |
header("Content-Type: text/css");
|
| 922 |
header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
|
| 923 |
header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
|
| 924 |
header("Cache-Control: no-store, no-cache, must-revalidate");
|
| 925 |
header("Cache-Control: post-check=0, pre-check=0", FALSE);
|
| 926 |
header("Pragma: no-cache");
|
| 927 |
}
|
| 928 |
|
| 929 |
$plugin = $plugin;
|
| 930 |
$plugins = render_plugins();
|
| 931 |
$function = $plugin .'_render_css_screen';
|
| 932 |
if (function_exists($function)) {
|
| 933 |
$output = $function(render_get_rules($plugin));
|
| 934 |
}
|
| 935 |
else {
|
| 936 |
$message = t("Error: @plugin does not provide a method to build a CSS file.", array('@plugin' => $plugin));
|
| 937 |
if ($verbose) {
|
| 938 |
drupal_set_message($message, 'error');
|
| 939 |
}
|
| 940 |
return ' /* '. $message ." */\n";
|
| 941 |
}
|
| 942 |
|
| 943 |
$dir = 'public://render';
|
| 944 |
if (file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
|
| 945 |
$filename = $plugin .'-screen.css';
|
| 946 |
if ($file = file_unmanaged_save_data($output, $dir .'/'. $filename, FILE_EXISTS_REPLACE)) {
|
| 947 |
if ($verbose) {
|
| 948 |
drupal_set_message(t('CSS file !file has been saved.', array('!file' => l($filename, file_create_url($dir .'/'. $filename)))));
|
| 949 |
}
|
| 950 |
}
|
| 951 |
else {
|
| 952 |
if ($verbose) {
|
| 953 |
drupal_set_message(t('CSS file !file could not be saved.', array('!file' => $dir .'/'. $filename)), 'error');
|
| 954 |
}
|
| 955 |
}
|
| 956 |
}
|
| 957 |
else {
|
| 958 |
if ($verbose) {
|
| 959 |
drupal_set_message(t('Cannot create directory %render.', array('%render' => $dir)), 'error');
|
| 960 |
}
|
| 961 |
}
|
| 962 |
if ($print) {
|
| 963 |
print $output;
|
| 964 |
}
|
| 965 |
}
|
| 966 |
|
| 967 |
/**
|
| 968 |
* Creates a download link for render_octet_download().
|
| 969 |
*
|
| 970 |
* @param string $plugin_name
|
| 971 |
* A name of a plugin.
|
| 972 |
* @param string $filename
|
| 973 |
* A filename of a plugin to link to.
|
| 974 |
*
|
| 975 |
* @return string
|
| 976 |
* An already rendered HTML link.
|
| 977 |
*/
|
| 978 |
function render_download_link($plugin_name, $filename) {
|
| 979 |
$plugindir = render_find_render($plugin_name);
|
| 980 |
if (!$plugindir) {
|
| 981 |
$plugindir = drupal_get_path('module', 'render') .'/'. $plugin_name;
|
| 982 |
}
|
| 983 |
return l($filename, 'render/download/'. urlencode($plugindir .'/'. $filename));
|
| 984 |
}
|
| 985 |
|
| 986 |
/**
|
| 987 |
* Downloads files using application/octet-stream mime type.
|
| 988 |
*
|
| 989 |
* Makes text files download rather than appearing in browser.
|
| 990 |
*
|
| 991 |
* @param string $file
|
| 992 |
* The file to be downloaded.
|
| 993 |
*/
|
| 994 |
function render_octet_download() {
|
| 995 |
$args = func_get_args();
|
| 996 |
$file = implode('/', $args);
|
| 997 |
if (user_access('administer site configuration') && is_file($file)) {
|
| 998 |
header('Content-Type: application/octet-stream');
|
| 999 |
header('Content-Disposition: attachment; filename="'. basename($file) .'"');
|
| 1000 |
ob_start();
|
| 1001 |
include $file;
|
| 1002 |
$contents = ob_get_contents();
|
| 1003 |
ob_end_clean();
|
| 1004 |
print $contents;
|
| 1005 |
}
|
| 1006 |
else {
|
| 1007 |
drupal_not_found();
|
| 1008 |
}
|
| 1009 |
}
|
| 1010 |
|
| 1011 |
/**
|
| 1012 |
* Return database fields that make up a rendering rule.
|
| 1013 |
*/
|
| 1014 |
function _render_fields() {
|
| 1015 |
return array('rid', 'plugin', 'name', 'selector', 'properties', 'weight');
|
| 1016 |
}
|
| 1017 |
|