Drupal 7 Fields/CCK concatenation - drupal-7

I have a custom content type called "stores" with four fields (Address, Name, Lat, Lon)
I have multiple stores with the same name (ie: safeway) and when working in any part of the admin interface I see duplicates of "safeway" -- I would like to add a hook to essentially concatenate "Name" and "Address" so the safeways are disambiguated in all lists, etc:
Safeway (299 River Ave.)
or
Name (Address)
Can someone please point me in the right direction??? Which hook methods do I need to read about?
Are there templates I can override? Ideally I do this as a single hook as I cannot imagine a single place in the application where the address would not be beneficial .
EDIT | I have found the Field API here but I am unsure as to which hook to override:
https://api.drupal.org/api/drupal/modules%21field%21field.module/group/field/7
EDIT 2 | I think I have narrowed down my search to this API:
https://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_formatter_prepare_view/7
But a working example would sure help???
Alex

I assume here that you are using the node's Title field as the Name field of your content type, becasue you say that you see duplicates in the admin interface.
If you need that just for administer your content, you can use the views module and build a view to show a page similar to admin/content that also shows the address field.
If you need the address to be also shown in the node page, you may use in the template.php file for your theme something like
function <yourtheme>_preprocess_node(&$variables, $hook) {
if ($variables['node']->type == '<store_node_type>') {
$variables['node']->title = $variables['node']->title . " ({$variables['node']->field_address})";
}
}

Related

Drupal 7: How do I extract specific field in a taxonomy page

