zena 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +38 -1
- data/app/controllers/documents_controller.rb +7 -5
- data/app/controllers/nodes_controller.rb +47 -6
- data/app/controllers/user_sessions_controller.rb +12 -3
- data/app/controllers/virtual_classes_controller.rb +8 -2
- data/app/models/acl.rb +5 -2
- data/app/models/cached_page.rb +5 -5
- data/app/models/column.rb +27 -4
- data/app/models/group.rb +1 -1
- data/app/models/node.rb +106 -24
- data/app/models/note.rb +2 -1
- data/app/models/relation.rb +9 -4
- data/app/models/relation_proxy.rb +2 -2
- data/app/models/role.rb +12 -5
- data/app/models/site.rb +10 -9
- data/app/models/skin.rb +8 -0
- data/app/models/string_hash.rb +65 -0
- data/app/models/text_document.rb +1 -1
- data/app/models/user.rb +2 -0
- data/app/models/virtual_class.rb +43 -10
- data/app/views/comments/create.rjs +1 -32
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/documents/show.rhtml +1 -1
- data/app/views/groups/_form.rhtml +7 -0
- data/app/views/groups/_li.rhtml +1 -1
- data/app/views/nodes/500.html +2 -1
- data/app/views/nodes/destroy.rjs +2 -0
- data/app/views/sites/jobs.erb +2 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
- data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
- data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
- data/app/views/versions/custom_tab.rhtml +1 -1
- data/app/views/versions/edit.rhtml +1 -1
- data/bricks/acls/lib/bricks/acls.rb +3 -3
- data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
- data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
- data/bricks/fs_skin/zena/init.rb +1 -0
- data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
- data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
- data/bricks/fs_skin/zena/tasks.rb +26 -0
- data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
- data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
- data/bricks/grid/lib/bricks/grid.rb +4 -3
- data/bricks/tags/lib/bricks/tags.rb +1 -7
- data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
- data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
- data/config/bricks.yml +3 -3
- data/config/gems.yml +2 -3
- data/lib/tasks/zena.rake +7 -3
- data/lib/zafu.rb +7 -0
- data/lib/zafu/all.rb +21 -0
- data/lib/zafu/compiler.rb +7 -0
- data/lib/zafu/controller_methods.rb +58 -0
- data/lib/zafu/handler.rb +57 -0
- data/lib/zafu/info.rb +4 -0
- data/lib/zafu/markup.rb +309 -0
- data/lib/zafu/mock_helper.rb +42 -0
- data/lib/zafu/node_context.rb +203 -0
- data/lib/zafu/ordered_hash.rb +53 -0
- data/lib/zafu/parser.rb +676 -0
- data/lib/zafu/parsing_rules.rb +382 -0
- data/lib/zafu/process/ajax.rb +530 -0
- data/lib/zafu/process/conditional.rb +92 -0
- data/lib/zafu/process/context.rb +186 -0
- data/lib/zafu/process/forms.rb +143 -0
- data/lib/zafu/process/html.rb +186 -0
- data/lib/zafu/process/ruby_less_processing.rb +321 -0
- data/lib/zafu/security.rb +15 -0
- data/lib/zafu/template.rb +25 -0
- data/lib/zafu/test_helper.rb +19 -0
- data/lib/zafu/view_methods.rb +6 -0
- data/lib/zena.rb +1 -1
- data/lib/zena/acts/enrollable.rb +1 -1
- data/lib/zena/app.rb +4 -17
- data/lib/zena/console.rb +18 -1
- data/lib/zena/core_ext/file_utils.rb +13 -1
- data/lib/zena/core_ext/fixnum.rb +4 -0
- data/lib/zena/core_ext/float.rb +7 -0
- data/lib/zena/deploy.rb +4 -2
- data/lib/zena/deploy/app_init.rhtml +2 -1
- data/lib/zena/deploy/database.rhtml +1 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +4 -4
- data/lib/zena/routes.rb +1 -1
- data/lib/zena/test_controller.rb +1 -1
- data/lib/zena/use.rb +14 -1
- data/lib/zena/use/action.rb +4 -2
- data/lib/zena/use/ajax.rb +86 -38
- data/lib/zena/use/authlogic.rb +16 -1
- data/lib/zena/use/calendar.rb +37 -17
- data/lib/zena/use/conditional.rb +2 -2
- data/lib/zena/use/context.rb +30 -9
- data/lib/zena/use/dates.rb +39 -3
- data/lib/zena/use/display.rb +6 -19
- data/lib/zena/use/forms.rb +100 -79
- data/lib/zena/use/i18n.rb +40 -16
- data/lib/zena/use/query_builder.rb +0 -6
- data/lib/zena/use/query_node.rb +17 -4
- data/lib/zena/use/relations.rb +1 -3
- data/lib/zena/use/rendering.rb +10 -8
- data/lib/zena/use/scope_index.rb +5 -1
- data/lib/zena/use/search.rb +2 -1
- data/lib/zena/use/urls.rb +82 -77
- data/lib/zena/use/workflow.rb +12 -4
- data/lib/zena/use/zafu_safe_definitions.rb +37 -9
- data/lib/zena/use/zafu_templates.rb +49 -20
- data/lib/zena/use/zazen.rb +6 -2
- data/locale/it/LC_MESSAGES/zena.mo +0 -0
- data/locale/it/zena.mo +0 -0
- data/locale/it/zena.po +1982 -0
- data/public/images/arrow_back.png +0 -0
- data/public/images/remove_tag.png +0 -0
- data/public/javascripts/grid.js +800 -199
- data/public/javascripts/window.js +1 -1
- data/public/javascripts/zena.js +130 -21
- data/public/stylesheets/grid.css +11 -2
- data/public/stylesheets/zena.css +2 -1
- data/test/custom_queries/complex.host.yml +5 -0
- data/test/fixtures/files/TestNode.zafu +36 -0
- data/test/functional/nodes_controller_test.rb +18 -1
- data/test/integration/zafu_compiler/action.yml +2 -2
- data/test/integration/zafu_compiler/ajax.yml +44 -26
- data/test/integration/zafu_compiler/asset.yml +12 -2
- data/test/integration/zafu_compiler/basic.yml +0 -16
- data/test/integration/zafu_compiler/calendar.yml +6 -6
- data/test/integration/zafu_compiler/complex_ok.yml +23 -1
- data/test/integration/zafu_compiler/conditional.yml +5 -5
- data/test/integration/zafu_compiler/context.yml +6 -5
- data/test/integration/zafu_compiler/dates.yml +23 -2
- data/test/integration/zafu_compiler/display.yml +46 -2
- data/test/integration/zafu_compiler/errors.yml +2 -2
- data/test/integration/zafu_compiler/eval.yml +35 -7
- data/test/integration/zafu_compiler/forms.yml +47 -13
- data/test/integration/zafu_compiler/i18n.yml +2 -2
- data/test/integration/zafu_compiler/meta.yml +35 -1
- data/test/integration/zafu_compiler/query.yml +23 -4
- data/test/integration/zafu_compiler/relations.yml +10 -6
- data/test/integration/zafu_compiler/roles.yml +4 -4
- data/test/integration/zafu_compiler/rubyless.yml +11 -1
- data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
- data/test/integration/zafu_compiler/security.yml +10 -6
- data/test/integration/zafu_compiler/urls.yml +23 -6
- data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
- data/test/integration/zafu_compiler/zazen.yml +14 -0
- data/test/selenium/Add/add3.rsel +8 -8
- data/test/selenium/Destroy/0setup.rsel +12 -0
- data/test/selenium/Destroy/destroy1.rsel +16 -0
- data/test/selenium/Edit/edit2.rsel +9 -9
- data/test/selenium/Edit/edit5.rsel +9 -9
- data/test/selenium/Edit/edit6.rsel +9 -9
- data/test/selenium/Form/form4.rsel +17 -0
- data/test/selenium/Toggle/toggle1.rsel +2 -0
- data/test/selenium/Toggle/toggle2.rsel +18 -0
- data/test/sites/zena/columns.yml +3 -0
- data/test/sites/zena/versions.yml +7 -0
- data/test/unit/cached_page_test.rb +13 -13
- data/test/unit/column_test.rb +26 -0
- data/test/unit/node_test.rb +16 -1
- data/test/unit/project_test.rb +6 -1
- data/test/unit/relation_test.rb +1 -1
- data/test/unit/role_test.rb +1 -1
- data/test/unit/string_hash_test.rb +30 -0
- data/test/unit/virtual_class_test.rb +31 -17
- data/test/unit/zafu_markup_test.rb +414 -0
- data/test/unit/zafu_node_context_test.rb +375 -0
- data/test/unit/zafu_ordered_hash_test.rb +69 -0
- data/test/unit/zena/acts/enrollable_test.rb +1 -1
- data/test/unit/zena/parser/zafu_asset.yml +0 -10
- data/test/unit/zena/parser/zazen.yml +1 -1
- data/test/unit/zena/parser_test.rb +1 -72
- data/test/unit/zena/use/dates_test.rb +1 -1
- data/test/unit/zena/use/rendering_test.rb +24 -7
- data/test/unit/zena/use/scope_index_test.rb +17 -0
- data/test/unit/zena/use/zazen_test.rb +2 -1
- data/zena.gemspec +71 -37
- metadata +104 -83
- data/app/views/nodes/destroy.erb +0 -0
- data/bricks/static/lib/bricks/static.rb +0 -151
- data/bricks/static/zena/init.rb +0 -1
- data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
- data/bricks/static/zena/test/unit/static_test.rb +0 -33
- data/lib/zena/parser/zafu_rules.rb +0 -244
- data/lib/zena/parser/zafu_tags.rb +0 -198
- data/lib/zena/parser/zena_rules.rb +0 -23
data/History.txt
CHANGED
@@ -1,4 +1,41 @@
|
|
1
|
-
== 1.2.
|
1
|
+
== 1.2.2 2012-08-30
|
2
|
+
|
3
|
+
* Major changes
|
4
|
+
* Basic zjs to batch create/update nodes (with grid.js).
|
5
|
+
* Zafu is not a separate gem anymore.
|
6
|
+
* Added simple support for JS Tags (used to define grid colums).
|
7
|
+
* Enabled rebuilding of templates on partial query.
|
8
|
+
* Enabled 'hash' property type.
|
9
|
+
* Enabled javascript on toggle.
|
10
|
+
* Enabled "fs_skin" brick to use zafu stored in brick file system.
|
11
|
+
* No need to use '>' or '<' in html params. \' escape works. Yeah !!
|
12
|
+
* Enabled "static" assets with symlink to skins in fs_skin bricks (/static/[brick]-[skin]/xxx.css => bricks/[brick]/skins/[skin]/static/xxx.css)
|
13
|
+
* No more strict scoping: "set" variables are rewritten if type matches.
|
14
|
+
* Added support for new in rubyless (Post.new, Post.new(:title => 'foo')).
|
15
|
+
* Added support for type in custom queries and SQLiss select "nodes select created_at as ti:time"
|
16
|
+
|
17
|
+
* Minor changes
|
18
|
+
* Fixed label traduction for param.
|
19
|
+
* Enable ajax response on Node destroy (use dummy update parameter).
|
20
|
+
* Added 'sum' method on array. <===== TODO: Document
|
21
|
+
* Added 'loading' option to [filter].
|
22
|
+
* Added 'master_template' zafu method to access the master template used for compilation.
|
23
|
+
* Fixed creation of modules bug.
|
24
|
+
* Using latest QueryBuilder (fixes default scope bug).
|
25
|
+
* Added 'ssl_on_auth' option to force https after (and during) login. <=== TODO: Document
|
26
|
+
* Removing evaluated strings if copy_id is blank.
|
27
|
+
* Exporting relations by class name instead of kpath (may differ from site to site).
|
28
|
+
* Using any character to build kpath if no character from the class name can be used.
|
29
|
+
* Going through reverse order in console's foreach in case we destroy nodes.
|
30
|
+
* Added support for "target" in [zazen] when rendering links.
|
31
|
+
* Fixed kpath propagation to relations on kpath change.
|
32
|
+
* Fixed [block] in [block] with [filter] bug.
|
33
|
+
* Added support for KPATH_VALUE(ClassName) in custom queries. <==== TODO: Document
|
34
|
+
* Fixed class scoping Contact? when current node is more specialized.
|
35
|
+
* Fixed bug on syntax error in Acl query.
|
36
|
+
* Fixed cache expire bug (some pages were not properly removed).
|
37
|
+
|
38
|
+
== 1.2.0, 1.2.1 2012-05-01
|
2
39
|
|
3
40
|
* Major changes
|
4
41
|
* Added 'remove_from_db' method to remove a site from the database.
|
@@ -61,14 +61,16 @@ class DocumentsController < ApplicationController
|
|
61
61
|
else
|
62
62
|
page.call 'UploadProgress.setAsFinished'
|
63
63
|
page.delay(1) do # allow the progress bar fade to complete
|
64
|
-
if params[:redir]
|
65
|
-
page << "Zena.reload_and_close(#{params[:redir].inspect})"
|
66
|
-
end
|
67
64
|
if params[:js]
|
68
65
|
page << params[:js]
|
69
66
|
end
|
70
|
-
if
|
71
|
-
page.
|
67
|
+
if params[:reload]
|
68
|
+
page << "Zena.t().Zena.reload(#{params[:reload].inspect})"
|
69
|
+
end
|
70
|
+
if params[:redir]
|
71
|
+
page << "Zena.reload_and_close(#{params[:redir].inspect})"
|
72
|
+
else
|
73
|
+
page.redirect_to document_url(@node[:zip], :reload => params[:reload], :js => params[:js])
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
@@ -235,9 +235,19 @@ class NodesController < ApplicationController
|
|
235
235
|
format.html {
|
236
236
|
redirect_to params[:redir] || zen_path(@node, :mode => params[:mode], :new => 'true')
|
237
237
|
}
|
238
|
-
format.js
|
238
|
+
format.js do
|
239
|
+
if params[:zjs]
|
240
|
+
attrs = {'id' => @node.zip}
|
241
|
+
params[:node].each do |k,v|
|
242
|
+
v = @node.zafu_eval(k, params[:opts])
|
243
|
+
attrs[k] = v
|
244
|
+
end
|
245
|
+
render :json => attrs.to_json, :status => :created
|
246
|
+
end
|
247
|
+
end
|
239
248
|
format.xml { render :xml => @node.to_xml(:root => 'node'), :status => :created, :location => node_url(@node) }
|
240
249
|
else
|
250
|
+
# ERROR
|
241
251
|
format.html do
|
242
252
|
flash[:error] = error_messages_for('node', :object => @node)
|
243
253
|
if request.referer
|
@@ -246,7 +256,11 @@ class NodesController < ApplicationController
|
|
246
256
|
raise ActiveRecord::RecordNotFound
|
247
257
|
end
|
248
258
|
end
|
249
|
-
format.js
|
259
|
+
format.js do
|
260
|
+
if params[:zjs]
|
261
|
+
render :json => @node.errors, :status => :unprocessable_entity
|
262
|
+
end
|
263
|
+
end
|
250
264
|
format.xml { render :xml => @node.errors, :status => :unprocessable_entity }
|
251
265
|
end
|
252
266
|
end
|
@@ -279,7 +293,7 @@ class NodesController < ApplicationController
|
|
279
293
|
end
|
280
294
|
end
|
281
295
|
|
282
|
-
format.xml
|
296
|
+
format.xml do
|
283
297
|
node_xml = @node.to_xml #need to be allocated before destroying
|
284
298
|
if node_xml && @node.destroy
|
285
299
|
render :xml => node_xml, :status => 200
|
@@ -289,7 +303,21 @@ class NodesController < ApplicationController
|
|
289
303
|
end
|
290
304
|
end
|
291
305
|
|
292
|
-
format.js
|
306
|
+
format.js do
|
307
|
+
|
308
|
+
if params[:zjs]
|
309
|
+
node_json = @node.to_json
|
310
|
+
if @node.destroy
|
311
|
+
render :json => node_json, :status => 200
|
312
|
+
else
|
313
|
+
render :json => @node.errors, :status => :unprocessable_entity
|
314
|
+
end
|
315
|
+
else
|
316
|
+
@parent = @node.parent
|
317
|
+
@node.destroy
|
318
|
+
# update_page_content(page, @parent)
|
319
|
+
end
|
320
|
+
end
|
293
321
|
|
294
322
|
end
|
295
323
|
end
|
@@ -410,7 +438,21 @@ class NodesController < ApplicationController
|
|
410
438
|
end
|
411
439
|
end # html
|
412
440
|
|
413
|
-
format.js
|
441
|
+
format.js do
|
442
|
+
@flash = flash
|
443
|
+
if params[:zjs]
|
444
|
+
if @node.errors.empty?
|
445
|
+
attrs = {}
|
446
|
+
params[:node].each do |k,v|
|
447
|
+
v = @node.zafu_eval(k, params[:opts])
|
448
|
+
attrs[k] = v
|
449
|
+
end
|
450
|
+
render :json => attrs.to_json, :status => :ok
|
451
|
+
else
|
452
|
+
render :json => @node.errors, :status => :unprocessable_entity
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
414
456
|
|
415
457
|
format.xml do
|
416
458
|
if @node.errors.empty?
|
@@ -544,7 +586,6 @@ class NodesController < ApplicationController
|
|
544
586
|
if path = request.env['REQUEST_PATH'].split('/')[2..-1]
|
545
587
|
params[:path] = path
|
546
588
|
else
|
547
|
-
Node.logger.warn("REQUEST_PATH: #{request.env['REQUEST_PATH'].inspect}")
|
548
589
|
path = params[:path]
|
549
590
|
end
|
550
591
|
end
|
@@ -28,13 +28,14 @@ class UserSessionsController < ApplicationController
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def destroy
|
31
|
+
port = request.port == 80 ? '' : ":#{request.port}"
|
31
32
|
if @user_session = UserSession.find
|
32
33
|
@user_session.destroy
|
33
34
|
reset_session
|
34
35
|
#flash.now[:notice] = _("Successfully logged out.")
|
35
|
-
redirect_to params[:redirect] || home_path(:prefix => prefix)
|
36
|
+
redirect_to "http://#{current_site.host}#{port}#{params[:redirect] || home_path(:prefix => prefix)}"
|
36
37
|
else
|
37
|
-
redirect_to home_path(:prefix => prefix)
|
38
|
+
redirect_to "http://#{current_site.host}#{port}#{home_path(:prefix => prefix)}"
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
@@ -52,5 +53,13 @@ class UserSessionsController < ApplicationController
|
|
52
53
|
def redirect_after_login
|
53
54
|
session.delete(:after_login_path) || home_path(:prefix => AUTHENTICATED_PREFIX)
|
54
55
|
end
|
55
|
-
|
56
|
+
|
57
|
+
# Overwrite redirect on https rules for this controller
|
58
|
+
def redirect_to_https
|
59
|
+
if params[:action] == 'destroy'
|
60
|
+
# ignore
|
61
|
+
else
|
62
|
+
redirect_to :protocol => "https://" if current_site.ssl_on_auth && !ssl_request? && !local_request?
|
63
|
+
end
|
64
|
+
end
|
56
65
|
end
|
@@ -133,9 +133,15 @@ class VirtualClassesController < ApplicationController
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def create
|
136
|
-
|
136
|
+
attrs = params[:virtual_class]
|
137
|
+
type = attrs.delete(:type)
|
137
138
|
if type == 'Role'
|
138
|
-
|
139
|
+
# Remove invalid attributes
|
140
|
+
accessible = ::Role.accessible_attributes
|
141
|
+
attrs.each do |k,v|
|
142
|
+
attrs.delete(k) if v.blank? or !accessible.include?(k)
|
143
|
+
end
|
144
|
+
@virtual_class = ::Role.new(attrs)
|
139
145
|
else
|
140
146
|
@virtual_class = VirtualClass.new(params[:virtual_class])
|
141
147
|
end
|
data/app/models/acl.rb
CHANGED
@@ -29,7 +29,7 @@ class Acl < ActiveRecord::Base
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def authorize?(base_node, params, request)
|
32
|
-
res = Node.find_by_sql(eval(make_query(base_node, params, request).to_s))
|
32
|
+
res = Node.find_by_sql(eval(make_query(base_node, params, request).to_s)) rescue nil
|
33
33
|
if res.empty?
|
34
34
|
nil
|
35
35
|
else
|
@@ -95,8 +95,11 @@ class Acl < ActiveRecord::Base
|
|
95
95
|
errors.add(:query, err.message)
|
96
96
|
end
|
97
97
|
nil
|
98
|
+
rescue RubyLess::SyntaxError => err
|
99
|
+
errors.add(:query, err.message.strip)
|
100
|
+
nil
|
98
101
|
rescue => err
|
99
|
-
errors.add(:query, err.message)
|
102
|
+
errors.add(:query, err.message.strip)
|
100
103
|
nil
|
101
104
|
end
|
102
105
|
end
|
data/app/models/cached_page.rb
CHANGED
@@ -68,12 +68,13 @@ class CachedPage < ActiveRecord::Base
|
|
68
68
|
end
|
69
69
|
|
70
70
|
# Remove cached pages related to the given node.
|
71
|
-
def expire_with(node,
|
72
|
-
if
|
73
|
-
|
71
|
+
def expire_with(node, filter = nil)
|
72
|
+
if filter
|
73
|
+
list = CachedPage.find(:all, :conditions => filter[:conditions], :joins => "INNER JOIN cached_pages_nodes AS cpn ON cpn.cached_page_id = cached_pages.id AND cpn.node_id = #{node.id}")
|
74
74
|
else
|
75
|
-
|
75
|
+
list = node.cached_pages
|
76
76
|
end
|
77
|
+
expire(list)
|
77
78
|
end
|
78
79
|
|
79
80
|
private
|
@@ -127,7 +128,6 @@ class CachedPage < ActiveRecord::Base
|
|
127
128
|
def cached_page_on_destroy
|
128
129
|
# allow ../public for single site mode
|
129
130
|
filepath = "#{SITES_ROOT}#{path.gsub(%r{\.\./(?!public)},'NO/')}" # just in case...
|
130
|
-
CachedPage.logger.info "remove #{filepath}"
|
131
131
|
# if symlink points to a dead file, exist? returns false...
|
132
132
|
FileUtils.rm(filepath) if File.exist?(filepath) || File.symlink?(filepath)
|
133
133
|
CachedPage.connection.execute "DELETE FROM cached_pages_nodes WHERE cached_page_id = '#{id}'"
|
data/app/models/column.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Column < ActiveRecord::Base
|
2
2
|
include RubyLess
|
3
3
|
include Property::StoredColumn
|
4
|
-
TYPES_FOR_FORM = %w{string datetime integer float}
|
4
|
+
TYPES_FOR_FORM = %w{string datetime integer float hash}
|
5
5
|
|
6
6
|
INDICES_FOR_FORM = %w{string ml_string datetime integer float}
|
7
7
|
|
@@ -70,16 +70,39 @@ class Column < ActiveRecord::Base
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def type_cast(value)
|
73
|
+
if value.blank?
|
74
|
+
return nil
|
75
|
+
end
|
73
76
|
if ptype == 'datetime'
|
74
|
-
if value.
|
75
|
-
nil
|
76
|
-
elsif value.kind_of?(Time)
|
77
|
+
if value.kind_of?(Time)
|
77
78
|
value
|
78
79
|
elsif value.kind_of?(String)
|
79
80
|
value.to_utc(_(Zena::Use::Dates::DATETIME), visitor.tz)
|
80
81
|
else
|
81
82
|
nil
|
82
83
|
end
|
84
|
+
elsif ptype == 'hash'
|
85
|
+
if value.kind_of?(Hash)
|
86
|
+
StringHash.from_hash(value)
|
87
|
+
elsif value.kind_of?(String)
|
88
|
+
StringHash.from_string(value)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def merge_hash(orig, value)
|
96
|
+
unless orig.kind_of?(StringHash)
|
97
|
+
orig = StringHash.from_hash(orig)
|
98
|
+
end
|
99
|
+
orig.merge!(value)
|
100
|
+
return orig
|
101
|
+
end
|
102
|
+
|
103
|
+
def klass
|
104
|
+
if ptype == 'hash'
|
105
|
+
StringHash
|
83
106
|
else
|
84
107
|
nil
|
85
108
|
end
|
data/app/models/group.rb
CHANGED
@@ -13,7 +13,7 @@ class Group < ActiveRecord::Base
|
|
13
13
|
|
14
14
|
include RubyLess
|
15
15
|
safe_method :name => String
|
16
|
-
attr_accessible :name, :user_ids, :replace_by # FIXME: add user_ids ? + add users validation (are in site)
|
16
|
+
attr_accessible :name, :user_ids, :replace_by, :auto_publish # FIXME: add user_ids ? + add users validation (are in site)
|
17
17
|
has_and_belongs_to_many :users, :order=>'login'
|
18
18
|
validates_presence_of :name
|
19
19
|
validate :valid_group
|
data/app/models/node.rb
CHANGED
@@ -185,6 +185,7 @@ class Node < ActiveRecord::Base
|
|
185
185
|
before_create :node_before_create
|
186
186
|
after_save :spread_project_and_section
|
187
187
|
after_create :node_after_create
|
188
|
+
after_destroy :node_after_destroy
|
188
189
|
attr_protected :zip, :id, :section_id, :project_id, :publish_from, :created_at, :updated_at
|
189
190
|
attr_protected :site_id
|
190
191
|
|
@@ -208,6 +209,7 @@ class Node < ActiveRecord::Base
|
|
208
209
|
safe_property :title, :text, :summary
|
209
210
|
|
210
211
|
safe_attribute :created_at, :updated_at, :event_at, :log_at, :publish_from, :basepath, :inherit, :position
|
212
|
+
safe_attribute :idx_datetime1, :idx_datetime2, :idx_float1, :idx_float2, :idx_string1, :idx_string2, :idx_integer1, :idx_integer2
|
211
213
|
|
212
214
|
|
213
215
|
# safe_node_context defined in Enrollable
|
@@ -245,7 +247,9 @@ class Node < ActiveRecord::Base
|
|
245
247
|
:user => 'User',
|
246
248
|
:author => author_proc,
|
247
249
|
:vclass => {:class => 'VirtualClass', :method => 'virtual_class'},
|
248
|
-
:new_record? => Boolean
|
250
|
+
:new_record? => Boolean,
|
251
|
+
[:eval, String] => {:class => String, :method => 'zafu_eval'},
|
252
|
+
[:eval, String, Hash] => {:class => String, :method => 'zafu_eval'}
|
249
253
|
|
250
254
|
# This is needed so that we can use secure_scope and secure in search.
|
251
255
|
extend Zena::Acts::Secure
|
@@ -290,6 +294,50 @@ class Node < ActiveRecord::Base
|
|
290
294
|
def v_number
|
291
295
|
version.number
|
292
296
|
end
|
297
|
+
|
298
|
+
Caster = ::ActiveRecord::ConnectionAdapters::Column
|
299
|
+
|
300
|
+
# Return class of cast value.
|
301
|
+
def self.cast_to_class(type)
|
302
|
+
case type
|
303
|
+
when :string then String
|
304
|
+
when :text then String
|
305
|
+
when :integer then Number
|
306
|
+
when :float then Number
|
307
|
+
when :decimal then Number
|
308
|
+
when :datetime then Time
|
309
|
+
when :timestamp then Time
|
310
|
+
when :time then Time
|
311
|
+
when :date then Time
|
312
|
+
when :binary then String
|
313
|
+
when :boolean then Boolean
|
314
|
+
else nil
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# Read with cast to an appropriate instance. This is used along with
|
319
|
+
# custom select in QueryBuilder queries.
|
320
|
+
def rcast(key, type)
|
321
|
+
@rcast_cache ||= {}
|
322
|
+
@rcast_cache[key] ||= begin
|
323
|
+
value = @attributes[key]
|
324
|
+
return nil if value.nil?
|
325
|
+
case type
|
326
|
+
when :string then value
|
327
|
+
when :text then value
|
328
|
+
when :integer then value.to_i rescue value ? 1 : 0
|
329
|
+
when :float then value.to_f
|
330
|
+
when :decimal then Caster.value_to_decimal(value)
|
331
|
+
when :datetime then Caster.string_to_time(value)
|
332
|
+
when :timestamp then Caster.string_to_time(value)
|
333
|
+
when :time then Caster.string_to_time(value)
|
334
|
+
when :date then Caster.string_to_time(value)
|
335
|
+
when :binary then Caster.binary_to_string(value)
|
336
|
+
when :boolean then Caster.value_to_boolean(value)
|
337
|
+
else value
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
293
341
|
|
294
342
|
# This is an adaptation of Versions::Multi code to use our special v_ shortcut
|
295
343
|
# to access version attributes.
|
@@ -307,6 +355,9 @@ class Node < ActiveRecord::Base
|
|
307
355
|
include Zena::Use::ScopeIndex::ModelMethods
|
308
356
|
|
309
357
|
include Zena::Use::QueryNode::ModelMethods
|
358
|
+
|
359
|
+
# Used by zafu_eval when parsing dates.
|
360
|
+
include Zena::Use::Dates::ModelMethods
|
310
361
|
|
311
362
|
@@native_node_classes = {'N' => self}
|
312
363
|
@@native_node_classes_by_name = {'Node' => self}
|
@@ -624,7 +675,7 @@ class Node < ActiveRecord::Base
|
|
624
675
|
end
|
625
676
|
|
626
677
|
entries = Dir.entries(folder).reject { |f| f =~ /^[\.~]|^__/ }.map do |filename|
|
627
|
-
String.from_filename(filename)
|
678
|
+
[filename, String.from_filename(filename)]
|
628
679
|
end.sort
|
629
680
|
|
630
681
|
index = 0
|
@@ -633,17 +684,16 @@ class Node < ActiveRecord::Base
|
|
633
684
|
catch (:next_entry) do
|
634
685
|
type = current_obj = sub_folder = document_path = nil
|
635
686
|
versions = []
|
636
|
-
filename = entries[index]
|
687
|
+
filename, title = *entries[index]
|
637
688
|
|
638
689
|
path = File.join(folder, filename)
|
639
690
|
|
640
691
|
if File.stat(path).directory?
|
641
692
|
type = :folder
|
642
|
-
title = filename
|
643
693
|
sub_folder = path
|
644
694
|
attrs = defaults.dup
|
645
695
|
attrs['v_lang'] ||= visitor.lang
|
646
|
-
elsif
|
696
|
+
elsif title =~ /^(.+?)(\.\w\w|)(\.\d+|)\.zml$/ # bird.jpg.en.zml
|
647
697
|
# node content in yaml
|
648
698
|
type = :node
|
649
699
|
title = "#{$1}#{$4}"
|
@@ -654,7 +704,7 @@ class Node < ActiveRecord::Base
|
|
654
704
|
attrs['title'] = title
|
655
705
|
attrs['v_lang'] = lang || attrs['v_lang'] || visitor.lang
|
656
706
|
versions << attrs
|
657
|
-
elsif
|
707
|
+
elsif title =~ /^((.+?)\.(.+?))(\.\w\w|)(\.\d+|)$/ # bird.jpg.en
|
658
708
|
type = :document
|
659
709
|
title = $1
|
660
710
|
attrs = defaults.dup
|
@@ -665,7 +715,6 @@ class Node < ActiveRecord::Base
|
|
665
715
|
else
|
666
716
|
# Document without extension
|
667
717
|
type = :document
|
668
|
-
title = filename
|
669
718
|
attrs = defaults.dup
|
670
719
|
lang = nil
|
671
720
|
attrs['v_lang'] = lang || attrs['v_lang'] || visitor.lang
|
@@ -674,9 +723,9 @@ class Node < ActiveRecord::Base
|
|
674
723
|
end
|
675
724
|
|
676
725
|
index += 1
|
677
|
-
while entries[index] =~ /^#{title}(\.\w\w|)(\.\d+|)\.zml$/ # bird.jpg.en.zml
|
726
|
+
while entries[index] && entries[index][1] =~ /^#{title}(\.\w\w|)(\.\d+|)\.zml$/ # bird.jpg.en.zml
|
678
727
|
lang = $1.blank? ? visitor.lang : $1[1..-1]
|
679
|
-
path = File.join(folder,entries[index])
|
728
|
+
path = File.join(folder,entries[index][0])
|
680
729
|
|
681
730
|
# we have a zml file. Create a version with this file
|
682
731
|
# no need for base_node (this is done after all with parse_assets in the controller)
|
@@ -848,10 +897,14 @@ class Node < ActiveRecord::Base
|
|
848
897
|
|
849
898
|
copy_node = new_attributes.delete(:_copy)
|
850
899
|
attributes = new_attributes.stringify_keys
|
851
|
-
|
900
|
+
|
852
901
|
if copy_node || attributes['copy_id']
|
853
|
-
copy_node
|
854
|
-
|
902
|
+
if !copy_node && attributes['copy_id'].blank?
|
903
|
+
attributes = Node.new.replace_attributes_in_values(attributes)
|
904
|
+
else
|
905
|
+
copy_node ||= Node.find_by_zip(attributes.delete('copy_id'))
|
906
|
+
attributes = copy_node.replace_attributes_in_values(attributes)
|
907
|
+
end
|
855
908
|
end
|
856
909
|
|
857
910
|
if !res['parent_id'] && p = attributes['parent_id']
|
@@ -936,6 +989,23 @@ class Node < ActiveRecord::Base
|
|
936
989
|
def zafu_versions
|
937
990
|
versions.all(:order => 'number desc')
|
938
991
|
end
|
992
|
+
|
993
|
+
# Enable dynamic property evaluation
|
994
|
+
def zafu_eval(str, opts = {})
|
995
|
+
value = safe_eval(str)
|
996
|
+
if value.kind_of?(String)
|
997
|
+
value
|
998
|
+
elsif value.kind_of?(Time)
|
999
|
+
format_date(value, opts)
|
1000
|
+
elsif value.kind_of?(Array)
|
1001
|
+
value.join(',')
|
1002
|
+
else
|
1003
|
+
value.to_s
|
1004
|
+
end
|
1005
|
+
rescue RubyLess::Error
|
1006
|
+
nil
|
1007
|
+
end
|
1008
|
+
|
939
1009
|
# Remove loaded version and properties on reload.
|
940
1010
|
def reload
|
941
1011
|
@version = nil
|
@@ -1326,12 +1396,12 @@ class Node < ActiveRecord::Base
|
|
1326
1396
|
visitor.commentator? && discussion && discussion.open?
|
1327
1397
|
end
|
1328
1398
|
|
1329
|
-
|
1330
|
-
|
1331
|
-
return if current_site.being_created?
|
1399
|
+
def sweep_cache(filter = nil)
|
1400
|
+
return true if current_site.being_created?
|
1332
1401
|
|
1333
1402
|
# Clear element cache
|
1334
|
-
|
1403
|
+
# Partial cache not used
|
1404
|
+
# Cache.sweep(:visitor_id=>self[:user_id], :visitor_groups=>[rgroup_id, wgroup_id, dgroup_id], :kpath=>self.vclass.kpath)
|
1335
1405
|
|
1336
1406
|
# Clear full result cache
|
1337
1407
|
|
@@ -1340,11 +1410,12 @@ class Node < ActiveRecord::Base
|
|
1340
1410
|
# FIXME: use self + modified relations instead of parent/project
|
1341
1411
|
[self, self.real_project(false), self.real_section(false), self.parent(false)].compact.uniq.each do |obj|
|
1342
1412
|
# destroy all pages in project, parent and section !
|
1343
|
-
CachedPage.expire_with(obj,
|
1413
|
+
CachedPage.expire_with(obj, filter)
|
1344
1414
|
end
|
1345
1415
|
|
1346
1416
|
# clear assets
|
1347
1417
|
FileUtils::rmtree(asset_path(''))
|
1418
|
+
true
|
1348
1419
|
end
|
1349
1420
|
|
1350
1421
|
# Include data entry verification in multiversion's empty? method.
|
@@ -1635,15 +1706,18 @@ class Node < ActiveRecord::Base
|
|
1635
1706
|
Discussion.create(:node_id=>self[:id], :lang=>v_lang, :inside => false)
|
1636
1707
|
end
|
1637
1708
|
end
|
1709
|
+
|
1710
|
+
def node_after_destroy
|
1711
|
+
sweep_cache
|
1712
|
+
end
|
1638
1713
|
|
1639
1714
|
# Called after a node is 'unpublished'
|
1640
1715
|
def after_unpublish
|
1641
1716
|
if !self[:publish_from] && !@new_record_before_save
|
1642
1717
|
# not published any more. 'unpublish' documents
|
1643
1718
|
sync_documents(:unpublish)
|
1644
|
-
else
|
1645
|
-
true
|
1646
1719
|
end
|
1720
|
+
sweep_cache
|
1647
1721
|
end
|
1648
1722
|
|
1649
1723
|
def after_redit
|
@@ -1653,8 +1727,10 @@ class Node < ActiveRecord::Base
|
|
1653
1727
|
|
1654
1728
|
# Called after a node is 'removed'
|
1655
1729
|
def after_remove
|
1656
|
-
|
1657
|
-
|
1730
|
+
if !@new_record_before_save
|
1731
|
+
sync_documents(:remove)
|
1732
|
+
end
|
1733
|
+
sweep_cache
|
1658
1734
|
end
|
1659
1735
|
|
1660
1736
|
# Called after a node is 'proposed'
|
@@ -1671,8 +1747,15 @@ class Node < ActiveRecord::Base
|
|
1671
1747
|
|
1672
1748
|
# Called after a node is published
|
1673
1749
|
def after_publish
|
1674
|
-
|
1675
|
-
|
1750
|
+
if !@new_record_before_save
|
1751
|
+
sync_documents(:publish)
|
1752
|
+
end
|
1753
|
+
sweep_cache
|
1754
|
+
end
|
1755
|
+
|
1756
|
+
# Called after a node is modified and directly published.
|
1757
|
+
def after_auto_publish
|
1758
|
+
sweep_cache
|
1676
1759
|
end
|
1677
1760
|
|
1678
1761
|
# Publish, refuse, propose the Documents of a redaction
|
@@ -1709,7 +1792,6 @@ class Node < ActiveRecord::Base
|
|
1709
1792
|
# This method is run whenever 'apply' is called.
|
1710
1793
|
def after_all
|
1711
1794
|
return unless super
|
1712
|
-
sweep_cache
|
1713
1795
|
if @add_comment
|
1714
1796
|
# add comment
|
1715
1797
|
@discussion ||= self.discussion
|