diff --git annotation_text/annotation_text.module annotation_text/annotation_text.module
index 21c99c2..cb43c88 100644
--- annotation_text/annotation_text.module
+++ annotation_text/annotation_text.module
@@ -37,28 +37,82 @@ function annotation_text_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
break;
case 'load':
- // TODO: find a better way of passing filter context
- $node->body = _annotation_text_add_context($node->body, $node);
- $node->teaser = _annotation_text_add_context($node->teaser, $node);
+ $node->body = annotation_text_add_markup($node->body, $node);
+ $node->teaser = annotation_text_add_markup($node->teaser, $node, TRUE);
+ break;
+ case 'presave':
+ // Handle version changes.
+ if ($node->nid && preg_match_all('@@i', $node->body, $matches)) {
+ if (count($matches[1])) {
+ foreach ($matches[1] as $key => $cid) {
+ // Get the new offset, length, and string
+ $offset = strpos($node->body, $matches[0][$key]);
+ // TODO: test with line breaks etc. Did this ever work across linebreaks??
+ preg_match('@' . $matches[0][$key] . '(.*?)@i', $node->body, $selections);
+ $string = $selections[1];
+ $replacements[] = array(
+ 'string' => $string,
+ 'span' => $selections[0],
+ );
+ $length = strlen($string);
+ // Update the text_annotations data.
+ $annotation = array(
+ 'cid' => $cid,
+ 'offset' => $offset,
+ 'length' => $length,
+ 'string' => $string,
+ );
+ // We cannot save the revised annotations during presave,
+ // as we do not know the new vid of the node.
+ // Store them in the node to use on update.
+ $node->annotation_text[] = $annotation;
+ }
+ // Remove annotation spans from markup before saving.
+ if (count($replacements)) {
+ foreach ($replacements as $replacement) {
+ $node->body = str_replace($replacement['span'], $replacement['string'], $node->body);
+ $node->teaser = str_replace($replacement['span'], $replacement['string'], $node->teaser);
+ }
+ }
+ }
+ }
+ break;
+ case 'update':
+ // Annotation updates and new revisions are added here now that the
+ // $node->vid is known.
+ $cids = array();
+ if (isset($node->annotation_text) && count($node->annotation_text)) {
+ foreach ($node->annotation_text as $annotation) {
+ // Ensure this is a valid comment with a record for this node.
+ if (db_result(db_query("SELECT cid FROM {comments} WHERE nid = %d AND cid = %d", $node->nid, $annotation['cid']))) {
+ $cids[$annotation['cid']] = 1;
+ $annotation['vid'] = $node->vid;
+ $update = db_result(db_query("SELECT vid FROM {annotation_text} WHERE cid = %d and vid = %d", $annotation['cid'], $node->vid));
+
+ if ($update) {
+ drupal_write_record('annotation_text', $annotation, array('cid', 'vid'));
+ }
+ else {
+ // A new revision is being created, which needs a new record.
+ drupal_write_record('annotation_text', $annotation);
+ }
+ }
+ }
+ }
+ // Remove any old annotations for this vid if they were removed
+ // during edit. (Leave them as regular comments only)
+ $result = db_query("SELECT cid FROM {annotation_text} WHERE vid = %d", $node->vid);
+ while ($cid = db_result($result)) {
+ if (!isset($cids[$cid])) {
+ db_query("DELETE FROM {annotation_text} WHERE cid = %d AND vid = %d", $cid, $node->vid);
+ }
+ }
break;
}
}
}
/**
- * Helper that adds node context to node body, for later use in filter stage
- */
-function _annotation_text_add_context($text, $node) {
- // strip previous contexts
- $text = preg_replace('@@i', '', $text);
-
- // add context
- $text .= "";
-
- return $text;
-}
-
-/**
* Implements hook_comment().
*/
function annotation_text_comment(&$a1, $op) {
@@ -73,9 +127,6 @@ function annotation_text_comment(&$a1, $op) {
if (!isset($annotations['c'. $a1['cid']])) {
drupal_write_record('annotation_text', $a1['annotation_text']);
}
-
- cache_clear_all($node->format .':'. md5($node->body), 'cache_filter');
- cache_clear_all($node->format .':'. md5($node->teaser), 'cache_filter');
}
break;
@@ -86,42 +137,6 @@ function annotation_text_comment(&$a1, $op) {
}
/**
- * Implements hook_filter().
- */
-function annotation_text_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) {
- switch ($op) {
- case 'list':
- return array(
- 0 => t('Annotation filter'),
- );
-
- case 'description':
- switch ($delta) {
- case 0:
- return t('Attaches user annotations to text.');
-
- default:
- return;
- }
-
- case 'process':
- switch ($delta) {
- case 0:
- return annotation_text_filter_process($text, $format);
-
- default:
- return $text;
- }
-
- case 'no cache':
- return TRUE; // TODO: Don't cache for now
-
- default:
- return $text;
- }
-}
-
-/**
* Load annotations for a node version.
*/
function annotation_text_annotations($vid) {
@@ -139,25 +154,24 @@ function annotation_text_annotations($vid) {
return $annotations[$vid];
}
+
/**
- * Filter process function that does the heavy lifting
+ * Add the annotations to the text.
*/
-function annotation_text_filter_process($text, $format) {
- if (preg_match('@@i', $text, $matches)) {
- // our context
- $nid = $matches[1];
- $node = node_load($nid);
- $annotations = array();
- $corrected_annotations = array();
-
- // generate adjustment list
- $adjustments = _annotation_text_get_offset_adjustments($text);
-
- // strip all html tags
- $clean = _annotation_text_get_clean_text($text, $adjustments);
-
- $result = db_query("SELECT * FROM {annotation_text} WHERE vid = %d ORDER BY offset ASC, length ASC", $node->vid);
- while ($annotation = db_fetch_object($result)) {
+function annotation_text_add_markup($text, $node, $teaser = FALSE) {
+ $annotations = array();
+ $corrected_annotations = array();
+
+ // generate adjustment list
+ $adjustments = _annotation_text_get_offset_adjustments($text);
+
+ // strip all html tags
+ $clean = _annotation_text_get_clean_text($text, $adjustments);
+
+ $result = db_query("SELECT * FROM {annotation_text} WHERE vid = %d ORDER BY offset ASC, length ASC", $node->vid);
+ while ($annotation = db_fetch_object($result)) {
+ // Don't try to match annotations into teasers if their offset is past the teaser length.
+ if (!$teaser || $annotation->offset < strlen($text)) {
// match it up
if (($annotation->matched_offset = _annotation_text_closest_match($clean, $annotation->string, $annotation->offset, $annotation->length)) !== FALSE) {
// correct matched_offset due to html tags
@@ -166,125 +180,125 @@ function annotation_text_filter_process($text, $format) {
$annotations[] = $annotation;
}
}
-
+ }
+
+ // split up overlapping annotations
+ if (!empty($annotations)) {
+ // initialize offset
+ $offset = 0;
+
// split up overlapping annotations
- if (!empty($annotations)) {
- // initialize offset
- $offset = 0;
-
- // split up overlapping annotations
- while (1) {
- $found = FALSE;
- $corrected_annotation = FALSE;
-
- // make sure offset is not in the middle of an html tag
- // go through adjustments as adjust
- foreach ($adjustments as $pos => $tag) {
- if (($pos <= $offset) && ($offset < ($pos + strlen($tag)))) {
- $offset = $pos + strlen($tag);
- }
+ while (1) {
+ $found = FALSE;
+ $corrected_annotation = FALSE;
+
+ // make sure offset is not in the middle of an html tag
+ // go through adjustments as adjust
+ foreach ($adjustments as $pos => $tag) {
+ if (($pos <= $offset) && ($offset < ($pos + strlen($tag)))) {
+ $offset = $pos + strlen($tag);
+ }
+ }
+
+ // find first annotation that contains this offset
+ foreach ($annotations as $id => $annotation) {
+ if (($annotation->corrected_offset <= $offset) && ($offset < ($annotation->corrected_offset + $annotation->length))) {
+ $corrected_annotation = array(
+ 'offset' => $offset,
+ 'length' => $annotation->corrected_length - ($offset - $annotation->corrected_offset),
+ 'cids' => array($annotation->cid => $annotation->cid),
+ );
+ $found = TRUE;
+ break;
}
-
- // find first annotation that contains this offset
+ }
+
+ // if not found, find first annotation AFTER offset
+ if (!$found) {
foreach ($annotations as $id => $annotation) {
- if (($annotation->corrected_offset <= $offset) && ($offset < ($annotation->corrected_offset + $annotation->length))) {
+ if ($offset < $annotation->corrected_offset) {
+ $offset = $annotation->corrected_offset;
$corrected_annotation = array(
'offset' => $offset,
- 'length' => $annotation->corrected_length - ($offset - $annotation->corrected_offset),
+ 'length' => $annotation->corrected_length,
'cids' => array($annotation->cid => $annotation->cid),
);
$found = TRUE;
break;
}
}
-
- // if not found, find first annotation AFTER offset
- if (!$found) {
- foreach ($annotations as $id => $annotation) {
- if ($offset < $annotation->corrected_offset) {
- $offset = $annotation->corrected_offset;
- $corrected_annotation = array(
- 'offset' => $offset,
- 'length' => $annotation->corrected_length,
- 'cids' => array($annotation->cid => $annotation->cid),
- );
- $found = TRUE;
- break;
- }
- }
+ }
+
+ // if still not found, then we hit the end
+ if (!$found) {
+ break;
+ }
+
+ // now that we found a valid offset to work with
+ // go through annotations and adjust
+ foreach ($annotations as $id => $annotation) {
+ // collect cids if range overlaps
+ if (($annotation->corrected_offset <= $offset) && (($annotation->corrected_offset + $annotation->length) > $offset)) {
+ $corrected_annotation['cids'][$annotation->cid] = $annotation->cid;
}
-
- // if still not found, then we hit the end
- if (!$found) {
- break;
+
+ // if same offset, but shorter length
+ if (($annotation->corrected_offset == $offset) && ($annotation->length < $corrected_annotation['length'])) {
+ $corrected_annotation['length'] = $annotation->corrected_length;
}
-
- // now that we found a valid offset to work with
- // go through annotations and adjust
- foreach ($annotations as $id => $annotation) {
- // collect cids if range overlaps
- if (($annotation->corrected_offset <= $offset) && (($annotation->corrected_offset + $annotation->length) > $offset)) {
- $corrected_annotation['cids'][$annotation->cid] = $annotation->cid;
- }
-
- // if same offset, but shorter length
- if (($annotation->corrected_offset == $offset) && ($annotation->length < $corrected_annotation['length'])) {
- $corrected_annotation['length'] = $annotation->corrected_length;
- }
- // else, if higher offset, but less than curent length
- elseif (($annotation->corrected_offset > $offset) && ($annotation->corrected_offset < ($offset + $corrected_annotation['length']))) {
- $corrected_annotation['length'] = $annotation->corrected_offset - $offset;
- }
- // else, if lower offset, but end is in range
- elseif (($annotation->corrected_offset < $offset) && (($annotation->corrected_offset + $annotation->length) > $offset) && (($annotation->corrected_offset + $annotation->length) < ($offset + $corrected_annotation['length']))) {
- $corrected_annotation['length'] = ($annotation->corrected_offset + $annotation->corrected_length) - $offset;
- }
+ // else, if higher offset, but less than curent length
+ elseif (($annotation->corrected_offset > $offset) && ($annotation->corrected_offset < ($offset + $corrected_annotation['length']))) {
+ $corrected_annotation['length'] = $annotation->corrected_offset - $offset;
}
-
- // we don't want annotations breaking existing HTML tags
- // go through adjustments and shorten length as necessary
- foreach ($adjustments as $pos => $tag) {
- if (($offset < $pos) && (($pos + strlen($tag)) <= ($offset + $corrected_annotation['length']))) {
- $corrected_annotation['length'] = $pos - $offset;
- break;
- }
+ // else, if lower offset, but end is in range
+ elseif (($annotation->corrected_offset < $offset) && (($annotation->corrected_offset + $annotation->length) > $offset) && (($annotation->corrected_offset + $annotation->length) < ($offset + $corrected_annotation['length']))) {
+ $corrected_annotation['length'] = ($annotation->corrected_offset + $annotation->corrected_length) - $offset;
}
-
- // sanity check - we shouldn't have an invalid length at this time
- if ($corrected_annotation['length'] <= 0) {
+ }
+
+ // we don't want annotations breaking existing HTML tags
+ // go through adjustments and shorten length as necessary
+ foreach ($adjustments as $pos => $tag) {
+ if (($offset < $pos) && (($pos + strlen($tag)) <= ($offset + $corrected_annotation['length']))) {
+ $corrected_annotation['length'] = $pos - $offset;
break;
}
-
- // increment offset
- $offset += $corrected_annotation['length'];
-
- $corrected_annotations[] = $corrected_annotation;
}
-
- // Now that annotations are cleaned up, add annotation markup.
- $currAdjustment = 0;
- foreach ($corrected_annotations as $corrected_annotation) {
- // generate classes and anchor for this region
- $classes = array('annotation');
- foreach ($corrected_annotation['cids'] as $cid) {
- $classes[] = 'annotation-cid-'. $cid;
- }
-
- // Add class that specifies number of overlapping annotations.
- $classes[] = 'annotation-text-'. count($corrected_annotation['cids']);
-
- // Generate new string, and replace old string.
- $string = substr($text, $corrected_annotation['offset'] + $currAdjustment, $corrected_annotation['length']);
- $newString = ''. $string .'';
- $text = substr_replace($text, $newString, $corrected_annotation['offset'] + $currAdjustment, $corrected_annotation['length']);
-
- // Adjust on-the-fly adjustment so we continue to insert tags at
- // the right place.
- $currAdjustment += strlen($newString) - strlen($string);
+
+ // sanity check - we shouldn't have an invalid length at this time
+ if ($corrected_annotation['length'] <= 0) {
+ break;
}
+
+ // increment offset
+ $offset += $corrected_annotation['length'];
+
+ $corrected_annotations[] = $corrected_annotation;
+ }
+
+ // Now that annotations are cleaned up, add annotation markup.
+ $currAdjustment = 0;
+ foreach ($corrected_annotations as $corrected_annotation) {
+ // generate classes and anchor for this region
+ $classes = array('annotation');
+ foreach ($corrected_annotation['cids'] as $cid) {
+ $classes[] = 'annotation-cid-'. $cid;
+ }
+
+ // Add class that specifies number of overlapping annotations.
+ $classes[] = 'annotation-text-'. count($corrected_annotation['cids']);
+
+ // Generate new string, and replace old string.
+ $string = substr($text, $corrected_annotation['offset'] + $currAdjustment, $corrected_annotation['length']);
+ $newString = ''. $string .'';
+ $text = substr_replace($text, $newString, $corrected_annotation['offset'] + $currAdjustment, $corrected_annotation['length']);
+
+ // Adjust on-the-fly adjustment so we continue to insert tags at
+ // the right place.
+ $currAdjustment += strlen($newString) - strlen($string);
}
}
-
+
return $text;
}