What is the hook to use to set an expiry time on a nodes cache.? - drupal

I would like to cache a node individually based on the published date of the node. Older nodes could be cached longer than newer nodes. I thought I could cache using cache_set individually but realized that nodes are cached by default and so it could be better to set an expiry time on the cache. Any thoughts on how to do this? A hook perhaps?

Drupal does not have a node cache per se. If you have the page cache turned on for anonymous users, the cahced data for nodes is likely spread across three tables:
cache_content
This table caches the values of fields that are not passed through an input filter such as file_fields or text areas with "Plain Text" selected.
cache_filter
This table caches the filtered values of Rich Text fields such as Body or a CCK text area with "Rich Text" selected.
cache_page
This table caches the entire redered page output as seen by anonymous visitors
I don't know of a way to dictate exactly when these cache rows expire, so you would have create a function
If you want to clear all caches for specific nodes based on custom rules, you could use a cache_clear_all function within HOOK_cron to accomplish that. You would first need to determine which nodes meet your criteria for cache deletion, then you could use cache_clear_all with a 'cid' wildcard parameter. Something like (this would go inside a HOOK_cron function in your custom module and requires that a proper cron job is set up):
<?php
$wildcard = //Your criteria for the cache_content table;
cache_clear_all($wildcard, 'cache_content', TRUE);
$wildcard = //Your criteria for the cache_filter table;
cache_clear_all($wildcard, 'cache_filter', TRUE);
$wildcard = //Your criteria for the cache_page table;
cache_clear_all($wildcard, 'cache_page', TRUE);
I think the main point here is that it's quite difficult to override Drupal's build-in cache expiries.

You might try hook_flush_caches() but I'm not entirely sure if that's what your looking for or not... Just a thought.
Another possible avenue would be drupal_page_cache_header().
HTH. :)

Related

Manually set the current item in a form

What is the code to manually switch a form to a specific record? I was trying to use relations but I can't make a relation to a calculated table, which is where this is coming from, so I have to hardcode which data is populated.
I'm looking for something like
onLoad()
(read the ID from page properties, which I use for globals)
widget.item.select(id);
I think you would want to use:
widget.datasource.selectKey(id);
This works on the assumption that your record is currently loaded in your client however. If your record is not loaded then this will not work.

Drupal views: list referenced nodes except the one used as contextual filter

