lportal 1.0.9 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/ChangeLog +71 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +6 -5
  4. data/Rakefile +23 -0
  5. data/init.rb +1 -1
  6. data/lib/acts/resourceful.rb +104 -0
  7. data/lib/company.rb +25 -0
  8. data/lib/group.rb +83 -29
  9. data/lib/journal/article.rb +8 -4
  10. data/lib/mb/category.rb +30 -59
  11. data/lib/mb/message.rb +24 -67
  12. data/lib/permission.rb +16 -0
  13. data/lib/release.rb +9 -0
  14. data/lib/resource.rb +19 -0
  15. data/lib/resource_code.rb +21 -1
  16. data/lib/role.rb +7 -27
  17. data/lib/tag/asset.rb +26 -4
  18. data/lib/user.rb +20 -23
  19. data/lib/web/layout.rb +134 -39
  20. data/lib/web/layout_set.rb +8 -4
  21. data/lib/web/portlet.rb +92 -20
  22. data/lib/web/portlet_preferences.rb +176 -13
  23. data/lib/web/portlet_properties.rb +32 -0
  24. data/lib/web/typesettings.rb +32 -7
  25. data/lportal.rb +30 -3
  26. data/migrations/20090101000001_add_sequences.rb +64 -0
  27. data/migrations/20090309000001_portlet_properties.rb +19 -0
  28. data/portlets.rb +76 -0
  29. data/schema.rb +34 -0
  30. data/test/unit/company_test.rb +21 -9
  31. data/test/unit/dl_file_test.rb +2 -1
  32. data/test/unit/group_test.rb +74 -16
  33. data/test/unit/journal/article_test.rb +15 -1
  34. data/test/unit/mb/category_test.rb +12 -15
  35. data/test/unit/mb/message_test.rb +3 -2
  36. data/test/unit/mb/thread_test.rb +1 -1
  37. data/test/unit/organization_test.rb +7 -2
  38. data/test/unit/phone_test.rb +2 -0
  39. data/test/unit/release_test.rb +25 -0
  40. data/test/unit/role_test.rb +7 -7
  41. data/test/unit/tag/asset_test.rb +59 -2
  42. data/test/unit/user_test.rb +73 -77
  43. data/test/unit/web/layout_set_test.rb +18 -1
  44. data/test/unit/web/layout_test.rb +191 -5
  45. data/test/unit/web/portlet_preferences_test.rb +314 -17
  46. data/test/unit/web/portlet_properties_test.rb +36 -0
  47. data/test/unit/web/portlet_test.rb +121 -19
  48. data/test/unit/web/typesettings_test.rb +24 -11
  49. data/version.rb +1 -2
  50. metadata +20 -6
  51. data/install.rb +0 -1
data/lib/web/layout.rb CHANGED
@@ -5,7 +5,10 @@ module Web
5
5
  set_table_name :layout
6
6
  set_primary_key :plid
7
7
 
8
- validates_uniqueness_of :layoutid, :scope => [:groupid, :privatelayout]
8
+ acts_as_resourceful
9
+
10
+ # FIXME: does not work properly. even if the layoutid is available, this causes self.errors
11
+ #validates_uniqueness_of :layoutid, :scope => [:groupid, :privatelayout]
9
12
 
10
13
 
11
14
  # com.liferay.portal.model.Layout
@@ -34,6 +37,7 @@ module Web
34
37
  # Optional extra parameters:
35
38
  # - locale
36
39
  def initialize(params)
40
+ logger.debug params.inspect
37
41
  raise 'No groupid given' unless (params[:groupid] or params[:group])
38
42
  raise 'No privatelayout given' if params[:privatelayout].nil?
39
43
  _name = params.delete(:name) || 'New layout'
@@ -52,11 +56,13 @@ module Web
52
56
  name += _name
53
57
  name += '</name></root>'
54
58
  self.name = name
59
+ self.save
55
60
 
