Trigger Rule with Filefield 'when field has changed' in Drupal 7 - drupal-7

I've got a set of different rules that check if various field types have been updated 'after updating existing content'. The problem is that each one works fine, except for the only filefield type which will not work. The condition used is a 'NOT Data comparison' on the field checking the 'node-unchanged' version against the new 'node' version. This works with every other type of field and actions appropriately (that I have used at least), just not the filefield type; the rule just fires regardless of changes or not on the filefield.
I also found this post about a very similar problem: https://www.drupal.org/node/1011014#comment-10040082
I think I have the makings of a workaround, but I just wanted to check this with some fellow developers first as my PHP isn't the best.
If I were to enable the PHP module then add a condition in rules that checks the 'source' attribute to see if a new file has been added... would this work? The code I have is:
if (isset($object->field_FILEFIELD_NAME[0]['source'])) { //Check for new files }
I believe that $object is the node passed on by rule function as argument.
Is this a good idea/best approach? Any ideas or workarounds would be great.

Yes, you can use PHP for filefield checks as it is more clear (but always less secure). Here are my suggestions:
Create a Rule component (of type "Condition set (AND)") instead of a rule to do this check.
Use a parameter with your rule component (of type Node) so you have the $node available.
Use php to do the checks. Get the file data from the filefield using $node.
Create a normal rule (eg with event Before Saving Content) where you will use this component as a condition among others.
As you said you need to check for differences not for empty values, right? So instead of using isset you need to see if there is a different fid (which normally changes when there is a different file). Other methods are available and if you want to see which data can change do a dpm() to the filefield using devel module.
In order to get the unchanged value of the filefield use the same component on you main Rule but with the $unchanged node as parameter.

Related

Grails 3 "show" view with Fields plugin 2.1.0-SNAPSHOT

Stuck at a trivial problem in Grails 3.1.5: Show the fields of a domain object, excluding one of them, including a transient property. Yes, this is my first Grails 3 project after many years with previous versions.
The generated show.gsp contains
<f:display bean="rfaPdffile"/>
This will include a field that may contain megabytes of XML. It should never be shown interactively. The display: false constraint is no longer in the docs, and seems to be silenty ignored.
Next I tried explicitly naming the fields:
<f:with bean="rfaPdffile">
<f:display property='fileName'/>
<f:display property='pageCount'/>
...
</f:with>
This version suprisingly displays the values without any markup whatsoever. Changing display to field,
<f:with bean="rfaPdffile">
<f:field property='fileName'/>
<f:field property='pageCount'/>
...
</f:with>
sort of works, but shows editable values. So does f:all.
In addition I tried adding other attributes to f:display: properties (like in f:table), except (like in f:all). I note in passing that those two attributes have different syntax for similar purposes.
In the Field plugin docs my use case is explicitly mentioned as a design goal. I must have missed something obvious.
My aim is to quickly throw together a prototype gui, postponing the details until later. Clues are greatly appreciated
If I understood you correctly, you want to have all bean properties included in the gsp but the one with the "megabytes of XML" should not be displayed to the user?
If that is the case you can do:
f:with bean="beanName"
f:field property="firstPropertyName"
f:field property="secondPropertyName"
And the one you don't wish to display:
g:hiddenField name="propertyName" value="${beanName.propertyName?}"
f:with
So list all the properties as f:field or f:display and put the one you don't wish to display in a g:hiddenField Grails tag
You can also try:
f:field property="propertyName"
widget-hidden="true"
but the Label is not hidden in this case.
Hope it helps
My own answer: "use the force, read the source". The f:display tag has two rather obvious bugs. I will submit a pull request as soon as I can.
Bugs aside, the documentation does not mention that the plugin may pick up the "scaffold" static property from the domain, if it has one. Its value should be a map. Its "exclude" key may define a list of property names (List of String) to be excluded. This probably works already for the "f:all" tag; bug correction is needed for the "f:display" tag.
My subjective impression is that the fields plugin is in a tight spot. It is intertwined with the Grails architecture, making it sensitive to changes in Grails internals. It is also required by the standard scaffolding plugin, making it very visible. Thus it needs constant attention from maintainers, a position not to be envied. Even now conventions for default constraints seem to have changed somewhere between Grails 3.0.9 and 3.1.7.
Performance of the fields plugin is sensitive to the total number of plugins in the app where it is used. It searches all plugins dynamically for templates.
For the wish list I would prefer stricter tag naming. The main tags should be verbs. There are two main actions, show and edit. For each action there are two main variants, single bean or multiple beans.
My answer is that at present (2 March 2017) there is no answer. I have searched the Net high and low. For the index (list) and create and edit views, the fields plugin works well enough. A certain field can be easily excluded from the create and edit views, relatively easily from the list view (by listing those that should show), and in no way I could find from the show view. This is such a common need that one would suspect it will be addressed soon. Also, easily showing derived values in the show view, like 'total' for an invoice. One can do that by adding an ordered list with a list item showing the value below the generated ordered list of values, but that is kind of a hack.
In some ways, the old way was easier. Yes, it generated long views, but they were generated and didn't have to be done by the programmer - just custom touches here and there.

getting the field values of content types from drupal

Here I want to know how to get the field values of my custom content type 'mypop'. I tried all methods in google but I don't know how to use, for example i tried function node_load, I can't able to know where to write this function, what are the parameters and tried EntityFieldQuery too. Can I know the how to do it in brief explaination.
Thanks in Advance.
Definitely a very broad question. Assuming you have the content type 'mypop' created already, think the easiest steps for you would be to:
Make sure you create some content of that content type
Customize the "Manage Display" on that content type and make sure the fields you want are set to visible there
Once you do this, those fields should be visible when you view the nodes of that content type already. If you want to further customize the view, you should probably customize the template file for that specific content type (there's other options but trying to keep this as simple as possible).
To do this, copy the "node.tpl.php" file you'll find on the modules/node folder to your theme templates folder and change it's name to be "node--mypop.tpl.php".
That way, you'll override Drupal's default display template for that specific content type only. Now you can basically tweak it into anyway you want.
Hope this helps!
Thanks a lot Alberto. Its working now! I have another issue too, it also got cleared and now its working fine !Another issue is javascript called automatically when I open views edit for other contents. Now by doing overriding this template file, it also gets cleared. Thank you !
node_load take node id. So in order to use noad_load() function, you should first retrieve node ids. Better if you use noad_load_multiple().
// Query all of the nids of a particular content type.
$nids = db_select('node', 'n')
->fields('n', array('nid'))
->condition('type', 'Article', '=')
->execute()
->fetchCol();
// Get all of the article nodes.
$nodes = node_load_multiple($nids);
You can see the result by calling print_r($nodes). Just write a normal function in you .module file or .inc file. Call it anywhere, your choice. say, in menu callback.

Usually the form is POST, but in a single instance it is GET

I do a standard pattern in my application - a link to /controller/delete/object_id, then a post form to "confirm", a check if $this->request->is('post') and if true - the controller deletes the object from database.
What is weird is that for a single, particular object_id, my browser (Firefox) forces the form to be a GET one. With any other object_id everything is ok, but with this particular one, despite all declarations within form tag and etc. brower generates a GET request.
Do you have any clue what this might be?! I even tried to use brower's private mode, because I thought it can be some garbage in browser cache, but the bug is still here.
I managed to bypass this problem:
define a specific action in form->create, pointing to your controller' method
add a hidden field with object_id
add some additional code in the controller method to get object_id from $this->request->data, because a hidden post field is not passed as an argument to method, as it is with GET method.
This way, to some unknown reason, it just works. Anyway, I still feel I'm doing something wrong. It's not as "clean" as I would expect.

How does features manage content type field changes?

I'm having fun with a change to a content type field (from a node reference to a text field) which results in an error when a recreated feature is merged. The error is
FieldException: Cannot change an existing field's type. in field_update_field() (line 234 of /var/www/htdocs/modulesfieldfield.crud.inc)
At the moment, this is only affecting a merge back into a developer's workspace and the staging environment is a clean build from GIT, so unaffected. But it raises an early flag in terms of defining an update process when it goes to production.
When in production, I assume that it will be a matter of managing an export of each instance of that content type, remove the content type, install the recreated feature, migrate the exported data into the refactored content type and then apply any tests that may be defined for that change.
What is the recommended best practice process, i.e. the standard to follow to get it right at the outset?
Many thanks in advance
Best way is to tag your feature with a version.
First version: your old field and it's data
Second version: your old field definition and the new one.
In this version you can migrate the data contained in the old field within a hook_update_N().
Third version: simply remove old field definition
I hope to have answered your question as you expected

CakePHP RequestHandler: setContent/renderAs/respondAs .. what?

Can someone please explain these functions:
RequestHandlerComponent::renderAs()
RequestHandlerComponent::respondAs()
RequestHandlerComponent::setContent()
It feels slightly redundant to have all three of them (as public methods anyway). If I want to respond to a request with a PDF file, does that mean I'd have to call all three functions? How should I use these in my controller?
They're all different. From the API Docs:
renderAs
Sets the layout and template paths for the content type defined by $type.
I.e. more or less a shortcut for $this->layout = '...' and $this->render(...).
respondAs
Sets the response header based on type map index name. If DEBUG is greater than 2, the header is not set.
Outputs header(...).
setContent
Adds/sets the Content-type(s) for the given name. This method allows content-types to be mapped to friendly aliases (or extensions), which allows RequestHandler to automatically respond to requests of that type in the startup method.
Doesn't actually do anything to the output, just allows you to add new types that are not defined by default.
For outputting a PDF (assuming you have it as a file already) you should actually use a Media View.

Resources