i have the following case: I am building a website that has information on filmmakers and their films. I have a node type for the filmmaker, with biographical content, etc and another one for the films, with a field 'author' that references one or more of the filmmakers (since one film may have been made by several of them).
I also have a views block called 'filmography' that lists all the films whose author is the filmmaker (node) the user is seeing. Setting this up with a contextual filter was quite easy.
But now I want to present in this block along with the film name, all the filmmakers that may have made the film ('author' field in the film node) and that are different from the filmmaker being viewed. Displaying all the filmmaker nodes referenced by the author field is immediate, but I want to remove the filmmaker that I am using in the contextual filter. The goal is to get something like this:
Filmmaker 1
Movie 1
Movie 2 (with Filmmaker 2)
Movie 3
I have the notion that this might be done using views php and filtering the node references returned, but I wonder if there is an easier solution for that...
Thanks
Update: I have managed to get a result using the Views Field View module, passing the list of referenced nodes (filmmakers) as a contextual filter (node ID) and then adding another contextual filter (node ID as well) as an exclusion, and getting the default value of the letter from 'node id from URL option' (that is, from filmmaker's page the filmography view is embedded in). Keeping the question open for a while to get other, possibly more efficient, alternatives.
As I read your question, the Views Field View module popped into my mind as the obvious solution (then I saw your edit). I think this will still be your best bet. Definitely avoid using php fields as that is not a good practice in general from a security standpoint. If you are concerned about efficiency/performance, then you should just use views caching setting under the advanced options. Seems like this option is always looked over.
If you are looking for alternative options, one might be to use rendered nodes as your View style instead of fields, then use Display Suite to generate additional display modes beyond "Default" and "Teaser," create a view with the filters, then use the Entity Views Attachment (EVA) module to insert a view as a display mode field. While this is certainly a robust approach, it adds a lot of processing overhead with the rendered entities, so you definitely want to cache the results of that as well.
p.s. You might get faster/more responses over at https://drupal.stackexchange.com/

Identify Unique Browser / tab instance, e.g. User has 2 tabs open on mysite.com-identify each

I have read this and many other links the past few days.
The problem is that I need to have a unique identifier for each tab or browser that a user has open for mysite.com (example site name)
I cannot use a unique session, as when I open mysite.com and have e.g. selected "carrots" in the session, then all the other tabs/browsers for mysite.com now has "carrots" in the specific session value.
But still the server obviously identifies each browser/tab uniquely. Is there a way to get hold of this unique browser/tab ID, or to create a unique one?
I am not referring to generating a unique ID oneself via JavaScript, I saw some good examples on StackOverflow. The problem would be that I'd need to implement it on each master page and carry it around between master/non master pages. Also for e.g. In my instance it won't work as I can have the browser open and it would generate 20 different IDs if I ran it 20 times across a few pages e.g. when I cannot transfer the value across ports.
So please, not to waste everyone's time, this is not a random GUID creation question, this question relates to obtaining a unique recreatable ID (if it gets lost)for each tab/browser, preferably identifying by the link to the server.
This is a big topic you've touched on.
If you only need to persist the ID during a form submit, you can take the approach of the client-side window.name property and use the window.onload to propagate a hidden field with that value.
But this won't work when user is following hyper-links (click on a link on a site).
onload: check if window.name is set; if not set, assign a GUID. if set, set a hidden field=window.name. So, on submit, your form will have the hidden field with the window.name GUID.
You can also use the HTML5 window.sessionStorage which will solve all your troubles, but that don't work on older browsers.
If you need support backward-browser AND non-submit type, then you will need to write some pretty complex cookie/session management on the client side. Not pretty. Just hope the above 2 is sufficient.

How to add/save temporary table on form

We created special form to creating purchase prices for vendors.
New form has almost the same fields as original (so we used PriceDiscTable), but the record/datasoruce was set as temporary table. After user filled mandatory fields will click button, (extra logic behind) and record will inster to database (real priceDiscTable).
The idea was to grand access to trade prices for users that not necessarily has access to purchase prices. In theory everything was ok, but when user with no access to PriceDiscTable open new form, error was shown "Not enougt right to use table 'Price agreements'".
We try set the AllowCheck to false in formDatasource but this only allow us to open the form, but user still cannot add or modify records.
Is there any way to force system to allow user to write data in the temporary table?
Disabling security key or grand access to real table is not an option.
Duplicate table and create with same fields is nuisance (if we use same table we can use data() method to assign fields)
I think that creating a new temporary table with [almost] the same fields would be the best solution.
If the only reason you oppose to this approach is that you wouldn't be able to use data() to copy data from one table to another you can use buf2BufByName() as described here: http://mybhat.blogspot.co.uk/2012/07/dynamics-ax-buf2buf-and-buf2bufbyname.html
You can use RunAs to impersonate another user...perhaps a system user. I don't entirely follow what you are trying to do, but it sounds like this solution would work for you if you know exactly what your custom code is doing and is capable of.
See Classes\AifOutboundProcessingService\runAsWrapper to see an example.
You will not be able to display the PriceDiscTable without giving the user at least "view" access or editing Classes\FormRun to somehow bypass the security key, which is kernel level so it's also not possible.
I agree with 10p where you should create a temp table and then create a custom method handler combined with buf2bufbyname() or buf2buf().
Another option you can screw around with, if you REALLY want to use .data() is using a Common as the datasource. You could add the fields you want on the grid with the common, then you can pass a common back/forth. This has a good amount of form setup to get this working, but it could produce what you want eventually I think.
static void Job8(Args _args)
{
Common common;
salesTable salesTable;
;
common = new DictTable(366).makeRecord();
select firstonly common where common.RecId == 5637145357;
salesTable.data(common);
info(strfmt("%1 - %2", salesTable.SalesId, salesTable.SalesName));
}

Drupal - Rules Condition that node has been updated more than once?

Is it possible to have a Rules Condition that a node has been updated more than once?
I need different email alerts for when content is created and when its updated. The issue is that im using the Multistep module:
http://drupal.org/project/multistep
The Multistep module breaks the node creation form into 2 or more separate pages. One the first page the node is created but unpublished. When you finish all the steps the node is updated and published. I need the email to be sent after the node has had all the steps filled in, as the CCK fields are used in the email. Therefore I cant use Rules inbuilt event of 'After saving new content' and 'After updating existing content'.
How can I differentiate in Rules from when the node is first fully filled in, and when its subsequently updated? One way to do this would be to have different conditions for weather the node has been updated once or more than once. Is this possible and if so, is it the best solution?
Thanks
I think the easiest way to do this would be too look at the URL or referrer like mentioned here, http://drupal.org/node/827728. You'd have to use the Execute PHP functionality and have some knowledge of how to write a short script though.
PROBLEM:
How to test for the number of times a node has been modified.
POSSIBLE SOLUTION:
Include a "counter" field in the CCK that is hidden from the user (via CSS) and auto-incremented each time the node is accessed. Then use the value of this counter in rules conditions.
(See e.g., http://drupal.org/node/1172550 for more details)
PROBLEM:
How to treat a node differently based on whether it is being 'added' for the first time, or 'updated'.
POSSIBLE SOLUTION:
Create a path rule that is conditional on node type.
Trigger the path rule for the node/add page of the specific node type.
Pre-populate fields on the node/add page using the elementdefaults module.

Resources