56
61
  # perhaps layoutid could be sequenced.
57
62
  layouts = (self.is_public? ? self.group.public_layouts : self.group.private_layouts)
58
63
  _ids = (layouts.any? ? layouts.collect(&:layoutid) : nil)
59
64
  self.layoutid = (_ids.nil? ? 1 : _ids.sort.max+1)
65
+ self.save
60
66
 
61
67
  # increment pagecount
62
68
  _set = self.layoutset
@@ -88,34 +94,11 @@ module Web
88
94
  # +201 2 10166
89
95
  # +202 3 10301
90
96
 
91
- rc = self.resource_code(2)
92
- unless rc
93
- rc = ResourceCode.create(
94
- :companyid => self.companyid,
95
- :name => self.liferay_class,
96
- :scope => 2
97
- )
98
- end
99
- unless Resource.find(:first, :conditions => "codeid=#{rc.id} AND primkey='#{self.group.id}'")
100
- Resource.create(
101
- :codeid => rc.id,
102
- :primkey => self.group.id
103
- )
104
- end
97
+ self.get_resource(:scope => 2)
105
98
 
106
99
  # Create a resource with scope=4 for this Layout.
107
- rc = self.resource_code(4)
108
- unless rc
109
- rc = ResourceCode.create(
110
- :companyid => self.companyid,
111
- :name => self.liferay_class,
112
- :scope => 4
113
- )
114
- end
115
- resource = Resource.create(
116
- :codeid => rc.id,
117
- :primkey => self.id
118
- )
100
+ resource = self.get_resource(:scope => 4)
101
+ logger.debug 'resource: %s' % resource.inspect
119
102
 
120
103
  # COPY permission_ (permissionid, companyid, actionid, resourceid) FROM stdin;
121
104
  # +301 10109 ADD_DISCUSSION 202
@@ -123,7 +106,7 @@ module Web
123
106
  # +303 10109 VIEW 202
124
107
 
125
108
  self.class.actions.each do |actionid|