How do I extract specific field for display in a taxonomy page?
I have a custom content type called "film" and each film has a Term Reference field called "casting". As expected I can click on a "casting" (tag) it brings me a page where all films are listed wherever this tag is associated. For expample if I click on "Kate Winslet" from movie Titanic, I land on a page http://localhost/mysite/tags/kate-winslet where other movies of Kate Winslet are listed. Up to this point everything is just fine.
I do not want Drupal to pull in and show default fields like just Title and Body in its own display format. Rather I want it so that I can display a photo from each film, year of release and of course the title and trimmed version of the body. I only want to customize the content of this page so that I have the control over What to Show and Where To Show a specific field value.
This is what I tried:
I cloned and put page.tpl.php in my theme's template folder. Renamed it as page--vocabulary--tags.tpl.php. Then I took out the following line of code (<?php print render($page['content']);?>) from my page--vocabulary--tags.tpl.php. The intention was to check whether the overridden template is actually being accessed by Drupal or not. It does!
But I am not been able to extract fields like field_photo or field_release_date from $page['content]. To get an idea about defined variables and how they are placed I used the following line of code:
<pre><?php /*print var_export(get_defined_vars(), TRUE);*/ ?></pre>. But even from there I could not extract a particular field like I mentioned above. The fields look to be somewhere inside $page['content']['system_main']['nodes'], but I don't know how to get to a specific field directly.
I also created a template.php with the following preprocess hook function:
<?php
function introduction_preprocess_page(&$vars) {
if (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
$term = taxonomy_term_load(arg(2));
$vars['theme_hook_suggestions'][] = 'page__vocabulary__' . $term->vocabulary_machine_name;
$vars['content'] = $vars['page']['content']['system_main']['nodes'];
}
}
?>
Both <?php print render($content) ?> and <?php print render($page['content']) ?> print the same result but I want something like <?php render($content['photo_field'])?> which I am not been able to.
I am sorry for making this too long. I have just stepped into Drupal. So wanted to make sure that what I am trying to explain matches exactly what I want to accomplish.
You are probably trying the long way to this.
You can use Views module. It allows to create custom listings querying the database, but also override existent ones, like the case of the taxonomy term page listing.
Once you have the module installed (if it's not yet), particularly the Views UI module, go to /admin/structure/views and scroll to bottom, where disabled views (grayed rows) are. You'll find one called Taxonomy term, described as 'A view to emulate Drupal core's handling of taxonomy/term.'
Click Enable on the right of it and then go to the same place where the Enable link is, click the arrow to unfold and choose Edit.
Once you're in the view edit page, you can manipulate the listing at your convenience, adding/removing fields or whatever you want to do in your particular case. If you are not familiar with Views, I recommend you to learn about it, there is a lot of related content on the web and it is close to essential for Drupal development.
Also, if you want to add more customisation to the page, you can use the same approach with the Panels module, who allows to override system pages (not just listings like Views).

Drupal7 - Filter view based on current user's roles?

Using Drupal7, Views3 and the Node Reference module, I'm using a view to populate a node reference field on a custom content type. (So it's a view of "Reference" display type.)
I want to filter this view to show (and allow users to select) only:
published content (OK)
content of a certain type (OK)
only nodes created by the current user (OK)
OR if the current user is admin or some other role, bypass the previous filter (3) and show all nodes (but still respect filters 1 and 2) (not OK)
Filters 1 and 2 are always mandatory; then either filter 3 OR 4 must also be mandatory. I know I can rearrange filters into filter groups to make this work. The problem is that I cannot find a way to build filter 4.
For filter 3, I had to bring in a Relationship of type "Content: Author", which made a lot of new filters appear, including the "User: Current" that I used for filter 3 (node author == current user).
For filter 4, I need to filter based on the role of the current user (not author), and I cannot find how to do that.
In the filters list there's a new "User: Roles" filter available, but it only refers to the "Content: Author" relationship, so it only checks the node author's roles. That's not what I need.
I'm guessing I have to add a new Relationship to bring in the current user data (something like "User: current"), and then filter on that data, but I cannot find that in the Add Relationship screen.
Any idea how to do that?
Thanks in advance.
Update:
Note: when editing the node reference field (in my custom content type), I see there's a "views arguments" field that allows to pass arguments to the view. It's not clear whether this field accepts tokens, but if so, maybe I could use that field to pass the current user ID to the View. But then I don't know how to use that in Views...
After posting the same question on drupal.stackexchange, I was suggested a solution using some PHP code in Views (contextual filter). It's the best solution I've found yet, so unless someone can propose a better solution, I'll stick with this one.
Here is the solution:
https://drupal.stackexchange.com/questions/38205/alter-field-settings-using-hook/38922#38922
And here is the gist of it:
In the View, add a contextual filter on Author: Uid, and use the following settings:
WHEN THE FILTER VALUE IS NOT AVAILABLE:
Provide default value
Type: PHP Code
Use the following code:
global $user;
if (in_array('administrator', $user->roles))
{return -1;}
else
{return $user->uid;}
WHEN THE FILTER VALUE IS AVAILABLE OR A DEFAULT IS PROVIDED
Specify validation criteria
Validator: PHP Code
Use the following code:
if ($argument == -1)
{return FALSE;}
else
{return TRUE;}
Action to take if filter value does not validate: Display all results for the specified field (this is what will give admins access to all results)
And that's it!
Notes:
Compared to my initial settings, the relationship (Content: Author) isn't needed anymore; neither is the "Author" filter (which was brought in by the relationship anyway).
For Drupal 6, the condition in the first PHP snippet should rather be if (in_array('super user', array_values($user->roles)))
You can allow other roles as well, simply by editing the condition above. For instance:
if (
in_array('administrator', $user->roles) ||
in_array('editor', $user->roles)
)
After adding the author relationship, there should be a new filter criteria User: Roles.
Inside your views filter criteria, you will need to have 2 filter groups combined by OR; First group contain Filters 1, 2 and 3. And the other group should contain filters 1, 2 and 4.

Is there a clean way of users managing their own locations?

A lot of my site is dynamically generated dependant on the user location.
To get an initial fix I am currently using the Smart_IP module which does this based on the user IP address - which works great as a starting point. I can access $_SESSION['smart_ip']['location']['longitude'] & $_SESSION['smart_ip']['location']['latitude'] as required - perfect!
But I need to allow my user to override this..
Using HTML5 geolocation. I want to only do this on user request, ie click 'locate me', rather than requesting their location uninvited.
Using one of a few pre-defined locations selectable by the user.
Using an inputed address by the user.
Is there any drupal module I can use for this, or how else could I achieve it?
-
Just to clarify, I am talking about anonymous users here - the general public visiting my site. I just want them to be able to refine their 'location' by overriding the defaults I give them using smart_ip.
I suggest to use Geolocation field and all it's submodules or Geofield. Last one provides more input methods.
Use the Address field module to allow the user create multiple addresses into a node (or even into his profile), Geocoder module to get the lon/lat from these addresses and then a Views to display them in a list.
Same as 2 but without views.
If you want to allow user select one of the 3 methods you can use an other - helper - field (eg a select list with the 3 options).
Finally you should add an extra field to store the lat/lon pair final values maybe with Computed field module or 2 simple textfields that will get the selected values through javascript.

Drupal 7 - How to create a contextual filter based on an aliased url

CASE:
I've created a content type 'Attorney', and have set a url alias pattern for all attorneys to be 'attorneys/[node:title]'. I'd like to create a view that uses the aliased path to display the information about the attorney. This view should have a 'page' display.
EXAMPLE:
When a user visits 'http://mydomain.com/attorneys/aaron-silber' the view returns data for the Attorney with the name Aaron Silber.
BACKGROUND:
I've searched high and low for a solution to this but can't seem to find one that works for me. Typically I'm asked to create a page view with a url of 'attorneys/%' and add a contextual filter with 'Content: Nid', choosing to provide a default value (type: Raw value from URL, path component 2).
The resources on the web for this case are aweful at best. Lets try to fix it here once and for all.
Thanks!
Use a Views block instead with the visibility set to "Only the listed pages" and supply "attorneys/*" in the textarea. Set the block to display in the main content region. Use the Content: Nid filter with a default value of path component 2, as you were previously attempting.
You can't have an attorney node page and a Views page occupying the same URL.

How to create a Drupal rule to check (on cron) a date field and if passed set field "status" to "ended"?

I'm trying to create a custom rule (using the Rules module) so that every time the cron runs, this rule checks a date field in a custom content type I created. If that date has passed then I want to set a list widget from active to ended.
This is how far I get when trying to create this rule:
Set React on event to Cron maintenance tasks are performed
Add Condition > Set Select the condition to add to Data comparison > Continue
Here is the issue: Data selectors only has site and no access to field data.
Any ideas where I'm going wrong here?
The problem with Rules condition "Cron maintenance tasks are performed" is that at that point, there is no access to the node object so any checks/manipulations on the node are not possible. As a solution, instead of Event = Cron maintenance tasks are performed, use Event = Node: Content is viewed. You can leave it open for any content type so that when someone visits the website and opens at least one page, some action will be triggered.
You need to create a rules component first:
Go to Rules > Components (admin/config/workflow/rules/components)
Then create a new component and select 'Rule' from select list
Set a name for this component and in the table below select:
Data type: Text Token
Label: A name that you want
Machine name: Use the same name of the label but set here only lower case and underscore
Usage: Parameter
In the component add the condition 'Data comparison' and select node:type
Add other conditions that you want
Set the actions that you want and save
Now go to Rules (admin/config/workflow/rules) and create the rule with action on cron maintenance (as you have already done)
Jump the conditions section and in the actions:
New action: Add a variable
Value: Text
Then write the value of this variable just like the machine name of content type that you want to cycle on (if you want you can change the name and machine name of this variable in the section below)
Now add another action 'Fetch entity by property'
Entity type value: Node
Property value: Type
Data selector: the variable created at the point 8
Now add a loop in parameter list use the variable provided by 'Fetch entity by property'
Add an action in the loop (click on the link to the right of loop row) and select the component created in the point 2 and pass the variable provided by loop
I state: I do not know if it works but at least it should direct you towards the right path
Sorry for my english, I hope you understand everything :)
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 Views Rules module. Some details about this 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 you want to be processed (related to your custom content type and if possible filter somehow using your date field). Whereas that view has fields (columns) for whatever is needed in subsequent steps, e.g the node ID, the date field, and possibly other fields as well. You'll need these View fields later on as values to be processed by your rule, "to set a list widget from active to ended*" (as in your question). Important: use a Views display type of "Rules".
Remove that "add condition" (in the custom rule you started) and, instead, 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" (= to set a list widget from active to ended). 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 value of that list widget 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. Typically the things you cannot, or have not yet, expressed as a Views filter. However, if you have a choice between using a Views filter and an extra Rules Condition, I recommend to go for the Views filter, because that will reduce the number of your iterations in your Rules loop (performance!).
Easy, no?

Resources