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  * @name Tag
 48  * @constructor
 49  * @param {String} name
 50  * @param {Site} site
 51  * @param {String} type
 52  * @property {TagHub[]} _children
 53  * @property {Images[]} images
 54  * @property {String} name
 55  * @property {Site} site
 56  * @property {Story[]} stories
 57  * @property {String} type
 58  * @extends HopObject
 59  */
 60 Tag.prototype.constructor = function(name, site, type) {
 61    this.name = name;
 62    this.site = site;
 63    this.type = type;
 64    return this;
 65 }
 66 
 67 /**
 68  * 
 69  * @param {String} action
 70  * @returns {Boolean}
 71  */
 72 Tag.prototype.getPermission = function(action) {
 73    if (!res.handlers.site.getPermission("main")) {
 74       return false;
 75    }
 76    switch (action) {
 77       case ".":
 78       case "main":
 79       case "rss.xml":
 80       return true;
 81       case "edit":
 82       case "delete":
 83       case "rename":
 84       return User.require(User.PRIVILEGED) ||
 85             Membership.require(Membership.MANAGER);
 86    }   
 87    return false;
 88 }
 89 
 90 Tag.prototype.main_action = function() {
 91    res.handlers.list = new jala.ListRenderer(this.getTagged());
 92    res.handlers.list.setPageSize(this.site.pageSize);
 93    res.data.title = gettext("Tag: {0}", this.name);
 94    res.data.body = this.renderSkinAsString("$Tag#main");
 95    res.handlers.site.renderSkin("Site#page");
 96    res.handlers.site.log();
 97    return;
 98 }
 99 
100 Tag.prototype.rss_xml_action = function() {
101    res.dependsOn(this.site.modified);
102    res.digest();
103    res.contentType = "text/xml";
104    var tagHubs = this.getTagged().list(0, this.site.pageSize);
105    var stories = [];
106    for (var i in tagHubs) {
107       stories.push(tagHubs[i].tagged);
108    }
109    res.write(this.site.getXml(stories));
110    return;
111 }
112 
113 Tag.prototype.rename_action = function() {
114    var tag = this;
115    if (req.data.name) {
116       // Trim and remove troublesome characters  (like ../.. etc.)
117       // We call getAccessName with a virgin HopObject to allow most names
118       var name = this.getAccessName.call(new HopObject, File.getName(req.data.name));
119       tag = this.site.getTags(this.type, Tags.ALL).get(name);
120       if (!tag) {
121          tag = new Tag(name, this.site, this.type);
122          this.site.$tags.add(tag);
123       }
124       if (tag !== this) {
125          this.forEach(function() { 
126             this.tag_id = tag._id;
127          });
128          this.remove();
129          res.commit();
130       }
131    }
132    res.redirect(tag.href());
133    return;
134    
135    // FIXME: Actually, the method should work like this but it caused a mess:
136    if (req.data.name) {
137       var name = this.getAccessName.call(new HopObject, File.getName(req.data.name));
138       var tag = this.site.getTags(this.type, Tags.ALL).get(name);
139       if (tag) {
140          if (tag !== this) {
141             // move tagged items to tag like above
142          }
143       } else {
144          // rename tag like: this.name = name
145       }
146    }
147 }
148 
149 Tag.prototype.delete_action = function() {
150    var parent = this._parent;
151    while (this.size() > 0) {
152       this.get(0).remove();
153    };
154    this.remove();
155    res.redirect(this.site[Tag.MOUNTPOINTS[this.type]].href());
156 }
157 
158 /**
159  * 
160  * @param {String} action
161  * @returns {String}
162  */
163 Tag.prototype.href = function(action) {
164    res.push();
165    res.write(this.site[Tag.MOUNTPOINTS[this.type]].href());
166    res.write(encodeURIComponent(this.name));
167    res.write("/");
168    if (action) {
169       res.write(java.net.URLEncoder.encode(action));
170    }
171    return res.pop();
172 }
173 
174 /**
175  * 
176  * @param {Object} param
177  * @param {String} type
178  */
179 Tag.prototype.permission_macro = function(param, type) {
180    return this.getPermission(type);
181 }
182 
183 /**
184  * @returns {Story[]|Image[]}
185  */
186 Tag.prototype.getTagged = function() {
187    return this[pluralize(this.type.toLowerCase())];
188 }
189 
190 /**
191  * @returns {String}
192  */
193 Tag.prototype.getTitle = function() {
194    return this.name;
195 }
196 
197 /**
198  * @returns {String}
199  */
200 Tag.prototype.toString = function() {
201    return this.type + " tag " + this.name + " of Site " + this.site.alias;
202 }
203