126
- p = Permission.create(
109
+ p = Permission.get(
127
110
  :companyid => self.companyid,
128
111
  :actionid => actionid,
129
112
  :resourceid => resource.id
@@ -133,21 +116,50 @@ module Web
133
116
  # +10129 301
134
117
  # +10129 302
135
118
  # +10129 303
136
- # +10111 303
137
119
 
120
+ # admins can do everything
138
121
  self.company.administrators.each do |user|
139
- user.user_permissions << p
122
+ user.permissions << p
140
123
  end
141
124
 
142
125
  # COPY groups_permissions (groupid, permissionid) FROM stdin;
143
126
  # +10166 301
144
127
  # +10166 303
145
- group = self.group
146
- self.group.permissions << p
128
+
129
+ # group members can ADD_DISCUSSION and VIEW
130
+ if (actionid=='ADD_DISCUSSION' or actionid=='VIEW')
131
+ self.group.permissions << p
132
+ end
133
+
134
+ # COPY users_permissions (userid, permissionid) FROM stdin;
135
+ # +10111 303
136
+
137
+ # guest is permitted to VIEW if the layout is public.
138
+ if self.is_public? and actionid=='VIEW'
139
+ self.company.guest.permissions << p
140
+ end
141
+
147
142
  end
143
+
144
+ # the layout management portlet (new in 5.2.x?)
145
+
146
+ # COPY portletpreferences (portletpreferencesid, ownerid, ownertype, plid, portletid, preferences) FROM stdin;
147
+ # +10259 0 3 10301 88 <portlet-preferences />
148
+
149
+ # perhaps this will create itself?
150
+ # Web::PortletPreferences.create(:plid => self.plid, :portletid => 88)
151
+
148
152
  return self
149
153
  end
150
154
 
155
+ def save
156
+ super
157
+ if self.errors.any?
158
+ logger.error self.errors.inspect
159
+ raise self.errors[:layoutid] if self.errors[:layoutid]
160
+ end
161
+ end
162
+
151
163
  public
152
164
 
153
165
  belongs_to :group,
@@ -207,17 +219,100 @@ module Web
207
219
 
208
220
  # the URL path to this Layout
209
221
  def path
210
- self.layoutset.url_prefix + self.group.friendlyurl + self.friendlyurl
222
+ self.layoutset ?
223
+ self.layoutset.url_prefix + self.group.friendlyurl + self.friendlyurl : ''
224
+ end
225
+
226
+ # Settings for this Layout.
227
+ #
228
+ # Returns the object model of the string "typesettings".
229
+ def settings
230
+ Typesettings.new(self.typesettings)
211
231
  end
212
232
 
213
- # ResourceCode associated to this instance (and scope)
214
- def resource_code(scope=4)
215
- ResourceCode.find(:first,
216
- :conditions => "companyid=#{self.companyid} AND name='#{self.liferay_class}' AND scope=#{scope}")
233
+ # Save settings. Parses them to typesettings string.
234
+ #
235
+ # Parameters:
236
+ # - ts = Typesettings instance
237
+ def settings=(ts)
238
+ raise 'parameter must be a Typesettings instance' unless ts.is_a?(Typesettings)
239
+ self.typesettings = ts.to_s
217
240
  end
218
241
 
219
- def contents
220
- Typesettings.new(self.typesettings)
242
+ # As the method 'name' returns the name in XML, name_string is the string representation.
243
+ def name_string
244
+ self.name[/([^>]*)<\/name/,1]
245
+ end
246
+
247
+ # Insert the name string to XML.
248
+ def name_string=(name)
249
+ self.name = "<?xml version='1.0' encoding='UTF-8'?>"+\
250
+ '<root available-locales="en_US" default-locale="en_US"><name language-id="en_US">%s</name></root>' % name
251
+ end
252
+
253
+ # sets the number of columns in this layout
254
+ def columns=(nr)
255
+ s = self.settings
256
+ s.columns = nr
257
+ self.settings = s
258
+ end
259
+
260
+ # Add a portlet to this layout.
261
+ def <<(portlet, params={})
262
+ unless portlet
263
+ logger.debug 'No portlet given'
264
+ return false
265
+ end
266
+
267
+ if portlet.is_a?(Web::PortletPreferences)
268
+ preferences = portlet
269
+ portlet = preferences.portlet
270
+ else
271
+ preferences = portlet.preferences
272
+ end
273
+
274
+ # define the layout
275
+ preferences.layout = self
276
+ preferences.save
277
+
278
+ # not very OO..
279
+ settings = self.settings
280
+ location = (params[:location] ||= {:column => 1})
281
+ #puts location.inspect
282
+
283
+ # accept either a string or a symbol or Portlet
284
+ # puts portlet.inspect
285
+ # puts settings.portlets.inspect
286
+ settings.portlets.update(
287
+ location[:column] => [preferences || portlet]
288
+ )
289
+ # puts settings.portlets.inspect
290
+ self.settings=settings
291
+
292
+ [1,2].each do |scope|
293
+ preferences.get_resource(:scope => scope)
294
+ end
295
+
296
+ # guest permissions are given if the layout is public.
297
+ # (TODO: AND IF THE GROUP IS GUEST)
298
+
299
+ resource = preferences.get_resource(:scope => 4)
300
+ preferences.class.actions.each do |actionid|
301
+ p = Permission.get(
302
+ :companyid => self.companyid,
303
+ :actionid => actionid,
304
+ :resourceid => resource.id
305
+ )
306
+ if actionid=='VIEW'
307
+ self.group.permissions << p
308
+ if self.is_public?
309
+ guest = self.company.guest
310
+ guest.permissions << p
311
+ end
312
+ end
313
+ end
314
+
315
+ self
221
316
  end
222
317
 
223
318
  end
@@ -45,14 +45,18 @@ module Web
45
45
  end
46
46
 
47
47
  def layouts
48
+ return 0 unless self.group
48
49
  Web::Layout.find(:all, :conditions => "groupid=#{self.groupid} AND privatelayout=#{self.privatelayout}" )
49
50
  end
50
51
 
51
52
  # lookup the path prefix for this LayoutSet
52
53
  def url_prefix
54
+ return '' unless self.group
53
55
  return '/web' if self.is_public?
54
-
55
- _class = Classname.model(Classname.find(self.group.classnameid).value)
56
+ _class = (
57
+ self.group.classnameid==0 ?
58
+ Group : Classname.model(Classname.find(self.group.classnameid).value)
59
+ )
56
60
  if _class == User
57
61
  return '/user' #if self.is_private?
58
62
  #return '/web'
@@ -62,8 +66,8 @@ module Web
62
66
  #return '/web'
63
67
 
64
68
  else
65
- logger.debug 'FIXME: ' + _class
66
- return nil
69
+ logger.debug 'FIXME: %s' % _class
70
+ return ''
67
71
  end
68
72
  end
69
73
 
data/lib/web/portlet.rb CHANGED
@@ -1,47 +1,119 @@
1
- module Web
2
- # Not all portlets are necessarily saved in the database.
1
+ module Web # :nodoc:
2
+ # Portlets can be included onto a Layout. Portlets are not instantiated per se; when one is
3
+ # inserted on a Layout, PortletPreferences is created. This instance (from ActiveRecord's point-of-view),
4
+ # may be instantiated or not, from Liferay's POV. Instantiation in this sense means that each PortletPreferences
5
+ # may have session-based customization.
6
+ #
7
+ # Caterpillar can gather this information from the Liferay XML files, see its documentation.
8
+ #
3
9
  class Portlet < ActiveRecord::Base
4
10
  set_table_name :portlet
5
11
  set_primary_key :id_
6
12
 
7
13
  public
8
14
 
15
+ # com.liferay.portal.model.Portlet
16
+ def liferay_class
17
+ 'com.liferay.portal.model.Portlet'
18
+ end
19
+
9
20
  belongs_to :company,
10
21
  :foreign_key => "companyid"
11
22
 
12
- def name
13
- self.portletid
23
+ # Creates a portlet instance with preferences.
24
+ def initialize(params={})
25
+ super(params)
26
+ self.roles ||= ''
27
+ self.active_ = true if self.active_.nil?
28
+
29
+ self
14
30
  end
15
31
 
16
- # primkey in resource_ table
17
- def primkey(plid)
18
- "#{plid}_LAYOUT_#{self.portletid}"
32
+
33
+ # Searches from PortletProperties.
34
+ # Returns nil unless one is found. Returns a Portlet if the properties are found.
35
+ def self.find_by_name(name)
36
+ pp = Web::PortletProperties.find_by_name(name)
37
+ unless pp
38
+ logger.warn 'Portlet by name was not found -- are portletproperties up-to-date?'
39
+ return nil
40
+ end
41
+ pp.portlet
19
42
  end
20
43
 
21
- def resource(plid)
22
- Resource.find_by_primkey(self.primkey(plid))
44
+
45
+ # PortletPreferences for this instance (@preferences)
46
+ #
47
+ # This Web::Portlet instance may have several "instances of itself", each of which are stored
48
+ # in PortletPreferences. Each of these are unique rows in the database,
49
+ # and these are accessible through the 'instances' association.
50
+ #
51
+ # PortletPreferences are created when the Portlet is added to a Layout.
52
+ # Its portletid, on the other hand, depends on whether this portlet is instanceable.
53
+ def preferences
54
+ unless @preferences
55
+ @preferences = Web::PortletPreferences.create({:portlet => self})
56
+ end
57
+ return @preferences
23
58
  end
24
59
 
25
- # all instances
26
- def resources
27
- # Resource.find_by_primkey(self.primkey)
28
- # Resource.find(:all, :conditions => "primkey='#{self.primkey}'")
29
- resources = []
30
- ResourceCode.find(:all, :conditions => "name='#{portletid}'").each do |rc|
31
- resources << Resource.find(:all, :conditions => "codeid='#{rc.id}'")
60
+ attr_writer :preferences
61
+
62
+ # All instances of a specific portlet. See also preferences.
63
+ def instances
64
+ unless @instances
65
+ @instances = Web::PortletPreferences.find_all_by_portletid(self.portletid)
32
66
  end
67
+ return @instances
68
+ end
69
+
70
+ # Various static properties of the portlet instance and the portlet in general.
71
+ # Requires custom migrations for PortletProperties.
72
+ # The tables within are filled by Caterpillar, since it knows the location of the
73
+ # portlet XML files.
74
+ def properties
75
+ unless @properties
76
+ @properties = Web::PortletProperties.find_by_portletid(self.portletid)
77
+ end
78
+ return @properties
79
+ end
33
80
 
34
- return resources.flatten
81
+ # The default title string that is displayed.
82
+ #
83
+ # Requires custom migrations for PortletProperties. Defaults to an empty string.
84
+ #
85
+ # PortletPreferences may override this, see PortletPreferences#title.
86
+ #
87
+ def title
88
+ self.properties ?
89
+ self.properties.title : ''
90
+ end
91
+
92
+ # Portlet's JSR286 name.
93
+ #
94
+ # Requires custom migrations for PortletProperties. Defaults to portletid.
95
+ #
96
+ def name
97
+ self.properties ?
98
+ self.properties.name : self.portletid
35
99
  end
36
100
 
37
101
  def is_active?
38
102
  self.active_
39
103
  end
40
104
 
41
- # comply API with Web::PortletPreferences
42
- def preferences_
43
- ""
105
+ # Is the portlet instanceable? This is defined in the XML configuration.
106
+ # Requires custom migrations for PortletProperties.
107
+ #
108
+ # Defaults to true.
109
+ def instanceable?
110
+ return @instanceable if !@instanceable.nil? # test value
111
+ self.properties ?
112
+ self.properties.instanceable : true
44
113
  end
45
114
 
115
+ # for testing and debugging
116
+ attr_writer :instanceable
117
+
46
118
  end
47
119
  end
@@ -1,38 +1,167 @@
1
1
  module Web
2
+ # While PortletPreferences acts_as_resourceful, it is a resource as the portlet it represents.
3
+ # The ResourceCode has a 'name' value that is the Portlet's portletid.
4
+ #
5
+ # Also see Lportal::Portlets, that adds a method +path+.
2
6
  class PortletPreferences < ActiveRecord::Base
3
7
  set_table_name :portletpreferences
4
8
  set_primary_key :portletpreferencesid
5
9
 
10
+ acts_as_resourceful
11
+
12
+ include Lportal::Portlets
13
+
6
14
  public
7
15
 
16
+ # com.liferay.portal.model.PortletPreferences
17
+ def liferay_class
18
+ 'com.liferay.portal.model.PortletPreferences'
19
+ end
20
+
21
+ # add portlets to layouts via Layout#<<
8
22
  belongs_to :layout,
9
23
  :class_name => 'Web::Layout',
10
24
  :foreign_key => 'plid'
11
25
 
12
- belongs_to :owner,
13
- :class_name => 'User',
14
- :foreign_key => 'ownerid'
26
+ # this is more complicated than this.
27
+ # belongs_to :owner,
28
+ # :class_name => 'User',
29
+ # :foreign_key => 'ownerid'
15
30
 
16
- def name
31
+
32
+ # Actions for Permissions.
33
+ def self.actions
34
+ %w{
35
+ CONFIGURATION
36
+ VIEW
37
+ }
38
+ end
39
+
40
+ # PortletPreferences instance keeps record of unique Portlet preferences.
41
+ #
42
+ # Parameteres:
43
+ # - portletid (String) (or portlet)
44
+ # - portlet Web::Portlet
45
+ # - preferences String
46
+ def initialize(params={})
47
+ portlet = params.delete(:portlet) if params[:portlet]
48
+
49
+ super(params)
50
+
51
+ self.preferences ||= '<portlet-preferences />'
52
+ self.ownerid ||= 0 # ??
53
+ self.ownertype ||= 3 # ??
54
+
55
+ # since the instance in not yet saved, the portletid might be integer
56
+ portlet ||= Web::Portlet.find_by_portletid("#{self.portletid}")
57
+ if portlet
58
+ self.portlet = portlet # instantiates if applicaple
59
+ else
60
+ # nil is most likely an error. the portlet database is not populated?
61
+ # in this case default to fallback action and instantiate the portlet.
62
+ self.portletid = self.class.instance_id(self.portletid)
63
+ end
64
+ self
65
+ end
66
+
67
+ # generates a random instance id
68
+ def self.instance_id(portletid)
69
+ '%s_INSTANCE_%s' % [portletid, random_string(4)]
70
+ end
71
+
72
+ # Defines the portlet that the preferences describe.
73
+ # Instantiates if the portlet can instantiated.
74
+ def portlet=(portlet)
75
+ self.portletid = (
76
+ portlet.instanceable? ?
77
+ self.class.instance_id(portlet.portletid) : portlet.portletid
78
+ )
79
+ end
80
+
81
+ # The Web::Portlet of this "preferences".
82
+ def portlet
83
+ unless @portlet
84
+ unless self.companyid
85
+ logger.warn 'Requested portlet of portletpreferences -- yet no companyid could be fetched.'
86
+ @portlet = nil
87
+ else
88
+ logger.debug 'ok'
89
+ logger.debug self.portlet_id
90
+ @portlet = Web::Portlet.find(:first,
91
+ :conditions => "companyid=#{self.companyid} AND portletid='#{self.portlet_id}'")
92
+ end
93
+ end
94
+ logger.debug @portlet.inspect
95
+ return @portlet
96
+ end
97
+
98
+ # Various static properties of the portlet instance and the portlet in general.
99
+ # Requires custom migrations for PortletProperties.
100
+ # The tables within are filled by Caterpillar, since it knows the location of the
101
+ # portlet XML files.
102
+ #
103
+ # This is intentionally duplicated for Web::Portlet to minimize database queries.
104
+ def properties
105
+ unless @properties
106
+ @properties = Web::PortletProperties.find_by_portletid(self.portlet_id)
107
+ end
108
+ return @properties
109
+ end
110
+
111
+ # The portletid of the Web::Portlet. <tt>portletid</tt> is still the actual portletid of the instance.
112
+ def portlet_id
17
113
  self.portletid.split(/_INSTANCE_/)[0]
18
114
  end
19
115
 
20
- # primkey in resource_ table
116
+ # the 4-char random string
117
+ def instance_id
118
+ self.portletid.split(/_INSTANCE_/)[1]
119
+ end
120
+
121
+ # The default title string that is displayed. Requires custom migrations for PortletProperties.
122
+ # Rails-portlets override this, with the value of <head><title>.
123
+ # There are no Ruby setters yet, this value is read-only.
124
+ #
125
+ # TODO: parse self.preferences:
126
+ # <portlet-preferences>
127
+ # <preference>
128
+ # <name>portlet-setup-title-fi_FI</name>
129
+ # <value>my custom title</value>
130
+ # </preference>
131
+ # <preference>
132
+ # <name>portlet-setup-use-custom-title</name>
133
+ # <value>true</value>
134
+ # </preference>
135
+ # </portlet-preferences>
136
+ def title
137
+ self.properties ?
138
+ self.properties.title : ''
139
+ end
140
+
141
+ # Portlet's JSR286 name.
142
+ #
143
+ # Requires custom migrations for PortletProperties. Defaults to portlet's portletid.
144
+ #
145
+ def name
146
+ self.properties ?
147
+ self.properties.name : self.portlet_id
148
+ end
149
+
150
+ # primkey is the foreign key in the resource_ table.
21
151
  def primkey
152
+ logger.debug 'primkey'
22
153
  "#{self.plid}_LAYOUT_#{self.portletid}"
23
154
  end
24
155
 
25
- # argument plid is to comply API with Web::Portlet.resource
26
- def resource(plid=nil)
27
- Resource.find_by_primkey(self.primkey)
28
- # Resource.find(:all, :conditions => "primkey='#{self.primkey}'")
156
+ # Parses the preferences string to an XML structure
157
+ def to_xml
158
+ REXML::Document.new(self.preferences)
29
159
  end
30
160
 
31
- # loads the preferences XML structure to Ruby Hash
32
- def preferences_
33
- xml = REXML::Document.new(self.preferences)
161
+ # Translates the preferences XML structure to Array of Hashes.
162
+ def to_a
34
163
  preferences = []
35
- xml.elements.each("portlet-preferences/preference") do |pref|
164
+ self.to_xml.elements.each("portlet-preferences/preference") do |pref|
36
165
  phash = {
37
166
  :name => pref.elements["name"].text,
38
167
  :value => (pref.elements["value"] ? pref.elements["value"].text : "")
@@ -42,5 +171,39 @@ module Web
42
171
  return preferences
43
172
  end
44
173
 
174
+ attr_writer :companyid
175
+
176
+ # @companyid can be set temporarily.
177
+ # if layout is set, its companyid is used.
178
+ def companyid
179
+ ( self.layout ? self.layout.companyid : @companyid
180
+ ) or nil
181
+ end
182
+
183
+ # Override acts_as_resourceful. Use portlet's portletid (without INSTANCE) as the ResourceCode name.
184
+ def resource_code(scope=4)
185
+ ResourceCode.get({
186
+ :companyid => self.companyid,
187
+ :name => self.portlet_id,
188
+ :scope => scope
189
+ })
190
+ end
191
+
192
+ def scope2_primkey
193
+ self.layout ?
194
+ self.layout.groupid : nil
195
+ end
196
+
197
+ def scope4_primkey
198
+ self.primkey
199
+ end
200
+
201
+ private
202
+
203
+ def self.random_string(len=10)
204
+ chars = ('a'..'z').to_a + ('A'..'Z').to_a
205
+ (0...len).collect { chars[Kernel.rand(chars.length)] }.join
206
+ end
207
+
45
208
  end
46
209
  end
@@ -0,0 +1,32 @@
1
+ module Web # :nodoc:
2
+ # This table is not in the original lportal database.
3
+ # This is created by a ActiveRecord migration and contains metadata about portlets.
4
+ class PortletProperties < ActiveRecord::Base
5
+ set_table_name :portletproperties
6
+
7
+ # Returns a portlet from a random company unless @companyid is set.
8
+ def portlet
9
+ unless @portlet
10
+ conditions = ["portletid='#{self.portletid}'"]
11
+ conditions << "companyid=#{@companyid}" if @companyid
12
+ @portlet = Web::Portlet.find(:first, :conditions => conditions.join(' AND '))
13
+ unless @portlet
14
+ # create
15
+ p = Web::Portlet.create(
16
+ :portletid => self.portletid
17
+ )
18
+ if @companyid
19
+ p.companyid = @companyid
20
+ p.save
21
+ end
22
+ @portlet = p.reload
23
+ end
24
+ end
25
+ return @portlet
26
+ end
27
+
28
+ # @companyid can be set temporarily.
29
+ attr_accessor :companyid
30
+
31
+ end
32
+ end