I have Drupal 5 View (must be "Views 1" so), which contains Event_StartTime field, which shows up normally for the fields that have a real date inside. But I also have a number of records with Event_StartTime field value like Dec 31 1969 - 8:00pm which looks bad in view and I need to replace them with some custom label, like "No Date Available".
Can I somehow inject this condition (if value = x show value y) into view?
Even when I print in "No Date Available" into SQL, the view will show empty field.
To sum up, the general problem is that View fields are kind of limiting, and sometimes you just need to replace some field value, but it's either "date or nothing" or "node-reference id or nothing".
P.S. The situation might be a bit complicated because I use "Bonus: Views Export" module which makes my view return CSV data.
I'm not really familiar with Views1 anymore, but I think you have at least two options:
At the theming level - you could override the field template and put a check for the particular date value in there, replacing it when found. Of course this check would depend on the formatting of the dates, so if you ever change that, you'd need to adjust the check as well.
At the view generation level - you could execute the view 'manually' from code and inspect the views object right after instantiation and/or after execution, but before rendering (See her for an example of manipulationg the view object in Views2). You could manipulate the result property after execution, but before rendering, or you might be able to put a pre-render callback in there right after instantiation (but I'm not sure if this is already possible in Views1).
Building off of Henrik's comment, theming seems to me to be the best place to do this. You would need to add a function to your template.php file to override that specific view. See the Views 1 theming documentation. Based on this documentation, you create a function with the name of your view of the form
function THEMENAME_view_view_VIEWNAME($view, $type, $nodes, $level = NULL, $args = NULL)
to theme the whole view. $nodes is an array of partially-loaded node objects that are included in your view. You can load each node and check the values of the Event_StartTime field with something like this:
foreach ($nodes as $id => $node) {
$temp_node = node_load($node->nid);
//now check value of Event_StartTime assuming that is what you named the field
if ($temp_node->Event_StartTime === 'Dec 31 1969 - 8:00pm') {
$temp_node->Event_StartTime = 'No Date Available';
}
//output the fields of your view . . .
}
I only showed how to check the value of the Event\_StartTime field, and I am not sure what the actual value is. Dec 31 1969 is before the dates returned by the time() function, so if this does not work you might want to check if Event_StartTime === '', which may be true if the event field is just left empty. You will still have to theme the rest of your fields and output them as HTML, which might be too much of a pain just to change the output of one field. You can also override the output of individual fields. I have not done this so I couldn't walk you through it, but the link I gave above has some documentation on overriding field theming functions.
Related
I have added due_date into the Manifest Custom Field. Now I want that where ever task list showing to the user then Due Date also displayed over there.
I know its very small change in codebase but I am not able to debug this.
I missed a step you need I think to call $fields->readFieldsFromStoage($task) and then I used $field->getValueForStorage()
I can't say how correct or legal, of even efficient it is, but it does what I think you wanted
$fields = PhabricatorCustomField::getObjectFields(
$task,PhabricatorCustomField::ROLE_VIEW);
if ($fields){
$fields->readFieldsFromStorage($task);
foreach ($fields->getFields() as $field){
if ($field->getModernFieldKey()=='custom.mycustomfield'){
// in theory you might be able to add it like this
$item->addByline(pht('Due Date:%s', $field->getValueForStorage()));
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
}
}
Hope that helps
Ok not a solution, but a place to start...
To alter this you need to edit
ManiphestTaskListView.php in
phabricator/src/applications/maniphest/view
Where you want to put due date is where "Assigned:" is put
if ($task->getOwnerPHID()) {
$owner = $handles[$task->getOwnerPHID()];
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
}
Pulling in the custom fields may require a little more research, I think you can get to the tasks custom fields via the following
$fields = PhabricatorCustomField::getObjectFields(
$task,PhabricatorCustomField::ROLE_VIEW);
You could then pull out the field you want like this if you have to, I suspect there is a better way of doing this...so you just ask for the specific field
if ($fields){
foreach ($fields->getFields() as $field){
if ($field->getModernFieldKey()=='custom.mycustomfield'){
// in theory you might be able to add it like this
$item->addByline(pht('%s', $field->getXXXX()));
}
}
I'm not sure what you need to do to get the custom field value, i'm using getXXXX() to represent the sort of thing you might need to do, I think the custom fields often have a render() method but again I'm not completely sure how you go about getting that to render in your listview
So I have a post meta field that has two values, true or false. It is defaulted at false, and it'll automatically change to true when an event occurs.
Anyway, is it possible to create another meta field that records the exact time that this change occurs? If so, how would I go about doing this?
Well without modifying wordpress core or overriding the update_field() function in your theme functions.php you cant get in a smooth way the time when a record has been added to the database.
But what can i advice to you:
1) If your application highly depends on seconds:milliseconds when post_meta has been modified, you should use advanced technique: database transactions.
2) If your application are fine with a small delay between writing up 1st meta and the second just add it with add_post_meta() right below the update_field() performed
p.s If you think that overriding the function with functions.php is the way you prefer just ping me a comment, i'll try to help you with by editing the post.
Cheers!
EDIT
Right after your manipulation with allready_aired field performed
$alreadyAired = get_field('already_aired', $episodeID);
if (get_field('already_aired', $episodeID) == "no") {
update_field('field_28', "yes", $episodeID);
}
you can use add_post_meta($post_id, $meta_key, $meta_value, $unique) function in a way like this:
$alreadyAired = get_field('already_aired', $episodeID);
if (get_field('already_aired', $episodeID) == "no") {
update_field('field_28', "yes", $episodeID);
}
add_post_meta($episodeID, 'NEW_TIMESTAMP_FIELD', time(), true);
Then, you can call this NEW_TIMESTAMP_FIELD and use in a way you like (echo formatted date-string, compare 2 dates, etc.
Please note the 4th parameter of add_post_meta function. This one tell you that this field is unique and considering that app_post_meta does not affect "Update" actions, this bundle wont let this field get modified in the second time.
I'm using the better_exposed_filters module to create a set of exposed filters for a view. One of the filters is being displayed as a select field, and I would like the field to only display options that are actually associated with content in the database.
Currently, I am doing this using the hook_form_alter() method. For simplification, in the following example the field is called 'foo' and the content type with that field is called 'bar':
function my_module_form_alter(&$form, $form_state, $form_id) {
// Get all the values of foo that matter
$resource = db_query('select distinct field_foo_value from {content_type_bar}');
$foo = array();
while($row = db_fetch_object($resource)) {
$foo[$row->field_foo_value] = $row->field_foo_value;
}
$form['foo']['#options'] = $foo;
}
This works great -- the form displays only the options I want to display. Unfortunately, the view doesn't actually display anything initially and I also get the following error message:
An illegal choice has been detected. Please contact the site administrator.
After I filter options with the form once, everything seems to work fine.
Does anyone know how I can solve this problem? I'm open to an entirely different way of weeding out filter options, if need be, or a way that I can figure out how to address that error.
Under your view argument there should be a section called "Validator options" with ""Action to take if argument does not validate under it. Depending on what you want shown, you should be able to display all values or display an empty page.
I found a solution that works, but it's somewhat hackish. I force the form to think that it's validated, and it doesn't complain anymore, with the following line at the bottom of the function:
$form['foo']['#validated'] = true;
I have created a custom module and am using hook_block to programmatically create some blocks.
My question is how can I access field values including CCK fields for the current node within my module?
I basically want to get a value from a CCK field and use the value when building my block for that page.
Getting at the current node is an awkward pain in the posterior. Standard practice is to do something like this:
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
$node = node_load(arg(1));
// Collect output.
}
arg() pulls elements out of the Drupal path. Since all nodes (regardless of what a path alias might show you) appears at node/#, by checking for 'node' and that the second element is a number, you are fairly well guaranteed to have your hands on a node. Checking the third path element allows you to avoid processing on the node edit form and other pages that hang off a specific node.
CCK Values are loaded into the node, and usually look something like this:
// Text field. Structure also works for number fields.
$text = $node->field_my_text_field[0]['value']
// Node Reference field.
$nref = $node->field_my_nref_field[0]['nid']
// User Reference field.
$uref = $node->field_my_uref_field[0]['uid']
The "0" array element specifies the delta of the field. Any given field can actually process multiple values, and the array structure in CCK assumes this possibility even if you restrict the field to a single value.
In Drupal 6 there is a built-in Drupal function to get the node object.
if ($node = menu_get_object()) {
…
}
Read more here http://api.drupal.org/api/function/menu_get_item/6.
I'm trying to create a node (B type) & assign it to a A type node's CCK nodereference field using node_save() method.
$node_type_A = node_load($some_nid);
$node_type_A->field_type_B_node_ref[]['nid'] = $node_type_B_nid;
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
As the result, a new B type node will be created, but no reference will be assigned to the A type node. any help would be appreciated.
GApple is right, the format is correct, but there are couple of things that you might want to care about.
Delta Value
First you need to know the delta value of the latest node reference attached to $node_type_A, the delta is actually a partial index, when combined with vid field of the $node_type_A, they become the index for node reference table in the database. In other words, its a count for $node_type_B which are referenced in $node_type_A, ok?
GApple is right again, you have to exactly say where to add the new reference. When you got that delta value you can exactly say where to append (delta+1) the new reference. Here it is:
function get_current_delta($node_vid){
return db_result(db_query("SELECT delta FROM {content_field_type_A_node_ref}
WHERE vid = '%d'
ORDER BY delta DESC
LIMIT 1", $node_vid));
}
Adding the new reference
We got delta! so we can attach the new $node_type_B node to our $node_type_A node:
// Loading type_A node.
$node_type_A = node_load($some_nid);
// Getting current delta value.
$current_delta = get_current_delta($node_type_A->vid);
// "Appending" a node reference based on delta.
$node_type_A->field_type_B_node_ref += array($current_delta + 1 => array('nid' => $node_type_B_nid));
Resaving the updated node
Optionally call node_submit() to populate some essential fields in the node object and save it by utilizing node_save(). After all, you need to call content_insert() to make the node completely saved asidelong with its CCK fields:
// Resaving the updated node.
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
content_insert($node_type_A);
Flushing the content cache
Probably the most important part, this was killin' me for couple of days. CCK has a cache table in the database called cache_content (take a look at its structure), after resaving the updated node, you will notice that nothing has changed in the $node_type_A theme output even though that the tables are updated. We have to remove a record from that content cache table, this will force Drupal to show the latest snapshot of the data. You can define the following as a function:
db_query("DELETE FROM {cache_content} WHERE cid = '%s'", 'content:' . $node_type_A->nid . ':' . $node_type_A->vid);
Hope it helps ;)
I just checked one of my own modules that does something similar for the object format, and $node_type_A->field_type_B_node_ref[]['nid'] should be correct.
One thing to check for is that when you load the node, CCK may pre-populate the node reference array with an empty value. If you have configured the field to only allow one value, by using the array append operator (field_type_B_node_ref[]) it will create a second entry that will be ignored (field_type_B_node_ref[1]), instead of overwriting the existing value (field_type_B_node_ref[0]). Try explicitly specifying the array key if possible.
Great post, but one correction: don't flush cache entries by manually querying the DB. In the event someone is using memcache or any other external cache it's going to fail.
cache_clear_all() is your friend for clearing.
Suggested code, direct from the CCK module:
cache_clear_all('content:'. $node_type_A->nid .':'. $node_type_A->vid, content_cache_tablename());
I show CCK storing node references as $node->field_node_reference[0]['items'][0]['nid'], not $node->field_node_reference[0]['nid']. Have you tried mimicking that?
"Flushing the content cache" This works for me, especially if you get a data from node_load()