More work on tagging.
authorMichael J. Rubinsky <mrubinsk@horde.org>
Thu, 29 Jan 2009 18:46:51 +0000 (13:46 -0500)
committerMichael J. Rubinsky <mrubinsk@horde.org>
Thu, 29 Jan 2009 22:39:52 +0000 (17:39 -0500)
This adds tagging to the event edit form, deletion of tags from
the view panel and other tweaks.  Still need to add via panel and
calendar form.

kronolith/edit.php
kronolith/lib/Imple/TagActions.php
kronolith/lib/Tagger.php
kronolith/lib/Views/EditEvent.php
kronolith/templates/edit/edit.inc

index 372df15..c252388 100644 (file)
@@ -12,6 +12,8 @@
 function _save(&$event)
 {
     $res = $event->save();
+    $tagger = new Kronolith_Tagger();
+    $tagger->replaceTags($event->getUID(), Util::getFormData('tags'));
     if (is_a($res, 'PEAR_Error')) {
         $GLOBALS['notification']->push(sprintf(_("There was an error editing the event: %s"), $res->getMessage()), 'horde.error');
     } elseif (Util::getFormData('sendupdates', false)) {
index 1156980..89a5923 100644 (file)
@@ -1,6 +1,13 @@
 <?php
 /**
+ * Kronolith_Imple_TagActions:: Class to handle ajax requests for adding and
+ * removing tags from kronolith objects.
  *
+ * Copyright 2009 The Horde Project (http://www.horde.org)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ *
+ * @package Kronolith
  */
 class Kronolith_Imple_TagActions extends Kronolith_Imple
 {
@@ -27,6 +34,14 @@ class Kronolith_Imple_TagActions extends Kronolith_Imple
         Kronolith::addInlineScript($js, 'window');
     }
 
+    /**
+     * Handle the tag related action.
+     *
+     * If removing a tag, needs a 'resource' which is the local identifier of
+     * the kronolith object, a 'type' which should be the string reprentation of
+     * the type of object (event/calendar) and 'tags' should be the integer
+     * tag_id of the tag to remove.
+     */
     public function handle($args)
     {
         global $ansel_storage;
@@ -35,23 +50,64 @@ class Kronolith_Imple_TagActions extends Kronolith_Imple
         $content = array('id' => $args['resource'], 'type' => $args['type']);
         $tags = $args['tags'];
 
-        /* Get the resource owner */
-        /* Perms checks */
-
-        switch ($request) {
-        case 'add':
-            break;
-        case 'remove':
-            $tagger = new Kronolith_Tagger();
-            //$tagger->
-
+        // Check perms
+        if ($args['type'] == 'calendar') {
+            $cal = $GLOBALS['kronolith_shares']->getShare($args['resource']);
+            $perm = $cal->hasPermission(Auth::getAuth(), PERMS_EDIT);
+        } elseif($args['type'] == 'event') {
+            $event = $GLOBALS['kronolith_driver']->getByUID($args['resource']);
+            $perm = $event->hasPermission(PERMS_EDIT, Auth::getAuth());
+        }
 
-            break;
+        if ($perm) {
+            /* Get the resource owner */
+            switch ($request) {
+            case 'add':
+                //@TODO
+                break;
+            case 'remove':
+                $tagger = new Kronolith_Tagger();
+                $tagger->untag($args['resource'], (int)$tags, $args['type']);
+                break;
+            }
         }
+        return $this->_getTagHtml($tagger, $args['resource'], $args['type']);
+
     }
 
-    private function _getTagHtml($tags, $hasEdit)
+    /**
+     * Generate the HTML for the tag lists to send back to the browser.
+     *
+     * TODO: This should be made a view helper when we move to using Horde_View
+     *
+     * @param Kronolith_Tagger $tagger  The tagger object
+     * @param string $id                The identifier (share name or event uid)
+     * @param string $type              The type of resource (calendar/event)
+     *
+     * @return string  The HTML
+     */
+    private function _getTagHtml($tagger, $id, $type)
     {
+        $tags = $tagger->getTags($id, 'calendar');
+        $html = '';
+        $js = '';
+
+        if ($type == 'calendar') {
+            $cal = $GLOBALS['kronolith_shares']->getShare($id);
+            $hasEdit = $cal->hasPermission(Auth::getAuth(), PERMS_EDIT);
+        } elseif ($type == 'event') {
+            if ($kronolith_driver->getCalendar() != $cal) {
+                $kronolith_driver->open($cal);
+            }
+            $event = $GLOBALS['kronolith_driver']->getByUID($id);
+            $hasEdit = $event->hasPermission(PERMS_EDIT, Auth::getAuth());
+        }
+
+        foreach ($tags as $tag_id => $tag) {
+            $html .= '<li>' .  $tag . ($hasEdit ? '<a href="#" onclick="removeTag(\'' . $id . '\', \'' . $type . '\',' . $tag_id . ', \'' . Horde::url('imple.php', true) . '\'); Event.stop(event)" id="remove' . md5($id . $tag_id) . '">' . Horde::img('delete-small.png', _("Remove Tag"), '', $GLOBALS['registry']->getImageDir('horde')) . '</a>' : '') . '</li>';
+        }
+
+        return $html;
     }
 
 }
index 2ffc471..969a0c7 100644 (file)
@@ -2,14 +2,21 @@
 /**
  * Kronolith interface to the Horde_Content tagger
  *
+ * Copyright 2009 The Horde Project (http://www.horde.org)
  *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ *
+ * @package Kronolith
  */
 
-// Note:: Autoloading depends on there being a registry entry for content
+// NOTE: For now, autoloading depends on there being a registry entry for the
+//       'content' application.
+
 Horde_Autoloader::addClassPattern('/^Content_/',
                                   $GLOBALS['registry']->get('fileroot', 'content') . '/lib/');
 
-class Kronolith_Tagger {
+class Kronolith_Tagger
+{
 
     /**
      * Local cache of the type name => ids from Content, so we don't have to
@@ -74,6 +81,7 @@ class Kronolith_Tagger {
         if (!is_array($tags)) {
             $tags = self::$_tagger->splitTags($tags);
         }
+
         self::$_tagger->tag(Auth::getAuth(),
                    array('object' => $localId,
                          'type' => self::$_type_ids[$content_type]),
@@ -115,11 +123,65 @@ class Kronolith_Tagger {
     public function untag($localId, $tag, $content_type = 'event')
     {
         self::$_tagger->removeTagFromObject(
-            array('object' => $localId, 'type' => $content_type),
+            array('object' => $localId, 'type' => self::$_type_ids[$content_type]),
             $tag);
     }
 
     /**
+     * Tag the given resource with *only* the tags provided, removing any tags
+     * that are already present but not in the list.
+     *
+     * @param $localId
+     * @param $tags
+     * @param $content_type
+     *
+     * @return void
+     */
+    public function replaceTags($localId, $tags, $content_type = 'event')
+    {
+        // First get a list of existing tags.
+        $existing_tags = $this->getTags($localId, $content_type);
+
+        // If we don't have an array - split the string.
+        if (!is_array($tags)) {
+            $tags = self::$_tagger->splitTags($tags);
+        }
+        $remove = array();
+        foreach ($existing_tags as $tag_id => $existing_tag) {
+            $found = false;
+            foreach ($tags as $tag_text) {
+                //if ($existing_tag == String::lower($tag_text, true)) {
+                if ($existing_tag == $tag_text) {
+                    $found = true;
+                    break;
+                }
+            }
+            // Remove any tags that were not found in the passed in list.
+            if (!$found) {
+                $remove[] = $tag_id;
+            }
+        }
+
+        $this->untag($localId, $remove, $content_type);
+        $add = array();
+        foreach ($tags as $tag_text) {
+            $found = false;
+            foreach ($existing_tags as $existing_tag) {
+                if ($tag_text == $existing_tag) {
+                    $found = true;
+                    break;
+                }
+            }
+            if (!$found) {
+                $add[] = $tag_text;
+            }
+        }
+
+        $this->tag($localId, $add, $content_type);
+    }
+
+
+    /**
      * @TODO
      * @param array $tags  An array of tag ids.
      */
index 649fa83..73dd679 100644 (file)
@@ -99,6 +99,10 @@ class Kronolith_View_EditEvent {
 
         $event = &$this->event;
 
+        // Tags
+        $tagger = new Kronolith_Tagger();
+        $tags = $tagger->getTags($event->getUID(), 'event');
+        $tags = implode(',', array_values($tags));
         echo '<div id="EditEvent"' . ($active ? '' : ' style="display:none"') . '>';
         require KRONOLITH_TEMPLATES . '/edit/javascript.inc';
         require KRONOLITH_TEMPLATES . '/edit/edit.inc';
index ba9baa1..f5842a9 100644 (file)
   <input type="checkbox" class="checkbox" id="private" name="private"<?php if ($event->isPrivate()) echo ' checked="checked"' ?> />
  </td>
 </tr>
-
+<!-- tags  -->
+<tr>
+ <td class="rightAlign">
+     <strong><?php echo Horde::label('tags', _("Tags"))?></strong>
+ </td>
+ <td colspan="4">
+   <input type="text" name="tags" id="tags" value="<?php echo $tags?>" size="40" value="<?php echo $tags?>" />
+ </td>
+</tr>
 <?php require KRONOLITH_TEMPLATES . '/edit/edit_timespan.inc' ?>
 
 <!-- alarm -->