Hi Jesse,
sorry, I was really busy an not able to answer or even look at your
mails the last days.
The second mail was much better than the first one. :-) I think you got
it. Here are some notes/conclusions regarding both of your mails (I
guess, you got most of them):
Of course the workflow definition is not defined or even expanded in the
several actions (as you wrote in the first mail). Mostly you define it
once (via XML or PHP) and then save it to the database. It's important
to understand the difference between workflow (definition) and workflow
execution - similar to the difference of classes and objects in
object-oriented programming: first you define your workflow and then
you create/access instances (=executions) of that definition.
Also it's important to note that the workflow execution suspends itself
if the workflow can not continue any more (and is not ended). This
could happen in two cases: there is an input node waiting for some
input variables or a service object where the execute() method
returns "false". In both cases the workflow is suspended. The execution
id is the main thing to find and resume() the workflow execution
later - this needs to be saved in what you call "workpool".
I also want to mention that there is a concept called "variable
handler". The difference to execution variables: if the workflow is
resumed (resp. suspended) the variable is loaded (resp. stored) via the
variable handler's logic. The advantage: if the variable (in your case
the article object) is updated in between, it is always the actual
version, you refer to in the workflow. (Also, you do not duplicate the
article's data.) Another possibility not to duplicate the article could
be, to have the article object only in the workflow execution but not
in the "normal" database. Thus the database is only filled with the
object if it is approved an published. But this depends on your
scenario (and in the latter case you can access the article only via
the workflow execution that stores it).
See some few notes below...
Am Dienstag, 2. Oktober 2007 schrieb Jesse Sanford:
> Thomas, After sending that last email I just realized a few things.
>
> First of all lets say that I have the workflow described in that last
> email
> programmatically all defined within an xml file or saved in the
> database tiein.
>
> Let's also say I removed the first input node. Since it wasn't really
> needed
> there is no reason to have it there. If we are creating a new article
> we can
> assume the content has already been created for it.
>
> Now the first node after the start Node should be the input node that
> waits
> for an editors approval (former $input2 node from my last email)
>
> So let's begin again...
>
> I create a new article object and hydrate it with the users input.
> Then I
> would simply load a new copy of that workflow a storage object.
>
> New($articleBody) {
>
> /* instantiate new article object */
>
> $article = new article($articleBody);
>
> /* load workflow from database and instantiate workflow variable */
>
> $db = ezcDBFactory::create( 'mysql://[EMAIL PROTECTED]/test' );
>
> $definition = new ezcWorkflowDatabaseDefinitionStorage( $db );
> $workflow = $definition->loadByName( ' articlePublishing' );
>
> /* Then I would start the workflow */
>
> $execution = new ezcWorkflowDatabaseExecution( $db );
>
> $execution->workflow - $workflow;
Perhaps you want to do something like:
$execution->setVariable( 'article', $article );
> $id = $execution->start();
or (if the first input node waits for the article):
$execution->start();
$execution->resume( array( 'article', $article ) );
> $article->workflowId = $id;
> $article->state = "waiting for approval";
> }
One thing, that seems to be not that nice: you store the execution id in
the article ($article->workflowId). That's not that nice from an
object-oriented view as it is not part of the article object. Without
any good reason it seems to be better if this is stored only in
the "workpool".
> Then I would end the new() article action.
Don't forget to store the execution id in the workpool. :-)
> So the execution would
> presumably
> start then hit the first input node and then wait. I would need to
> store this input $id and a description of this workflow somewhere so
> that the editor could review it correct? Lets just say I store it in
> the new article
> object.
Yes and No. As written above: store the id in the workpool and not in
the article. First this data is not part of the entity "article". Then:
it's much easier to find the pending workflows for a user via a
workpool if there are several objects (not only articles but perhaps
also forum posts or blog comments, ...). If needed just store some
metadata in the workpool (e.g. the workflow cares about an article or
whatever). (Of course there may be a situation where it should be
appropriate to store the execution id in the article - but I can't
imagine at the moment for your situation.)
> So the editor logs in. I querry my workpool table and find all the
> $ids for
> workflows that are now waiting for approval.
>
> I pick up that article attached to that $id and show the view for the
> approval screen.
>
> The editor pushes the approve button.
>
> The controller for the article object then fires it's approved action
>
> The approved action resumes the workflow with the "approval variable
> set to
> true (reference the last email for the approval conditional nodes and
> variables)
>
> Approved($article) {
>
> $article->approved = true;
>
> $db = ezcDBFactory::create( 'mysql://[EMAIL PROTECTED]/test' );
> $execution = new ezcWorkflowDatabaseExecution( $db,
> $article->workflowId );
> $execution->resume( array('approval' => true ) );
>
> $article->state = "approved waiting for publish";
>
> }
I do not really get, why you save the state information in two places:
$article->approved and $article->state. Probably this is redundant
information... (The same to $article->published below.)
> Then the workflow executes the $approvedNode branch and (any service
> objects
> attached to it correct?) and comes to a stop when it reaches the
> input node
> for publishing (former $input3 in last email)
>
> So now I close the approved action.
>
> Then the editor decides to publish this article so he goes into the
> view for
> the publish screen and clicks the publish button for this article.
>
> The published action on the article fires
>
> Published($article) {
>
> $article->published = true;
>
> $db = ezcDBFactory::create( 'mysql://[EMAIL PROTECTED]/test' );
> $execution = new ezcWorkflowDatabaseExecution( $db,
> $article->workflowId );
> $execution->resume( array('published' => true ) );
>
> $article->state = "published";
>
> }
>
> The workflow execution continues. The $publishedNode branch executes
> (any
> service objects attached to the $publishNode fire) and then the
> workflow moves on to the $merge (see last email) and then goes on to
> the end node thus finishing the workflow (correct?) does the workflow
> finish even though
> only one of the paths had been executed preceding the merge? Does it
> wait
> for anything else before the merge fires it's outNode?
Regarding end nodes: in general, if an end node is reached, the workflow
is ended - even if there is a branch that is not finished. This is
because of the implicit ending of the workflow execution if an end node
is reached.
If I understood you correctly, you have a merge node just before the end
node. It depends on the merge node, if this activates its out node (the
end node) e.g. when the first branch comes in or when all branches
reached the merge node. So it's not the end node that's important here
but the type of the merging node.
Hope that answered your questions. If not - just ask...
Have a nice day
Thomas
> Thanks again for all your help,
> Jesse
>
> On 9/26/07 9:18 AM, "Thomas Nunninger" <[EMAIL PROTECTED]> wrote:
> > One general note (as this is not the first request regarding
> > workflows to my personal email):
> >
> > Regarding questions about the workflow components (or others),
> > allways write to the eZ Components list. That way you ensure that
> > other people can profit or answer as well. I will allways post to
> > the list as well when answering such mails (unless you convince me,
> > why it's better to keep it private).
> >
> >
> > Hi Jesse,
> >
> >> Hi Thomas, I am sorry to bother you today but I am really
> >> interested in using the ezWorkflow component in a project I am
> >> working on but I am having trouble grasping how to incorporate it
> >> into the MVC architecture. Let's say for instance I have created
> >> CRUD screens for content entry. Lets also say that I have some
> >> semblance of a user acl. Now one workflow I have modeled involves
> >> a writer creating a story and then submitting it to an editor for
> >> review before the editor publishes the story. I know we can model
> >> this with a petri-net or a directed graph very easily. I also
> >> assume this can be created within the ezWorkflow component. My
> >> question is how do I get this to actually influence the
> >> Controllers and Views of the model as it gets written then
> >> approved then published.
> >
> > In general you allways need to take care about the execution ids
> > and which user it belongs to. It could be stored in the session or
>
> database
>
> > or provided via a parameter within the request.
> >
> > Sometimes it could be stored within the relevant data of the
> > covered objects. But if you have a more complex situation, I
> > suggest to use a separate table. Such a table could basically
> > contain a column for user (group), execution id and perhaps some
> > additional information if
>
> needed
>
> > (e.g. action).
> >
> > When a user sends an article for publishing, you insert an entry in
>
> the
>
> > table for the next user (group), the execution id and perhaps the
> > additional information. (What the next user group is, could be
> > defined in a special execution variable and read generally from the
> > workflow execution object.).
> >
> > When the editor looks into his account, you could query the table
> > and present him a list with all pending workflows that needs his
> > interaction. He could select one execution and provide the needed
>
> input
>
> > data to trigger the workflow to the next step. (If the workflow is
> > not finished, you could create a new entry in the table.)
> >
> > It could be pretty handy if you create your own
> > application-specific WorkflowUtils class providing easy handling of
> > starting/triggering workflows or fetching a list of all workflows
> > that need input from a special user. Then you can reuse this
> > functionality in several places of your application.
> >
> > Hope this answered your question. If not: just ask...
> >
> > Have a nice day
> >
> > Thomas
> >
> >> Thanks in advance. Your help is greatly appreciated!
> >>
> >> Jesse Sanford
--
Components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/components