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

Contents of /contributions/modules/customfilter/customfilter.module

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


Revision 1.4 - (show annotations) (download) (as text)
Mon Oct 29 11:49:36 2007 UTC (2 years, 1 month ago) by arhip
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +2 -2 lines
File MIME type: text/x-php
#187135 customfilter_set_edit_submit: Column count doesn't match value
customfilter_sample.xml: 'cache' added
1 <?php
2 // $Id: customfilter.module,v 1.3.2.1 2007/10/28 13:33:22 arhip Exp $
3
4 define('CUSTOMFILTER_CODE_DECLARE',
5 'global $_customfilter_code_vars;'
6 .'$vars = & $_customfilter_code_vars;');
7
8 global $_customfilter_code_vars;
9 global $_customfilter_globals;
10
11 /**
12 * Get filter sets from database
13 *
14 * @param $cols
15 * Columns to be retrieved
16 * @param $cond
17 * Condition, return all results by default
18 *
19 * @return
20 * Array of filter sets
21 */
22 function customfilter_get_sets($cols = array('sid', 'name', 'description'), $cond = '1=1') {
23 $sets = array();
24
25 // Prepare columns to select
26 if (! is_array($cols)) $cols = array($cols);
27 $columns = join(', ', $cols);
28
29 // Query & fetch
30 $result = db_query("SELECT %s FROM {customfilter_set} WHERE %s ORDER BY name", $columns, $cond);
31 while ($set = db_fetch_array($result)) {
32 $sets[] = $set;
33 };
34
35 return $sets;
36 }
37
38 /**
39 * Get a filter set from database
40 *
41 * @param $sid
42 * ID of the filterset
43 * @param $cols
44 * Columns to be retrieved
45 *
46 * @return
47 * The filter set
48 */
49 function customfilter_get_set($sid, $cols = array('sid', 'name', 'description')) {
50 // Prepare columns to select
51 if (! is_array($cols)) $cols = array($cols);
52 $columns = join(', ', $cols);
53
54 // Query & Fetch
55 $set = db_fetch_array(db_query("SELECT %s FROM {customfilter_set} WHERE sid=%d", $columns, $sid));
56
57 return $set;
58 }
59
60 /**
61 * Get filters from database
62 *
63 * @param $sid
64 * ID of the filter set
65 * @param $root
66 * Root filter. Returns tree of filters with this filter
67 * as the root
68 * @param $sortby
69 * Sort the result (and subfilters) by this field.
70 * Default: sort by weight
71 *
72 * @return
73 * Array of filters (each have ['sub'], contains subfilters if any)
74 */
75 function customfilter_get_filters($sid, $root = 0, $sortby = 'weight', $cols = '*') {
76 $filters = array();
77
78 // Prepare columns to select
79 if (! is_array($cols)) $cols = array($cols);
80 $columns = join(', ', $cols);
81
82 // Prepare nodes
83 $nodes = array();
84 if (is_array($root)) {
85 $nodes = $root;
86 }
87 else {
88 $nodes = array($root);
89 }
90
91 foreach ($nodes as $node) {
92 $result = db_query("SELECT %s FROM {customfilter_filter} WHERE sid=%d and parentid=%d ORDER BY %s", $columns, $sid, $node, $sortby);
93
94 while ($filter = db_fetch_array($result)) {
95 $filter['sub'] = customfilter_get_filters($sid, $filter['fid'], $sortby, $cols);
96
97 $filters[$filter['fid']] = $filter;
98 };
99 };
100
101 return $filters;
102 }
103
104 /**
105 * Get a filter from database
106 *
107 * @param $fid
108 * ID of the filter
109 * @param $cols
110 * Columns
111 *
112 * @return
113 * The filter
114 */
115 function customfilter_get_filter($fid, $cols = '*') {
116 // Prepare columns to select
117 if (! is_array($cols)) $cols = array($cols);
118 $columns = join(', ', $cols);
119
120 $filter = db_fetch_array(db_query("SELECT %s FROM {customfilter_filter} WHERE fid=%d", $columns, $fid));
121
122 return $filter;
123 }
124
125 /**
126 * Implementation of hook_help()
127 */
128 function customfilter_help($section) {
129 $help = '';
130
131 $sid = (is_numeric(arg(3)))? arg(3): '';
132 $fid = (is_numeric(arg(4)))? arg(4): '';
133
134 switch ($section) {
135 case "admin/modules#description":
136 $help = t('Custom Filter');
137 break;
138
139 case "admin/settings/customfilter":
140 $help = '<p>'. t('Custom Filter provides an ability for creating user defined filters using regular expressions. Instead of creating filter modules, users can create their own filter for specific site purpose.') .'</p>';
141
142 if (count(customfilter_get_sets()) > 0) {
143 $help .= '<p>'. t('Below are the filter sets. ');
144 }
145 else {
146 $help .= '<p>'. t('Before you can use custom filters, you must have at least one filter set. ');
147 }
148
149 $help .= t('Filter set is a container of filters. Each will appear in Input Format configuration. Click at their name to see what filter they have.') .'</p>';
150 break;
151
152 case "admin/settings/customfilter/export":
153 $help = '<p>'. t('You can export your custom filters as XML document. Just check filters you want to export below, and click the button Export.') .'</p>';
154 break;
155
156 case "admin/settings/customfilter/import":
157 $help = '<p>'. t('You can import custom filters from an XML file.') .'</p>';
158 break;
159
160 case "admin/settings/customfilter/$sid":
161 $help = '<p>'. t('This filterset has filters listed below. Each filter can have subfilters.') .'</p>';
162 break;
163
164 case "admin/settings/customfilter/add":
165 case "admin/settings/customfilter/$sid/edit":
166 $help = '<p>'. t('Give this filter set some name and description.') .'</p>';
167 break;
168
169 case "admin/settings/customfilter/$sid/add":
170 case "admin/settings/customfilter/$sid/$fid":
171 case "admin/settings/customfilter/$sid/$fid/edit":
172 case "admin/settings/customfilter/$sid/$fid/add":
173 $help = '<p>'. t('Here you can define your own filters using regular expressions. For some information about regular expressions, please look at ') . l('http://www.regular-expressions.info', 'http://www.regular-expressions.info') .'</p>';
174 break;
175 }
176
177 return $help;
178 }
179
180 /**
181 * Implementation of hook_perm()
182 */
183 function customfilter_perm() {
184 return array('administer customfilter');
185 }
186
187 /**
188 * Implementation of hook_menu()
189 */
190 function customfilter_menu($may_cache) {
191 $access = user_access('administer customfilter');
192
193 $items = array();
194
195 if ($may_cache) {
196 $items[] = array(
197 'path' => 'admin/settings/customfilter',
198 'title' => t('Custom Filter'),
199 'description' => t('User defined filters.'),
200 'callback' => 'customfilter_settings',
201 'access' => $access,
202 'type' => MENU_NORMAL_ITEM,
203 );
204
205 // Customfilter: List
206 $items[] = array(
207 'path' => 'admin/settings/customfilter/list',
208 'title' => t('List'),
209 'access' => $access,
210 'type' => MENU_DEFAULT_LOCAL_TASK,
211 'weight' => 1);
212
213 // Customfilter: Add filterset
214 $items[] = array(
215 'path' => 'admin/settings/customfilter/add',
216 'title' => t('Add filter set'),
217 'callback' => 'drupal_get_form',
218 'callback arguments' => array('customfilter_set_edit', 'add'),
219 'access' => $access,
220 'type' => MENU_LOCAL_TASK,
221 'weight' => 2);
222
223 // Customfilter: Export
224 $items[] = array(
225 'path' => 'admin/settings/customfilter/export',
226 'title' => t('Export'),
227 'callback' => 'drupal_get_form',
228 'access' => $access,
229 'callback arguments' => array('customfilter_export_form'),
230 'type' => MENU_LOCAL_TASK,
231 'weight' => 3);
232
233 // Customfilter: Import
234 $items[] = array(
235 'path' => 'admin/settings/customfilter/import',
236 'title' => t('Import'),
237 'callback' => 'drupal_get_form',
238 'access' => $access,
239 'callback arguments' => array('customfilter_import_form'),
240 'type' => MENU_LOCAL_TASK,
241 'weight' => 4);
242
243 // Customfilter: Get XML
244 $items[] = array(
245 'path' => 'admin/settings/customfilter/export/xml',
246 'title' => t('XML'),
247 'callback' => 'customfilter_xml_export',
248 'access' => $access,
249 'type' => MENU_CALLBACK);
250
251 }
252 else {
253 if (arg(0) == 'admin' && arg(1) == 'settings' && arg(2) == 'customfilter' && is_numeric(arg(3))) {
254 $sid = arg(3);
255 $set = customfilter_get_set($sid, 'name');
256
257 if ($set) {
258 // Filterset: List filters
259 $items[] = array(
260 'path' => "admin/settings/customfilter/$sid",
261 'title' => t("Custom filter: {$set['name']}"),
262 'callback' => 'customfilter_filters',
263 'callback arguments' => array(arg(3)),
264 'access' => $access,
265 'type' => MENU_CALLBACK);
266
267 $items[] = array(
268 'path' => "admin/settings/customfilter/$sid/list",
269 'title' => t('List'),
270 'access' => $access,
271 'type' => MENU_DEFAULT_LOCAL_TASK,
272 'weight' => 1);
273
274 // Filterset: Edit filterset
275 $items[] = array(
276 'path' => "admin/settings/customfilter/$sid/edit",
277 'title' => t('Edit'),
278 'callback' => 'drupal_get_form',
279 'access' => $access,
280 'callback arguments' => array('customfilter_set_edit', 'edit', $sid),
281 'type' => MENU_LOCAL_TASK,
282 'weight' => 2);
283
284 // Filterset: Delete filterset
285 $items[] = array(
286 'path' => "admin/settings/customfilter/$sid/delete",
287 'title' => t('Delete'),
288 'callback' => 'drupal_get_form',
289 'access' => $access,
290 'callback arguments' => array('customfilter_set_delete', $sid),
291 'type' => MENU_LOCAL_TASK,
292 'weight' => 3);
293
294 // Filterset: Add filter
295 $items[] = array(
296 'path' => "admin/settings/customfilter/$sid/add",
297 'title' => t('Add filter'),
298 'callback' => 'drupal_get_form',
299 'callback arguments' => array('customfilter_filter_edit', 'add', $sid),
300 'access' => $access,
301 'type' => MENU_LOCAL_TASK,
302 'weight' => 4);
303
304 if (is_numeric(arg(4))) {
305 $fid = arg(4);
306 $filter = customfilter_get_filter($fid, 'name');
307
308 // Filter: List
309 $items[] = array(
310 'path' => "admin/settings/customfilter/$sid/$fid",
311 'title' => t("Filter: {$filter['name']}"),
312 'callback' => 'drupal_get_form',
313 'callback arguments' => array('customfilter_filter_edit', 'edit', $sid, $fid),
314 'access' => $access,
315 'type' => MENU_CALLBACK);
316
317 // Filter: Edit filter
318 $items[] = array(
319 'path' => "admin/settings/customfilter/$sid/$fid/edit",
320 'title' => t('Edit'),
321 'access' => $access,
322 'type' => MENU_DEFAULT_LOCAL_TASK,
323 'weight' => 1);
324
325 // Filter: Delete filter
326 $items[] = array(
327 'path' => "admin/settings/customfilter/$sid/$fid/delete",
328 'title' => t('Delete filter'),
329 'callback' => 'drupal_get_form',
330 'callback arguments' => array('customfilter_filter_delete', $fid),
331 'access' => $access,
332 'type' => MENU_LOCAL_TASK,
333 'weight' => 3);
334
335 // Filter: Add subfilter
336 $items[] = array(
337 'path' => "admin/settings/customfilter/$sid/$fid/add",
338 'title' => t('Add subfilter'),
339 'callback' => 'drupal_get_form',
340 'callback arguments' => array('customfilter_filter_edit', 'add', $sid, $fid),
341 'access' => $access,
342 'type' => MENU_LOCAL_TASK,
343 'weight' => 2);
344 }
345 }
346 }
347 }
348
349 return $items;
350 }
351
352 /**
353 * Administer Page
354 */
355 function customfilter_settings() {
356 return customfilter_sets();
357 }
358
359 /**
360 * Lists defined filter sets
361 */
362 function customfilter_sets() {
363 return customfilter_set_render_table();
364 }
365
366 /**
367 * Renders table of filter sets
368 *
369 * @return
370 * Themed table of filters
371 */
372 function customfilter_set_render_table() {
373 $header = array(
374 t('Name'),
375 t('Description'),
376 array('data' => t('Operations'), 'colspan' => '2'));
377
378 $rows = customfilter_set_get_rows();
379
380 $table = theme(
381 'table',
382 $header,
383 $rows ? $rows : array(array(array('data' => t('No custom filter defined.'), 'colspan' => 5))));
384
385 return $table;
386 }
387
388 /**
389 * Renders table rows of filter table
390 *
391 * @return
392 * Generated rows
393 */
394 function customfilter_set_get_rows() {
395 $sets = customfilter_get_sets();
396
397 foreach ($sets as $set) {
398 $rows[] = array(
399 l(t($set['name']), "admin/settings/customfilter/{$set['sid']}"),
400 '<em>'. t($set['description']) .'</em>',
401 l(t('edit'), "admin/settings/customfilter/{$set['sid']}/edit"),
402 l(t('delete'), "admin/settings/customfilter/{$set['sid']}/delete"),
403 );
404 }
405
406 return $rows;
407 }
408
409 /**
410 * Edit a filter set
411 */
412 function customfilter_set_edit($op, $sid = 0) {
413 if ($op == 'edit') {
414 $item = customfilter_get_set($sid, '*');
415 }
416 elseif ($op == 'add') {
417 $item = array(
418 'sid' => 0,
419 'name' => 'Filter set #',
420 'cache' => 1,
421 'description' => '',
422 'shorttips' => '',
423 'longtips' => '',
424 );
425 }
426
427 $form['sid'] = array('#type' => 'value', '#value' => $item['sid']);
428 $form['operation'] = array('#type' => 'value', '#value' => $op);
429
430 $form['name'] = array(
431 '#type' => 'textfield',
432 '#title' => t('Name'),
433 '#default_value' => $item['name'],
434 '#description' => t('The name of the filter set.'),
435 '#required' => TRUE);
436
437 $form['cache'] = array(
438 '#type' => 'checkbox',
439 '#title' => t('Cache'),
440 '#default_value' => $item['cache'],
441 '#description' => t('If checked, the content will be cached (i.e. this filter will be executed once per content edit).'));
442
443 $form['description'] = array(
444 '#type' => 'textarea',
445 '#title' => t('Description'),
446 '#default_value' => $item['description'],
447 '#description' => t('Some text to describe this filter set.'));
448
449 $form['shorttips'] = array(
450 '#type' => 'textarea',
451 '#title' => t('Tips (short)'),
452 '#default_value' => $item['shorttips'],
453 '#description' => t(''));
454
455 $form['longtips'] = array(
456 '#type' => 'textarea',
457 '#title' => t('Tips (full)'),
458 '#default_value' => $item['longtips'],
459 '#description' => t(''));
460
461 $form['submit'] = array(
462 '#type' => 'submit',
463 '#value' => t('Save'));
464
465 return $form;
466 }
467
468 /**
469 * Submit modified filter set
470 */
471 function customfilter_set_edit_submit($form_id, $form_values) {
472 switch ($form_values['operation']) {
473 case 'edit':
474 db_query("UPDATE {customfilter_set}
475 SET
476 name='%s', cache=%d, description='%s',
477 shorttips='%s', longtips='%s'
478 WHERE sid=%d",
479 $form_values['name'],
480 $form_values['cache'],
481 $form_values['description'],
482 $form_values['shorttips'],
483 $form_values['longtips'],
484 $form_values['sid']);
485 break;
486 case 'add':
487 $nextid = db_next_id('{customfilter_set}_sid');
488
489 db_query("INSERT INTO {customfilter_set}
490 (sid, name, cache, description, shorttips, longtips)
491 VALUES(%d, '%s', %d, '%s', '%s', '%s');",
492 $nextid,
493 $form_values['name'],
494 $form_values['cache'],
495 $form_values['description'],
496 $form_values['shorttips'],
497 $form_values['longtips']);
498 break;
499 }
500
501 return 'admin/settings/customfilter';
502 }
503
504 /**
505 * Delete filter set
506 */
507 function customfilter_set_delete($sid) {
508 $set = customfilter_get_set($sid, '*');
509 $filters = customfilter_get_filters($sid);
510
511 $form['sid'] = array('#type' => 'value', '#value' => $sid);
512
513 $message = t('Are you sure you want to delete this filter set?');
514
515 $msg_text =
516 "<h3>". $set['name'] ."</h3>"
517 ."<p>". $set->description ."</p>";
518
519 if (count($filters) > 0) {
520 $msg_text .=
521 "<p>". t('This set has filters. If you delete this, they will be deleted too.') ."</p>"
522 . customfilter_filter_render_table($sid, $fid, FALSE);
523 }
524
525 $msg_text .= "<p>". t('This action cannot be undone.') ."</p>";
526
527 return confirm_form(
528 $form, $message,
529 'admin/settings/customfilter',
530 $msg_text,
531 t('Delete'));
532 }
533
534 /**
535 * Execute filter set deletion
536 */
537 function customfilter_set_delete_submit($form_id, $form_values) {
538 customfilter_delete_set($form_values['sid']);
539
540 return 'admin/settings/customfilter';
541 }
542
543 function customfilter_delete_set($sid) {
544 $filters = customfilter_get_filters($sid);
545
546 foreach ($filters as $filter) {
547 customfilter_delete_filter($filter['fid']);
548 }
549
550 db_query('DELETE FROM {customfilter_set} WHERE sid=%d', $sid);
551 }
552
553 /**
554 * Lists defined filters
555 */
556 function customfilter_filters($sid) {
557 return customfilter_filter_render_table($sid, 0);
558 }
559
560 /**
561 * Renders table of filters
562 *
563 * @param $sid
564 * ID of the filter set
565 * @param $fid
566 * ID of the root filter
567 * @param $op
568 * If TRUE, will render the 'operations' column
569 *
570 * @return
571 * Themed table of filters
572 */
573 function customfilter_filter_render_table($sid = 0, $fid = 0, $op = TRUE) {
574 // Table header
575 $header = array(
576 t('Name'),
577 t('Description'),
578 t('Pattern'),
579 t('Match'),
580 t('Weight'));
581
582 if ($op)
583 $header[] = array('data' => t('Operations'), 'colspan' => '3');
584
585 // Table rows
586 $rows = array();
587
588 $filters = customfilter_get_filters($sid, $fid);
589
590 if (count($filters) > 0) {
591 customfilter_filter_get_rows($filters, 0, $rows, $op);
592 }
593 else {
594 $rows[] = array(
595 0 => array('data' => 'No custom filter defined.', 'colspan' => 5),
596 );
597 }
598
599 $table = theme(
600 'table',
601 $header,
602 $rows);
603
604 return $table;
605 }
606
607 /**
608 * Renders table rows of filter table
609 *
610 * @param $filters
611 * Array of fetched filters from database (from customfilter_get_filters)
612 * @param $depth
613 * The level of subfilters that should be rendered
614 * @param $rows
615 * Generated rows
616 * @param $op
617 * If TRUE, will render the 'operations' column
618 */
619 function customfilter_filter_get_rows($filters, $depth, &$rows, $op = TRUE) {
620 foreach ($filters as $filter) {
621 $format = (($depth == 0)? "strong": "em");
622
623 $row = array(
624 str_repeat('&raquo;&nbsp;', $depth) .'<'. $format .'>'. t($filter['name']) .'</'. $format .'>',
625 '<em>'. t($filter['description']) .'</em>',
626 htmlspecialchars($filter['pattern']),
627 ($filter['parentid'] == 0)? "" : $filter['matches'],
628 $filter['weight'],
629 );
630
631 if ($op) {
632 $row[] = l(t('add'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/add");
633 $row[] = l(t('edit'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/edit");
634 $row[] = l(t('delete'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/delete");
635 }
636
637 $rows[] = $row;
638
639 if (is_array($filter['sub'])) {
640 customfilter_filter_get_rows($filter['sub'], $depth + 1, $rows, $op);
641 }
642 }
643 }
644
645 /**
646 * Edit a filter
647 */
648 function customfilter_filter_edit($op, $sid, $fid = 0) {
649 if ($op == 'edit') {
650 $item = customfilter_get_filter($fid, '*');
651 }
652 elseif ($op == 'add') {
653 $item = array(
654 'fid' => 0,
655 'parentid' => $fid,
656 'sid' => $sid,
657 'name' => '$1',
658 'description' => '',
659 'matches' => 1,
660 'pattern' => '/regex/i',
661 'replacement' => 'Regular Expressions',
662 'func' => 0,
663 'weight' => 0,
664 );
665 }
666
667 $matchopt = array();
668 for ($i = 0; $i <=99; $i++) {
669 $matchopt[$i] = $i;
670 };
671
672 $form['fid'] = array('#type' => 'value', '#value' => $item['fid']);
673 $form['sid'] = array('#type' => 'value', '#value' => $sid);
674 $form['parentid'] = array('#type' => 'value', '#value' => $item['parentid']);
675 $form['operation'] = array('#type' => 'value', '#value' => $op);
676
677 if ($item['parentid'] != 0) {
678 $form['matches'] = array(
679 '#type' => 'select',
680 '#title' => t('# Match'),
681 '#options' => $matchopt,
682 '#default_value' => $item['matches'],
683 '#description' => t('Matches.'));
684 }
685
686 $form['name'] = array(
687 '#type' => 'textfield',
688 '#title' => t('Name'),
689 '#default_value' => $item['name'],
690 '#description' => t('The name of the filter.'),
691 '#required' => TRUE);
692
693 $form['pattern'] = array(
694 '#type' => 'textarea',
695 '#title' => t('Pattern'),
696 '#default_value' => $item['pattern'],
697 '#description' => t('Regular expression. Look at <a href="http://www.regular-expressions.info">http://www.regular-expressions.info</a> for more help.'));
698
699 $form['replacement'] = array(
700 '#type' => 'textarea',
701 '#title' => t('Replacement text'),
702 '#default_value' => $item['replacement'],
703 '#description' => t('Replacement Text. Matched string will be replaced with text supplied here. Use $n (e.g. $1, $25) or ${n} (e.g. ${1}, ${25}), with n range from 0 to 99, to get the n-th original strings matched ($0 represents the entire matched string). If you set the <strong>PHP Code</strong> below, you can enter replaced text with some PHP Code. n-th matched string will be provided in $matches[n], and there will be a global variable named $vars you can use it for your own purpose. Don\'t forget to write the return statement.'));
704
705 $form['func'] = array(
706 '#type' => 'checkbox',
707 '#title' => t('PHP Code'),
708 '#default_value' => $item['func'],
709 '#description' => t('Check to allow using PHP code to replace the text.'));
710
711 $form['weight'] = array(
712 '#type' => 'weight',
713 '#title' => t('Weight'),
714 '#default_value' => $item['weight'],
715 '#description' => t('Filter weight.'));
716
717 $form['description'] = array(
718 '#type' => 'textarea',
719 '#title' => t('Description'),
720 '#default_value' => $item['description'],
721 '#description' => t('Some text to describe this filter.'));
722
723 $form['submit'] = array(
724 '#type' => 'submit',
725 '#value' => t('Save Configuration'));
726
727 return $form;
728 }
729
730 /**
731 * Submit modified filter
732 */
733 function customfilter_filter_edit_submit($form_id, $form_values) {
734 switch ($form_values['operation']) {
735 case 'edit':
736 db_query("UPDATE {customfilter_filter}
737 SET sid=%d, parentid=%d,
738 name='%s', description='%s',
739 matches=%d, pattern='%s', replacement='%s',
740 func=%d, weight=%d
741 WHERE fid=%d",
742 $form_values['sid'],
743 $form_values['parentid'],
744 $form_values['name'],
745 $form_values['description'],
746 $form_values['matches'],
747 $form_values['pattern'],
748 $form_values['replacement'],
749 $form_values['func'],
750 $form_values['weight'],
751 $form_values['fid']);
752 break;
753 case 'add':
754 $nextid = db_next_id('{customfilter_filter}_fid');
755
756 db_query("INSERT INTO {customfilter_filter}
757 (fid, sid, parentid, name, description, matches, pattern, replacement, func, weight)
758 VALUES(%d, %d, %d, '%s', '%s', %d, '%s', '%s', %d, %d);",
759 $nextid,
760 $form_values['sid'],
761 $form_values['parentid'],
762 $form_values['name'],
763 $form_values['description'],
764 $form_values['matches'],
765 $form_values['pattern'],
766 $form_values['replacement'],
767 $form_values['func'],
768 $form_values['weight']);
769 break;
770 }
771
772 return "admin/settings/customfilter/{$form_values['sid']}";
773 }
774
775 /**
776 * Delete a filter
777 */
778 function customfilter_filter_delete($fid) {
779 $filter = db_fetch_object(db_query("SELECT * FROM {customfilter_filter} WHERE fid=%d", $fid));
780 $subfilter = db_fetch_object(db_query("SELECT * FROM {customfilter_filter} WHERE parentid=%d", $fid));
781
782 $form['fid'] = array('#type' => 'value', '#value' => $fid);
783 $form['sid'] = array('#type' => 'value', '#value' => $filter->sid);
784
785 $message = t('Are you sure you want to delete this custom filter?');
786
787 $msg_text =
788 (($filter->parentid == 0)? "<h3>{$filter->name}</h3>" : "")
789 ."<p>{$filter->description}</p>"
790 ."<h3>Pattern</h3>"
791 ."<pre>{$filter->pattern}</pre>"
792 ."<h3>Replacer</h3>"
793 ."<pre>{$filter->replacer}</pre>";
794
795 if ($subfilter) {
796 $msg_text .=
797 "<p>". t('This filter has subfilters. If you delete this, they will be deleted too.') ."</p>"
798 . customfilter_filter_render_table($filter->sid, $fid, FALSE);
799 }
800
801 $msg_text .= "<p>". t('This action cannot be undone.') ."</p>";
802
803 return confirm_form(
804 $form, $message,
805 "admin/settings/customfilter/{$filter->sid}",
806 $msg_text,
807 t('Delete'));
808 }
809
810 /**
811 * Execute deletion
812 */
813 function customfilter_filter_delete_submit($form_id, $form_values) {
814 customfilter_delete_filter($form_values['fid']);
815
816 return "admin/settings/customfilter/{$form_values['sid']}";
817 }
818
819 function customfilter_delete_filter($fid) {
820 $result = db_query("SELECT * FROM {customfilter_filter} where parentid=%d", $fid);
821
822 while ($filter = db_fetch_object($result)) {
823 customfilter_delete_filter($filter->fid);
824 }
825
826 db_query("DELETE FROM {customfilter_filter} WHERE fid=%d", $fid);
827 }
828
829 /**
830 * Get complete description of a filter, including it's subfilters
831 */
832 function customfilter_get_descriptions($filter) {
833 $desc = "<em>". $filter['description'] ."</em>";
834
835 if (is_array($filter['sub']) && (count($filter['sub']) > 0)) {
836 $desc .= "<ul>";
837 foreach ($filter['sub'] as $subfilter) {
838 $desc .= "<li>";
839 $desc .= customfilter_get_descriptions($subfilter);
840 $desc .= "</li>";
841 }
842 $desc .= "</ul>";
843 }
844
845 return $desc;
846 }
847
848 /**
849 * Implementation of hook_filter_tips()
850 */
851 function customfilter_filter_tips($delta, $format, $long = FALSE) {
852 $col = ($long)? 'longtips': 'shorttips';
853
854 $tips = customfilter_get_set($delta, array('sid', $col));
855
856 return $tips[$col];
857 }
858
859 /**
860 * Implementation of hook_filter().
861 */
862 function customfilter_filter($op, $delta = 0, $format = -1, $text = '' ) {
863 switch ($op) {
864 case 'list':
865 return _customfilter_filter_list();
866
867 case 'no cache':
868 return ! _customfilter_filter_cache($delta);
869
870 case 'description':
871 return _customfilter_filter_desc($delta);
872
873 case 'prepare':
874 return $text;
875
876 case "process":
877 return _customfilter_process($delta, $format, $text);
878
879 default:
880 return $text;
881 }
882 }
883
884 function _customfilter_filter_list() {
885 $sets = customfilter_get_sets('sid, name');
886
887 $s = array();
888 foreach ($sets as $set) {
889 $s[$set['sid']] = t($set['name']);
890 }
891
892 return $s;
893 }
894
895 function _customfilter_filter_cache($delta) {
896 $set = customfilter_get_set($delta, array('sid', 'cache'));
897
898 return $set['cache'];
899 }
900
901 function _customfilter_filter_desc($delta) {
902 $set = customfilter_get_set($delta, array('sid', 'description'));
903
904 return t($set['description']);
905 }
906
907 /**
908 * Custom Filter process
909 */
910 function _customfilter_process($delta, $format, $text) {
911 global $_customfilter_globals;
912
913 $_customfilter_globals->text = $text;
914
915 // Get the filter set, according to $delta
916 $set = customfilter_get_set($delta, 'sid');
917 if ($set) {
918 $filters = customfilter_get_filters($delta);
919
920 if (count($filters) > 0) {
921 // Preparation
922 // The stack is used to save the parent filter when traversing
923 $_customfilter_globals->stack = array();
924
925 foreach ($filters as $filter) {
926 $_customfilter_globals->stack[] = $filter;
927
928 $_customfilter_globals->text = preg_replace_callback(
929 $filter['pattern'],
930 '_customfilter_process_filter',
931 $_customfilter_globals->text);
932
933 array_pop($_customfilter_globals->stack);
934 }
935 }
936 }
937
938 return $_customfilter_globals->text;
939 }
940
941 function _customfilter_process_extract_rep($replacement) {
942 $reps = array();
943
944 preg_match_all(
945 '/([^\\\\]|^)(\$([0-9]{1,2}|\{([0-9]{1,2})\}))/',
946 $replacement,
947 $reps,
948 PREG_OFFSET_CAPTURE);
949
950 $arr = array();
951
952 foreach ($reps[4] as $key => $val) {
953 if ($val == '') {
954 $str = $reps[3][$key][0];
955 }
956 else {
957 $str = $reps[4][$key][0];
958 }
959
960 $offset = $reps[2][$key][1];
961 $length = strlen($reps[2][$key][0]);
962
963 $arr[] = array(
964 'index' => $str,
965 'offset' => $offset,
966 'length' => $length
967 );
968 }
969
970 return $arr;
971 }
972
973 function _customfilter_process_replace_sub($replacement, $sub, $func = 0) {
974 if ($func == 1) {
975 $code = create_function(
976 '$matches',
977 CUSTOMFILTER_CODE_DECLARE . $replacement
978 );
979
980 $text = $code($sub);
981 }
982 else {
983 $text = $replacement;
984
985 $reps = _customfilter_process_extract_rep($replacement);
986 krsort($reps);
987
988 foreach ($reps as $rep) {
989 $text = substr_replace(
990 $text,
991 $sub[$rep['index']],
992 $rep['offset'],
993 $rep['length']);
994 };
995 }
996
997 return $text;
998 }
999
1000 function _customfilter_process_filter($matches) {
1001 global $_customfilter_globals;
1002
1003 $result = $matches[0];
1004
1005 $filter = end($_customfilter_globals->stack);
1006
1007 // if there is subfilter
1008 if (is_array($filter['sub']) && (count($filter['sub']) > 0)) {
1009 // do the same thing to each of them
1010 foreach ($filter['sub'] as $subfilter) {
1011 $_customfilter_globals->stack[] = $subfilter;
1012
1013 $substr = & $matches[$subfilter['matches']];
1014 $substr = preg_replace_callback(
1015 $subfilter['pattern'],
1016 '_customfilter_process_filter',
1017 $substr
1018 );
1019
1020 array_pop($_customfilter_globals->stack);
1021 }
1022
1023 $result = _customfilter_process_replace_sub(
1024 $filter['replacement'],
1025 $matches,
1026 $filter['func']);
1027
1028 } // if there is not, replace
1029 elseif ($filter['func'] == 1) {
1030 $result = preg_replace_callback(
1031 $filter['pattern'],
1032 create_function(
1033 '$matches',
1034 CUSTOMFILTER_CODE_DECLARE
1035 . $filter['replacement']
1036 ),
1037 $result);
1038 }
1039 else {
1040 $result = preg_replace(
1041 $filter['pattern'],
1042 $filter['replacement'],
1043 $result);
1044 }
1045
1046 return $result;
1047 }
1048
1049 /**
1050 * Export
1051 */
1052 function customfilter_export_form() {
1053 $form = array();
1054
1055 $sets = customfilter_get_sets();
1056 foreach ($sets as $set) {
1057 $opt[$set['sid']] = t($set['name']);
1058 }
1059
1060 $form['sets'] = array(
1061 '#type' => 'checkboxes',
1062 '#title' => t('Filter sets'),
1063 '#options' => $opt,
1064 '#description' => 'Choose filter sets.',
1065 );
1066
1067 $form['submit'] = array(
1068 '#type' => 'submit',
1069 '#value' => 'Export',
1070 );
1071
1072 return $form;
1073 }
1074
1075 function customfilter_export_form_submit($form_id, $form_values) {
1076 $sids = array();
1077 foreach ($form_values['sets'] as $sid) {
1078 if ($sid > 0) $sids[] = $sid;
1079 }
1080
1081 $arg = join('.', $sids);
1082
1083 return "admin/settings/customfilter/export/xml/$arg";
1084 }
1085
1086 function customfilter_xml_export($sets) {
1087 $sids = explode('.', $sets);
1088
1089 $xml = customfilter_xml_create($sids);
1090
1091 header('Content-Type: application/octet-stream');
1092 header('Content-Length: '. strlen($xml));
1093 header("Content-Disposition: attachment; filename=customfilter.xml");
1094
1095 echo $xml;
1096 }
1097
1098 function customfilter_xml_create($sids) {
1099 $xml = "<?xml version=\"1.0\" standalone=\"yes\"?>\n";
1100 $xml .= "<customfilter>\n";
1101
1102 foreach ($sids as $sid) {
1103 $xml .= customfilter_xml_filterset($sid);
1104 }
1105
1106 $xml .= "</customfilter>";
1107
1108 return $xml;
1109 }
1110
1111 function customfilter_xml_filterset($sid) {
1112 $set = customfilter_get_set($sid, '*');
1113
1114 $filters = customfilter_get_filters($sid, 0);
1115
1116 $xml = " <filterset name=\"{$set['name']}\" cache=\"{$set['cache']}\">\n";
1117 $xml .= " <description>{$set['description']}</description>\n";
1118 $xml .= " <tips>\n";
1119 $xml .= " <short><![CDATA[{$set['shorttips']}]]></short>\n";
1120 $xml .= " <long><![CDATA[{$set['longtips']}]]></long>\n";
1121 $xml .= " </tips>\n";
1122 $xml .= " <filters>\n";
1123
1124 foreach ($filters as $filter) {
1125 $xml .= customfilter_xml_filter($filter);
1126 }
1127
1128 $xml .= " </filters>\n";
1129 $xml .= " </filterset>\n";
1130
1131 return $xml;
1132 }
1133
1134 function customfilter_xml_filter($filter, $level = 0) {
1135 $indent = str_repeat(' ', $level + 3);
1136
1137 $xml = $indent ."<filter name=\"{$filter['name']}\" matches=\"{$filter['matches']}\" func=\"{$filter['func']}\" weight=\"{$filter['weight']}\">\n";
1138 $xml .= $indent ." <description><![CDATA[{$filter['description']}]]></description>\n";
1139 $xml .= $indent ." <pattern><![CDATA[{$filter['pattern']}]]></pattern>\n";
1140 $xml .= $indent ." <replacement><![CDATA[{$filter['replacement']}]]></replacement>\n";
1141
1142 $subfilters = $filter['sub'];
1143 if (is_array($subfilters) && (count($subfilters) > 0)) {
1144 $xml .= $indent ." <subfilters>\n";
1145 foreach ($subfilters as $subfilter) {
1146 $xml .= customfilter_xml_filter($subfilter, $level + 2);
1147 }
1148 $xml .= $indent ." </subfilters>\n";
1149 }
1150
1151 $xml .= $indent ."</filter>\n";
1152
1153 return $xml;
1154 }
1155
1156 /**
1157 * Import
1158 */
1159 function customfilter_import_form() {
1160 $form = array();
1161
1162 $form['xml'] = array(
1163 '#type' => 'file',
1164 '#title' => t('Import from file'),
1165 '#description' => t('The XML file to be imported.'),
1166 );
1167
1168 $form[] = array(
1169 '#type' => 'submit',
1170 '#value' => t('Import'),
1171 );
1172
1173 $form['#attributes'] = array('enctype' => 'multipart/form-data');
1174
1175 return $form;
1176 }
1177
1178 function customfilter_import_form_submit($form_id, $form_values) {
1179 global $_customfilter_globals;
1180 $cg = & $_customfilter_globals;
1181
1182 $file = file_check_upload('xml');
1183
1184 if ($file) {
1185 $thefile = fopen($file->filepath, "rb");
1186
1187 if ($thefile) {
1188 $fstat = fstat($thefile);
1189 $xml = fread($thefile, $fstat['size']);
1190
1191 fclose($thefile);
1192 drupal_set_message(t('XML file %f imported.', array('%f' => $file->filename)));
1193
1194 customfilter_xml_read($xml);
1195 _customfilter_xml_sql($cg->sets, $cg->filters);
1196 }
1197 }
1198 }
1199
1200 function customfilter_xml_read(& $xml) {
1201 global $_customfilter_globals;
1202 $cg = & $_customfilter_globals;
1203
1204 $cg->elements = array();
1205 $cg->sets = array();
1206 $cg->filters = array();