Plone 4 smarter generic setup updates needed - plone

The core of the problem, is that GenericSetup profiles are additive. Sometimes products can't be upgraded by simply applying profiles and the whole chain of profiles needs to be applied in a certain order.
For example, say we have a lot of independent site policies (only one of them applied
to the plone instance): S1, S2, ...., SN. And a couple of products, say A and B. For example, all those S1-SN, A, and B have metadata dependencies go like this: Sn -> A -> B
Suppose they deal with registry.xml and override something along the way. (The same can be the case from typeinfo and some other profile steps). If something changes in the product A, which may or may not be overriden in S1, we can't just perform an upgrade step for A, because when we press the button on the S1 site, its own policy overrides will be lost. However, it's a big deal to write upgrade steps for all of S1-SN just because a change in the A.
Is there any smart way to do upgrades at least for the case depicted above, when the whole problem would be solved by applying registry update in certain order, namely: B, A, Sn. (even then, there could be some hard cases)?
Since the package A has no idea of S1 (or S2 or whatever site policy happens to be), one solution is to make some "superpackage" which could have explicit knowledge about those chains of upgrades. But are there other solutions apart from always putting the resulting profile to the policy?
(For simplicity, lets forget that some changes could be done through the web)

This is actually already in GS, albeit it is not something all products use unfortunately.
The solution lies in using GS's upgradeStep.
Say you change the profile's metadata from version 1 to 2. In your zcml you register an upgrade step like this:
<genericsetup:upgradeStep
title="Upgrade myproduct from revision 1 to 2"
description=""
source="1"
destination="2"
handler="myproduct.one_to_two.upgrade"
sortkey="1"
profile="myproduct:default"
/>
In one_to_two.py you would then have
def upgrade(context):
registry = getUtility(IRegistry)
if 'foo' in registry:
do_stuff()
Inside there you can also rerun specific import steps, for instance:
context.runImportStepFromProfile('profile-myproduct:default','actions')
When the product is upgraded, only what is specified in the upgrade step handler will be applied, which is exactly what you need.
Documentation on all that here.

Decided to go with custom solution, with helper functions to make common upgrade task easier. Doesn't solve all the problems, but helps deployment.

Related

How to use Drupal rules to adapt content access permissions for nodes that are older than 1 week?

