webflow 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,312 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+ # This module adds helper methods to WebFlow controllers. See each method
22
+ # for a complete description of their function.
23
+
24
+ require "webflow/base"
25
+
26
+ module WebFlow
27
+ module BaseHelper
28
+
29
+
30
+ # Creates a submit button to send the parent form to an WebFlow controller.
31
+ # The options array takes the same values as the standard Rails submit_tag.
32
+ #def flow_submit_tag(value="Submit", event_name='', options={})
33
+ #
34
+ # # Convert keys to strings
35
+ # options.stringify_keys!
36
+ #
37
+ # # We can't use the disable_with option since disabling the button will
38
+ # # prevent some browsers from sending the submit button name along
39
+ # # with the form data. We need this button to send the event name.
40
+ # options.delete("disable_with")
41
+ #
42
+ # # Generate the tag
43
+ # tag :input, {"type" => "submit",
44
+ # "name" => "#{WebFlow::Base.event_input_name_prefix}#{WebFlow::Base.event_prefix}#{event_name}",
45
+ # "value" => value}.update(options.stringify_keys)
46
+ #
47
+ #end
48
+
49
+
50
+ # Creates a link to send an event to an WebFlow controller.
51
+ # The method takes all the standard Rails link_to parameters
52
+ # but needs one more : the event name to return.
53
+ #def flow_link_to(name, event_name='', options = {}, html_options = nil, *parameters_for_method_reference)
54
+ #
55
+ # # Delete the action and controller definition
56
+ # options.delete :action
57
+ # options.delete :controller
58
+ #
59
+ # # Specify the 'index' action
60
+ # options[:action] = :index
61
+ #
62
+ # # Add the flow key to the url
63
+ # options[WebFlow::Base.flow_execution_key_id] = @flow_id
64
+ #
65
+ # # Add the event name
66
+ # options[WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s] = WebFlow::Base.event_prefix + event_name.to_s
67
+ #
68
+ # # Call the standard link_to helper
69
+ # link_to name, options, html_options, *parameters_for_method_reference
70
+ #
71
+ #end
72
+
73
+
74
+ # Creates a form tag to send data to the WebFlow controller.
75
+ # Takes the same parameters as Rail's form_tag, but adds the flow
76
+ # exec key hidden input. You can either declare it as a returning
77
+ # function :
78
+ #
79
+ # <%= flow_form_tag %>
80
+ #
81
+ # or give it a block :
82
+ #
83
+ # <% flow_form_tag do |form| %>
84
+ #
85
+ # See end_flow_form_tag to close the first use case.
86
+ #def flow_form_tag(options={}, &block)
87
+ #
88
+ # # Init the HTML subhash if required
89
+ # options[:html] ||= {}
90
+ #
91
+ # # Remove the action html parameter
92
+ # options[:html].delete(:action)
93
+ #
94
+ # # There are two use cases.
95
+ # #
96
+ # # 1. The user has passed a block
97
+ # # We have to extend the block to add our controls
98
+ # #
99
+ # # 2. The user hasn't passed a block
100
+ # # We add our inputs at the end of the returned string
101
+ # #
102
+ # if block_given?
103
+ #
104
+ # # Okay, here's the strategy. We create a 'file' variable which calls all
105
+ # # necessary methods. Then, we tell Rails to evaluate all this while binding
106
+ # # the correct Ruby context to the new block.
107
+ # # Thanks a million to Guy Nador at http://devblog.famundo.com/articles/2007/03/28/lost-in-binding-adventures-in-ruby-metaprogramming
108
+ # # for this hack.
109
+ #
110
+ # @res = <<-EOF
111
+ #
112
+ # #{form_tag(url_for(:action => 'index'), options[:html])}
113
+ #
114
+ #
115
+ # #{capture(&block)}
116
+ #
117
+ #
118
+ # #{tag('input', {:type => :hidden, :name => WebFlow::Base.flow_execution_key_id, :value => @flow_id})}
119
+ #
120
+ # #{end_form_tag}
121
+ #
122
+ # EOF
123
+ #
124
+ #
125
+ # # Finally, launch execution.
126
+ # eval '_erbout.concat @res', block
127
+ #
128
+ #
129
+ # else
130
+ #
131
+ # # Looks like the user didn't pass a block, it's more simple like that.
132
+ # # We just concatenate our stuff at the end of the form_tag call
133
+ # result = form_tag(url_for(:action => 'index'), options[:html])
134
+ #
135
+ # # Add the flow key input
136
+ # result << tag('input', {:type => :hidden, :name => WebFlow::Base.flow_execution_key_id, :value => @flow_id})
137
+ #
138
+ # # Add the event input
139
+ # #result << tag( 'input', { :type => :hidden, :name => WebFlow::Base.event_input_name, :id => WebFlow::Base.event_input_name, :value => '' } )
140
+ #
141
+ # return result
142
+ #
143
+ # end
144
+ #
145
+ #
146
+ #end
147
+
148
+
149
+ # Allows the WebFlow framework to use AJAX form submission.
150
+ # Takes all the same parameters as the standard Rails form_remote_tag
151
+ # but alters the options hash to force the 'index' action to be called.
152
+ #def flow_form_remote_tag(options = {}, &block)
153
+ #
154
+ # # I don't know why to do this, they do it in form_remote_tag
155
+ # # and there's no documentation nor comments available... nice going.
156
+ # options[:form] = true
157
+ #
158
+ # # Init the options hash
159
+ # options[:html] ||= {}
160
+ # options[:url] ||= {}
161
+ #
162
+ # # Alter the options to change the destination url so that it points to
163
+ # # the index action
164
+ # options[:url][:action] = :index
165
+ # options[:action] = :index
166
+ #
167
+ # # Alter the onsubmit event to create an ajax form
168
+ # options[:html][:onsubmit] =
169
+ # (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
170
+ # "#{remote_function(options)}; return false;"
171
+ #
172
+ # # Call the standard flow_form_tag to do it's job
173
+ # flow_form_tag(options, &block)
174
+ #
175
+ #end
176
+
177
+
178
+ # Helper method to generate a hidden <tt>input</tt> tag for the flow execution key.
179
+ #
180
+ # @returns <tt>input</tt> tag with type hidden
181
+ #
182
+ def flow_key_tag
183
+ hidden_field_tag WebFlow::Base.flow_execution_key_id, @flow_id
184
+ end
185
+
186
+
187
+ def flow_form_tag(url_for_options = {}, options = {}, &block)
188
+ content =
189
+ if block_given?
190
+ form_tag url_for_options, options, &block
191
+ else
192
+ form_tag url_for_options, options
193
+ end
194
+
195
+ content << hidden_field_tag(WebFlow::Base.flow_execution_key_id, @flow_id)
196
+
197
+ content
198
+ end
199
+
200
+
201
+ # Helper method to generate a button element. This is a wrapper method for the Rails button_tag method.
202
+ # It adds a data-remote attribute, if specified, to enable an UJS ajax submission.
203
+ #
204
+ # @param content_or_options
205
+ # @param options
206
+ # @param block
207
+ #
208
+ # @returns <tt>button</tt> tag
209
+ #
210
+ def flow_button_tag(content_or_options = nil, options = nil, &block)
211
+ options = content_or_options if block_given? && content_or_options.is_a?(Hash)
212
+ options ||= {}
213
+ options.stringify_keys!
214
+
215
+ if remote = options.delete("remote")
216
+ options["data-remote"] = remote
217
+ end
218
+
219
+ if event = options.delete("event")
220
+ options["name"] = WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event.to_s
221
+ options["value"] = WebFlow::Base.event_prefix + event.to_s
222
+ end
223
+
224
+ button_tag content_or_options, options, &block
225
+ end
226
+
227
+
228
+ # Helper method to generate an HTML anchor element. This method is a wrapper for the Rails link_to method.
229
+ #
230
+ # @param args options, event_name, html_options
231
+ # @param block optional block
232
+ #
233
+ # @returns <tt>a</tt> tag for submitting flow request
234
+ #
235
+ def flow_link_to(*args, &block)
236
+ if block_given?
237
+ options = args.first || {}
238
+ event_name = args.second
239
+ html_options = args.third
240
+ flow_link_to(capture(&block), event_name, options, html_options)
241
+ else
242
+ name = args[0]
243
+ event_name = args[1]
244
+ options = args[2] || {}
245
+ html_options = args[3]
246
+
247
+ html_options[:method] = 'GET'
248
+ link_to name, append_flow_params(options, event_name), html_options
249
+ end
250
+ end
251
+
252
+ # Alias for Rails standard end_form_tag
253
+ def end_flow_form_tag
254
+ end_form_tag
255
+ end
256
+
257
+ #
258
+ def get_flow_data(key)
259
+ controller.current_flow_user_data[key]
260
+ end
261
+
262
+
263
+ private
264
+
265
+ # Adds required flow params to the generated url
266
+ #
267
+ # @param options Either a Hash, containing appropriate values for creating a url_for, or a String containing a url.
268
+ # @param event_name Name of the flow event to forward the request.
269
+ #
270
+ # @returns options, which can be a Hash or String depending on the passed parameter
271
+ #
272
+ def append_flow_params(options, event_name)
273
+ case options
274
+ when Hash
275
+ options[:url][WebFlow::Base.flow_execution_key_id] = @flow_id
276
+ options[:url][WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s] = WebFlow::Base.event_prefix + event_name.to_s
277
+
278
+ when String
279
+ options << (options.index("?").nil? ? "?" : "&")
280
+ options << "#{WebFlow::Base.flow_execution_key_id}=#{@flow_id}&"
281
+ options << "#{WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s}=#{WebFlow::Base.event_prefix + event_name.to_s}"
282
+ end
283
+
284
+ options
285
+ end
286
+
287
+ # Allows the WebFlow framework to use AJAX form submission.
288
+ # Takes all the same parameters as the standard Rails form_remote_tag, but adds
289
+ # the event name and flow id to the URL to return to the WebFlow controller.
290
+ # The URL is also overridden to point to the 'index' action.
291
+ #def flow_link_to_remote(name, event, options = {}, html_options = {})
292
+ #
293
+ # # Alter the options to change the destination url so that it points to
294
+ # # the index action
295
+ # options[:url] ||= {}
296
+ # options[:url][:action] = :index
297
+ # options[:action] = :index
298
+ #
299
+ # # Add the flow key to the url
300
+ # options[:url][WebFlow::Base.flow_execution_key_id] = @flow_id
301
+ #
302
+ # # Add the event name
303
+ # options[:url][WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event.to_s] = WebFlow::Base.event_prefix + event.to_s
304
+ #
305
+ # # Call the standard ajax link creation method
306
+ # link_to_function(name, remote_function(options), html_options)
307
+ #
308
+ #end
309
+
310
+ end
311
+
312
+ end
@@ -0,0 +1,82 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+ module WebFlow
22
+
23
+ # This class is used by steps to return an event descriptor to
24
+ # the WebFlow framework.
25
+ #
26
+ # Use it as :
27
+ #
28
+ # def step_definition
29
+ #
30
+ # (...)
31
+ #
32
+ # WebFlow::Event.new(:success)
33
+ #
34
+ # end
35
+ #
36
+ # There is also a sugar method included in WebFlow::Base which simplifies
37
+ # the event returning process.
38
+ #
39
+ # def step_definition
40
+ #
41
+ # (...)
42
+ #
43
+ # event :success
44
+ #
45
+ # end
46
+ #
47
+ class Event
48
+
49
+ attr_accessor :name
50
+
51
+ # Initializes the class instance
52
+ def initialize(m_event_name)
53
+
54
+ # The name of the event returned
55
+ @name = m_event_name.to_s
56
+
57
+ end
58
+
59
+ end
60
+
61
+ # The SystemEvent class is a subclass of WebFlow::Event and is used
62
+ # internally to trigger plugins execution.
63
+ # Since the plugins are not activated yet, SystemEvents are not used.
64
+ class SystemEvent < WebFlow::Event
65
+
66
+ attr_accessor :controller, :flow_data
67
+
68
+ # Initializes the class instance
69
+ def initialize(m_event_name, m_controller, m_flow_data)
70
+
71
+ # Super controller
72
+ super m_event_name
73
+
74
+ # Set values
75
+ @controller, @flow_data = m_controller, m_flow_data
76
+
77
+ end
78
+
79
+ end
80
+
81
+
82
+ end
@@ -0,0 +1,80 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+
22
+
23
+ module WebFlow
24
+
25
+
26
+
27
+
28
+ # Superclass used to raise errors from within the WebFlow framework.
29
+ class WebFlowError < StandardError
30
+ end
31
+
32
+
33
+
34
+ # Superclass used to raise errors from within the WebFlow framework
35
+ # when no flow corresponding to a given key can be found.
36
+ class NoSuchFlowError < WebFlowError
37
+ end
38
+
39
+
40
+
41
+ # This error class allows plugins to interrupt a flow execution and substitute
42
+ # it's execution result by a given Proc object.
43
+ #
44
+ # Example...
45
+ #
46
+ # my_block = proc { render 'test' }
47
+ # raise( PluginInterruptionError.new( my_block ), "Plugin Interruption..." )
48
+ #
49
+ # In this example, the flow execution chain would be halted and the block
50
+ # passed as a contructor argument would be executed. The Proc code will
51
+ # be executed on the current controller object instance via Ruby's
52
+ # instance_eval mechanism.
53
+ #
54
+ class PluginInterruptionError < WebFlowError
55
+
56
+ # Constructor used to create this error type.
57
+ # Pass a Proc object to be executed upon the rescue
58
+ # of a PluginInterruptionError exception.
59
+ def initialize(&block)
60
+
61
+ @_block = block
62
+
63
+ end
64
+
65
+ # Getter method to obtain the Proc object associated
66
+ # to this PluginInterruptionError instance.
67
+ def block
68
+ @_block
69
+ end
70
+
71
+ private
72
+
73
+ # Declaration of a private constructor to prevent initialization
74
+ # without the block parameter
75
+ def initialize
76
+ end
77
+
78
+ end
79
+
80
+ end