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