I have a special content type named "example". I want to show new nodes of this type to anonymous users of my site.
What I need: after 1 week the node was created, content access permissions (Content Access module is installed) are changed that only users with particular role are able to see this node.
Should this be triggered on cron or what? Or just how to do something to nodes that are older than 1 week?
Could you provide some instructions on how to do that? Because I'm new to the Rules module and have no any ideas.
You should be able to do this with Rules (see this question, not exactly what you want but close), but I'd go for a tiny custom module implementing hook_cron, where you fetch all nodes with creation date < (now - 1 week), and modify the permissions for each of them.
It should be more efficient than the Rule approach explained in my first link, where you need to loop over all nodes on each cron execution. And Rules can be quite more annoying than writing plain PHP. I prefer learning Drupal API than spending hours clicking in Rules interface (Rules is great, but it's hard).
Good luck
Yes you should be able to get this to work using the Rules module to implement what you're looking for, but I recommend you to also combine that with the Rules Once per Day and the Views Rules modules, as further explained below.
Step 1: Rules Event
Your question doesn't really specify anything that could/should be used as the Rules Event (for the rule to be triggered. And even though it's like "up to your own imagination" (any Rules Event will do), something that will work for sure is to use the Rules Once per Day module. Here is how it works (as per the comment in issue 2495775, from the module owner):
You specify a trigger hour on the administration settings page for this module.
The Rule trigger will then run when cron tasks are first run after the start of that hour. The actual run time will depend on your cron task timings.
So this is another way to understand/read this:
The "Event" will only be triggered when a cron job is run.
And that event will only be triggered 1 time / day, i.e. "next time cron runs after the trigger hour has passed".
Step 2: Rules Actions (and optional events)
Some details about the Views Rules module (from its project page):
Provides Views directly as Rules actions and loops to seamlessly use view result data.
The previous quote may seem a bit cryptic (it may make you think like "so what, how can this help me?"). Therefor some more details about how to move forward using these modules:
Create a view (using Views) so that you have 1 Views result (row) with all the nodes (of at least 1 week old) you want to be processed, whereas that view has fields (columns) for whatever is needed in subsequent steps, eg the node ID, but possibly other fields as well. You'll need these View fields later on as values to be processed by your rule, "to change the content access permissions (using the content_access module) so that only users with particular role are able to see such nodes" (similar to what you mentioned in your question). Important: use a Views display type of "Rules".
Create a custom rule in which you use the Views Rules module to iterate over each of these Views results in a Rules action, using the Rules technique known as a "Rules Loop".
For each iteration step in your Rules loop, perform a Rules Action to "do your thing" (= change the content access permissions). At that point you'll have all data from each column of your Views results available as so called Rules Parameters. So at that point it's a piece of cake to adapt the content access permissions for the node you're processing in that loop.
Optionally, you may also want to add whatever extra Rules Condition(s), also up to your own imagination.
Easy, no?

Tuleap OpenALM artifact part of multiple hierarchies

As I am new to Tuleap OpenALM I am trying to figure out how to make an artifact be part of multiple hierarchies. Effectively I have created a tracker to hold business use cases and another one in a hierarchy under it to hold variants of these use cases. Epics, User Stories, and Tasks are in this hierarchy under this variant. (Business Use Case \ Variant \ Epics \ User Stories \ Tasks) Additionally I have created a hierarchy holding Releases and Sprints (Releases \ Sprints). When performing sprint planning the Epics and User Stories do now show up under the release for selection. Is it possible to configure the Epics and User Stories to be under both hierarchies? Does anyone have any other potential solutions? Effectively I am attempting to link or tag the Epics and User Stories with an attribute of Business Use Case and corresponding Variant, and be able to have the use cases and variants in an easy to manage location. Furthermore I want to be able to generate reporting based on completion of stories under each of the use cases and variants. Any advice is much appreciated in advance.
It is not possible for an artifact to be under multiple hierarchies at the moment.But be careful, there is a difference between what we call hierarchy and what you're doing during a sprint planning or a release planning inside the AgileDashboard plugin:
On the AgileDashboard plugin you're not adding User stories under the Releases or Sprints, you're just linking them together.
In the Tracker Administration you can define Hierarchy and then when you link (using an ArtifactLink field) an Artifact A (in tracker A) that is under an Artifact B (in tracker B) following the hierarchy you defined, Artifact A will be visible in the Artifact B children and Artifact B will be visible as Artifact A parent.
So, If I understand correctly your use case (which might not be the case), just link User stories and Epics with the corresponding Business cases/Variant and if your hierarchy is correctly defined you should find them in the children/parent definitions. For the Release/Sprint planning part, continue to do so using the AgileDashboard plugin.
Please let me know if I answered correctly your question.

Using SpecFlow for End-to-End Regression Testing

We are employing BDD and using SpecFlow to drive our development (ATDD).
Our QA team would like to define their own 'end-to-end regression tests (in Gherkin/SpecFlow) and re-use the Steps we have already defined.
(Please note - I know that this is not a great example but it should provide enough details)
A test may include..
Log in
Search for a product
Select a product to buy
Create an order
Select delivery option.
Submit the order.
Cancel the order.
This would suggests a scenario like..
Given I am logged in
When I Search for a product
And I Select a product to buy
And I Create an order
And I Select delivery option
And I Submit the order
And I Cancel the order
Then ??!!
Which is clearly wrong as we are not checking the output at each step.
So this may be resolved as a sequence of scenarios:
Scenario 1:
Given I am logged in
When I Search for a product
Then I see a list of products
Scenario 2:
When I select a product to buy
Then I can create an order
Scenario 3:
When I create the order
And I Select delivery option
Then I can submit the order
etc etc
The main issue with this is that there seems no way to specify the order/sequence that the scenarios are run in (a characteristic of nUnit?). Because there are dependencies between scenarios (they are not set to a know starting point) they must be run in sequence.
My questions are:
a) Are we trying to fit a square peg in a round hole?!
b) Does anyone know if there is a way to use SpecFlow/Gherkin in this way?
c) Or does anyone know what alternatives there are?
Many thanks!
I would say that you are writing your scenarios on the wrong abstraction level. But that depends on what you want to use them for;
If you want to write test-scripts then you are on the right track... but it will be a nightmare to maintain as it, in the first case (long script) will be very brittle and the second case (several scenarios) need to ensure a certain execution order. Both of them are discouraged and considered anti-patterns.
I would suggest that you merge the ATDD-tests you are writing and talk to the test department to get their view on the matter and include the test-cases they need to ensure that the system is thoroughly tested. Who know? You might even learn something from each other :P
And when you write those "specifications" (as I rather call them) you write them on a higher level. So instead of writing:
Given I am logged in
When I Search for a product
And I Select a product to buy
And I Create an order
And I Select delivery option
And I Submit the order
you write something like
When I submit an order for product 'Canned beans'
In the step-definitions behind that step you perform all that automation (login, browsing to the product page, select the delivery options, submit the order).
All of this can be read about in these great articles on how to write maintainable UI Automation tests:
http://gojko.net/2010/04/13/how-to-implement-ui-testing-without-shooting-yourself-in-the-foot-2/
http://elabs.se/blog/15-you-re-cuking-it-wrong
http://www.marcusoft.net/2011/04/clean-up-your-stepsuse-page-objects-in.html
http://dhemery.com/pdf/writing_maintainable_automated_acceptance_tests.pdf
http://gojko.net/2010/01/05/bdd-in-net-with-cucumber-part-3-scenario-outlines-and-tabular-templates/
http://chrismdp.github.com/2011/09/layers-of-abstraction-writing-great-cucumber-code/
http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
http://mislav.uniqpath.com/2010/09/cuking-it-right/
I hope this helps

