View source
<?php
class CustomFilter implements ArrayAccess {
const API_VERSION = '2.1';
const API_MINIMUM_VERSION = '2.1';
private static $instance;
private $vars = array();
public function __call($name, $arguments) {
$flist = array();
foreach (module_implements('customfilter_api') as $module) {
$result = module_invoke($module, 'customfilter_api');
$bool = array(
isset($result) && is_array($result) && isset($result['version']) && version_compare($result['version'], self::API_MINIMUM_VERSION, '>') && version_compare($result['version'], self::API_VERSION, '<'),
);
if ($bool) {
$result = module_invoke($module, 'customfilter_function_info');
if (isset($result) && is_array($result)) {
$flist = array_merge($flist, $result);
}
}
}
if (isset($flist[$name])) {
$result = call_user_func_array($flist[$name]['function'], $arguments);
if (isset($result)) {
return $result;
}
else {
return '';
}
}
else {
return '';
}
}
private function __clone() {
}
private function __construct() {
}
public function __get($name) {
return isset($this->vars[$name]) ? $this->vars[$name] : NULL;
}
public function __isset($name) {
return isset($this->vars[$name]);
}
public function __set($name, $value) {
$this->vars[$name] = $value;
}
public function __unset($name) {
unset($this->vars[$name]);
}
public function offsetExists($offset) {
return isset($this->vars[$offset]);
}
public function offsetGet($offset) {
return isset($this->vars[$offset]) ? $this->vars[$offset] : NULL;
}
public function offsetSet($offset, $value) {
$this->vars[$offset] = $value;
}
public function offsetUnset($offset) {
unset($this->vars[$offset]);
}
public static function singleton() {
if (!isset(self::$instance)) {
self::$instance = new CustomFilter();
}
return self::$instance;
}
}
function customfilter_filter($op, $delta = 0, $format = -1, $text = '') {
$filters = _customfilter_get_filters();
switch ($op) {
case 'description':
return _customfilter_get_filter_descriptions($delta, 'description');
case 'list':
$flist = array();
foreach ($filters as $filter) {
$flist[$filter['fid']] = _customfilter_get_filter_descriptions($filter['fid'], 'name');
}
return $flist;
case 'no cache':
return isset($filters[$delta]['cache']) ? !$filters[$delta]['cache'] : TRUE;
case 'process':
if (empty($text)) {
return '';
}
if (!isset($filters[$delta])) {
return $text;
}
$globals =& _customfilter_globals('push');
$globals->text = $text;
$rules = _customfilter_get_rules($delta);
if (is_array($rules) && count($rules)) {
$globals->stack = array();
foreach ($rules as $rule) {
if ($rule['enabled']) {
$globals->stack[] = $rule;
$globals->text = preg_replace_callback($rule['pattern'], '_customfilter_process', $globals->text);
array_pop($globals->stack);
}
}
}
$result = $globals->text;
_customfilter_globals('pop');
return $result;
default:
return $text;
}
}
function customfilter_filter_tips($delta, $format, $long = FALSE) {
return _customfilter_get_filter_descriptions($delta, $long ? 'longtip' : 'shorttip');
}
function customfilter_flush_caches() {
return array(
'cache_customfilter',
);
}
function customfilter_perm() {
return array(
'administer customfilter',
);
}
function customfilter_description_load($id) {
}
function customfilter_filter_load($id) {
}
function customfilter_rule_load($id) {
}
function customfilter_cache_clear($type, $fid = NULL) {
switch ($type) {
case 'all':
cache_clear_all("*", 'cache_customfilter', TRUE);
break;
case 'filters':
cache_clear_all('filters', 'cache_customfilter');
cache_clear_all(isset($fid) ? "rules:{$fid}" : "rules", 'cache_customfilter', TRUE);
break;
}
}
function _customfilter_delete_rule($rid) {
$result = db_query("SELECT * FROM {customfilter_rule} where prid = %d", $rid);
while ($rule = db_fetch_object($result)) {
_customfilter_delete_rule($rule->rid);
}
db_query("DELETE FROM {customfilter_rule} WHERE rid = %d", $rid);
}
function _customfilter_get_filters() {
if ($cache = cache_get('filters', 'cache_customfilter')) {
$filters = $cache->data;
}
else {
$filters = array();
$result = db_query("SELECT * FROM {customfilter_filter}");
while ($filter = db_fetch_array($result)) {
$filters[$filter['fid']] = $filter;
}
cache_set('filters', $filters, 'cache_customfilter');
}
return $filters;
}
function _customfilter_get_filter_descriptions($fid = 0, $col = '') {
global $language;
if ($fid) {
$obj = db_fetch_object(db_query_range("SELECT * FROM {customfilter_filter_description} WHERE fid = %d AND language in ('%s', '')", $fid, $language->language, 0, 1));
if ($obj === FALSE) {
$obj = new stdClass();
$obj->fid = 0;
$obj->language = '';
$obj->id = '';
$obj->name = '';
$obj->description = '';
$obj->longtip = '';
$obj->shorttip = '';
}
return empty($col) ? $obj : (isset($obj->{$col}) ? $obj->{$col} : '');
}
else {
$descriptions = array();
$result = db_query("SELECT * FROM {customfilter_filter_description}");
while ($description = db_fetch_object($result)) {
$descriptions[$description->fdid] = $description;
}
return $descriptions;
}
}
function _customfilter_get_rules($fid, $root = 0, $use_cache = TRUE) {
if ($use_cache && ($cache = cache_get("rules:{$fid}:{$root}", 'cache_customfilter'))) {
$rules = $cache->data;
}
else {
$rules = array();
$result = db_query("SELECT * FROM {customfilter_rule} WHERE fid = %d and prid = %d ORDER BY weight", $fid, $root);
while ($rule = db_fetch_array($result)) {
$rule['sub'] = _customfilter_get_rules($fid, $rule['rid'], FALSE);
$rules[$rule['rid']] = $rule;
}
if ($use_cache) {
cache_set("rules:{$fid}:{$root}", $rules, 'cache_customfilter');
}
}
return $rules;
}
function &_customfilter_globals($op = '') {
$globals =& Vars::staticValue(__FUNCTION__, array());
$index =& Vars::staticValue(__FUNCTION__ . '_index', 0);
if ($op == 'push') {
$globals[++$index] = new stdClass();
}
elseif ($op == 'pop' && $index) {
unset($globals[$index--]);
}
return $globals[$index];
}
function _customfilter_process($matches) {
$globals =& _customfilter_globals();
$result = $matches[0];
$rule = end($globals->stack);
$code = $rule['code'];
$pattern = $rule['pattern'];
$replacement = $rule['replacement'];
if (is_array($sub = $rule['sub']) && count($sub)) {
foreach ($sub as $subrule) {
if ($subrule['enabled']) {
$globals->stack[] = $subrule;
$substr =& $matches[$subrule['matches']];
$substr = preg_replace_callback($subrule['pattern'], '_customfilter_process', $substr);
array_pop($globals->stack);
}
}
if ($code) {
_customfilter_replace_callback($replacement, TRUE);
$result = _customfilter_replace_callback($matches);
}
else {
$result = $replacement;
$rmatches = array();
$reps = array();
preg_match_all('/([^\\\\]|^)(\\$([0-9]{1,2}|\\{([0-9]{1,2})\\}))/', $replacement, $rmatches, PREG_OFFSET_CAPTURE);
foreach ($rmatches[4] as $key => $val) {
if ($val == '') {
$index = $rmatches[3][$key][0];
}
else {
$index = $rmatches[4][$key][0];
}
$offset = $rmatches[2][$key][1];
$length = drupal_strlen($rmatches[2][$key][0]);
$reps[] = array(
'index' => $index,
'offset' => $offset,
'length' => $length,
);
}
krsort($reps);
foreach ($reps as $rep) {
$result = substr_replace($result, $matches[$rep['index']], $rep['offset'], $rep['length']);
}
}
}
elseif ($code) {
$code =& Vars::staticValue('_customfilter_replace_callback');
$code = $replacement;
$result = preg_replace_callback($pattern, '_customfilter_replace_callback', $result);
}
else {
$result = preg_replace($pattern, $replacement, $result);
}
return $result;
}
function _customfilter_replace_callback($matches) {
$code =& Vars::staticValue(__FUNCTION__, '');
if ($code) {
$customfilter = CustomFilter::singleton();
@eval($code);
}
return isset($result) ? $result : '';
}