1 //
  2 // The Antville Project
  3 // http://code.google.com/p/antville
  4 //
  5 // Copyright 2001-2007 by The Antville People
  6 //
  7 // Licensed under the Apache License, Version 2.0 (the ``License'');
  8 // you may not use this file except in compliance with the License.
  9 // You may obtain a copy of the License at
 10 //
 11 //    http://www.apache.org/licenses/LICENSE-2.0
 12 //
 13 // Unless required by applicable law or agreed to in writing, software
 14 // distributed under the License is distributed on an ``AS IS'' BASIS,
 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16 // See the License for the specific language governing permissions and
 17 // limitations under the License.
 18 //
 19 // $Revision$
 20 // $LastChangedBy$
 21 // $LastChangedDate$
 22 // $URL$
 23 //
 24 
 25 /**
 26  * @fileOverview Defines the Tag prototype.
 27  */
 28 
 29 markgettext("Tag");
 30 markgettext("tag");
 31 
 32 /**
 33  * @constant
 34  */
 35 Tag.MOUNTPOINTS = {
 36    Story: "tags",
 37    Image: "galleries"
 38 }
 39 
 40 /**
 41  * @constant
 42  */
 43 Tag.DELIMITER = ", ";
 44 
 45 /**
 46  * @name Tag
 47  * @constructor
 48  * @param {String} name
 49  * @param {Site} site
 50  * @param {String} type
 51  * @property {TagHub[]} _children
 52  * @property {Images[]} images
 53  * @property {String} name
 54  * @property {Site} site
 55  * @property {Story[]} stories
 56  * @property {String} type
 57  * @extends HopObject
 58  */
 59 Tag.prototype.constructor = function(name, site, type) {
 60    this.name = name;
 61    this.site = site;
 62    this.type = type;
 63    return this;
 64 }
 65 
 66 /**
 67  * 
 68  * @param {String} action
 69  * @returns {Boolean}
 70  */
 71 Tag.prototype.getPermission = function(action) {
 72    if (!res.handlers.site.getPermission("main")) {
 73       return false;
 74    }
 75    switch (action) {
 76       case ".":
 77       case "main":
 78       case "rss.xml":
 79       return true;
 80       case "edit":
 81       case "delete":
 82       case "rename":
 83       return User.require(User.PRIVILEGED) ||
 84             Membership.require(Membership.MANAGER);
 85    }   
 86    return false;
 87 }
 88 
 89 Tag.prototype.main_action = function() {
 90    res.handlers.list = new jala.ListRenderer(this.getTagged());
 91    res.handlers.list.setPageSize(this.site.pageSize);
 92    res.data.title = gettext("Tag: {0}", this.name);
 93    res.data.body = this.renderSkinAsString("$Tag#main");
 94    res.handlers.site.renderSkin("Site#page");
 95    res.handlers.site.log();
 96    return;
 97 }
 98 
 99 Tag.prototype.rss_xml_action = function() {
100    res.dependsOn(this.site.modified);
101    res.digest();
102    res.contentType = "text/xml";
103    var tagHubs = this.getTagged().list(0, this.site.pageSize);
104    var stories = [];
105    for (var i in tagHubs) {
106       stories.push(tagHubs[i].tagged);
107    }
108    res.write(this.site.getXml(stories));
109    return;
110 }
111 
112 Tag.prototype.rename_action = function() {
113    var tag = this;
114    if (req.data.name) {
115       // Trim and remove troublesome characters  (like ../.. etc.)
116       // We call getAccessName with a virgin HopObject to allow most names
117       var name = this.getAccessName.call(new HopObject, File.getName(req.data.name));
118       tag = this.site.getTags(this.type, Tags.ALL).get(name);
119       if (!tag) {
120          tag = new Tag(name, this.site, this.type);
121          this.site.$tags.add(tag);
122       }
123       if (tag !== this) {
124          this.forEach(function() { 
125             this.tag_id = tag._id;
126          });
127          this.remove();
128          res.commit();
129       }
130    }
131    res.redirect(tag.href());
132    return;
133    
134    // FIXME: Actually, the method should work like this but it caused a mess:
135    if (req.data.name) {
136       var name = this.getAccessName.call(new HopObject, File.getName(req.data.name));
137       var tag = this.site.getTags(this.type, Tags.ALL).get(name);
138       if (tag) {
139          if (tag !== this) {
140             // move tagged items to tag like above
141          }
142       } else {
143          // rename tag like: this.name = name
144       }
145    }
146 }
147 
148 Tag.prototype.delete_action = function() {
149    var parent = this._parent;
150    while (this.size() > 0) {
151       this.get(0).remove();
152    };
153    this.remove();
154    res.redirect(this.site[Tag.MOUNTPOINTS[this.type]].href());
155 }
156 
157 /**
158  * 
159  * @param {String} action
160  * @returns {String}
161  */
162 Tag.prototype.href = function(action) {
163    res.push();
164    res.write(this.site[Tag.MOUNTPOINTS[this.type]].href());
165    res.write(encodeURIComponent(this.name));
166    res.write("/");
167    if (action) {
168       res.write(java.net.URLEncoder.encode(action));
169    }
170    return res.pop();
171 }
172 
173 /**
174  * 
175  * @param {Object} param
176  * @param {String} type
177  */
178 Tag.prototype.permission_macro = function(param, type) {
179    return this.getPermission(type);
180 }
181 
182 /**
183  * @returns {Story[]|Image[]}
184  */
185 Tag.prototype.getTagged = function() {
186    return this[pluralize(this.type.toLowerCase())];
187 }
188 
189 /**
190  * @returns {String}
191  */
192 Tag.prototype.getTitle = function() {
193    return this.name;
194 }
195 
196 /**
197  * @returns {String}
198  */
199 Tag.prototype.toString = function() {
200    return this.type + " tag " + this.name + " of Site " + this.site.alias;
201 }
202