Circular Sorting in Drupal 6, CCK & Views

I had an interesting request from a client today and I'm not exactly sure the best way to solve it using Drupal Views. They currently have a "Team Member" content type that represents members of their staff. Each staff member page has a link to all other staff member pages. So far that's not a problem.
They want this list to start with the person we're presently looking at and then proceed with who falls right after them in the "sorted" order. Then when it reaches the end of the list it wraps around and starts back at the beginning until they get back to themselves (similar to how a Circular Linked List would work).
So for example, assume I have Team Members A,B,C,D,E,F and G:
If I'm looking at Team Member A, the list order is: A, B, C, D, E, F,
G.
If I'm looking at Team Member D, the list order is: D, E, F, G, A, B,
C.
If I'm looking at Team Member G, the list order is: G, A, B, C, D, E,
F.
If I was dealing with some other data structure in a regular programming environment, I'm sure I could come up with some sort of algorithm to determine where we presently at and begin sorting from there and fake a "circular list". Views seems a little more tricky.
The only potential solution I can think of would be to create two separate views and then just join the results together after the fact.
One view would be a sorted list of all team members that have a sort number greater than or equal to the present team member.
A second view that is a sorted list of all team members that have a sort number less than or equal to the present team member.
I'm just curious if there are any more efficient ways of doing this kind of a sort with views?
As long as all your results can be contained on one page, you're probably best off with the solution you mention: manipulating two views (probably in the template, as Oswald suggests) so one is displayed after the other. However, if you do end up having lots of results, and needing paging ... you will probably need to do some fancy work in calculating the difference between sort numbers, and using this value in ORDER BY ... all that requiring the difficult task of rewriting the main Views query.
I tried this a few years ago and had enormous difficulties ... Merlin of Chaos, the main Views developer, simply stated somewhere that Views really wasn't meant to be for fancy programming, and that the way it handled queries wouldn't allow for much manipulation ... things would break. However, something has changed in the meantime ... I remember seeing a new function in Views which seemed to be made for the purpose of rewriting the main query.
Here is a tutorial on rewriting a views query: http://blog.raisedeyebrow.com/2010/04/rewrite-a-views-query/
Do note: due to the many things that are going on in Views, you should create a lot of dummy entries to make sure nothing is broken - if you re-write the query, it will be much more susceptible to error.
Actually, if you are acquainted with Drupal module building, for something like this it might just make more sense to build a custom module that allows you more control over the query and the display. This might actually be faster than a lot of experimentation and testing.
My choice would be the theming layer. I guess this can be done in a preprocess function. Maybe you have to override a template file. The Theme Developer module can tell you how the view is rendered and which overrides are possible.

Drupal: Upgrade Node strategy

I effectively want two nodes:
Normal Node
Premium Node
The only difference will be that the premium node can take more images and a few other features. What is the best strategy to go about this?
have two distinct nodes with the differences
have one nodes and somehow find a to apply an UPGRADED attribute to it?
I would prefer (b), as I want users to be able to upgrade nodes. And migrating a normal node to a premium node will be very difficult.
Any idea how I can accomplish b?
I would create two different content types (CCK), and either write custom code to translate between the two or use a module like Node Convert (in order to upgrade a node); it might be complicated at first, but you would have the advantage of being able to apply all of your restrictions (allowed image count, permissions etc) on a per-content type basis.
Here is an excerpt from the Node Convert project page:
... adds a menu tab "Convert" on the node view page, i.e. node/1/convert, which gives the ability to convert the node from its current node type to another node type. The module provides the means to transfer all the field values of the current node type into fields on the destination node type, or discard them.
The module integrates with Actions, Rules, Views Bulk Operations and Admin Views nicely. It has support for exporting templates into Features using CTools Exportables. It also provides a hook that enables developers to execute additional code on conversion.
You might be able to implement (b) as two different input filters - one for non-upgraded and one for upgraded. Then "upgrading" the node would be as simple as changing the input filter applied to its contents.

Resources