Drupal 7: Get all content items attached to all terms in a vocabulary sorted by date - drupal-7

Just like the title says. I have a vocabulary with several terms. I'd like to be able to get all items tagged by each of the terms in the vocabulary sorted by date created in one giant list. Is this possible with the built-in taxonomy API or am I going to have to build something custom?

As far as I know, there is no function/method in Drupal API will get that for you. I believe you will have to make your own.

When you say 'items' if you mean nodes then the function you are looking for is taxonomy_select_nodes().
https://api.drupal.org/api/drupal/modules%21taxonomy%21taxonomy.module/function/taxonomy_select_nodes/7
This function returns an array of node ids that match have the term selected.
/**
* Get an array of node id's that match terms in a given vocab.
*
* #param string $vocab_machine_name
* The vocabulary machine name.
*
* #return array
* An array of node ids.
*/
function _example_get_vocab_nids($vocab_machine_name) {
$vocabulary = taxonomy_vocabulary_machine_name_load($vocab_machine_name);
if (!$vocabulary) {
return array();
}
$terms = taxonomy_get_tree($vocabulary->vid);
if (!$terms) {
return array();
}
$nids = array();
foreach ($terms as $term) {
$term_nids = taxonomy_select_nodes($term->tid, FALSE);
$nids = array_merge($nids, $term_nids);
}
return $nids;
}

Related

Sorting a Doctrine ArrayCollection by a specific, custom field

I am attempting to sort an ArrayCollection by a specific field. The ArrayCollection is an array of courses. In the Course entity there is a method called isLive which returns a boolean.
I would like to sort this collection to have the "live" courses at the beginning of the array, so that's the courses that return true from a isLive call.
This is the code I have at present, but the first entry in the $sorted array is a non-live course.
$iterator = $this->courses->getIterator();
$iterator->uasort(function ($a, $b) {
if ($a->isLive() == $b->isLive()) {
return 0;
}
return ($a->isLive() < $b->isLive()) ? -1 : 1;
});
$sorted = new ArrayCollection(iterator_to_array($iterator));
It looks like a good use case for Doctrine Criteria. They allow to filter/sort ArrayCollections, either in memory if the collection is already loaded, either by adding a WHERE / ORDER BY SQL clause next time the collection will be loaded from the database. So that's pretty optimized!
Code should look like something like this, assuming you have a live field behind isLive():
$criteria = Criteria::create()
->orderBy(["live" => Criteria::DESC])
;
$sorted = $this->courses->matching($criteria);
For the entity, do this: add an OrderBy annotation to the property.
/**
* #OneToMany(targetEntity="Course")
* #OrderBy({"live": "ASC"})
*/
private $courses;
I got to a solution with the use of uasort and array_search as below:
/**
* #return ArrayCollection
*/
public function getCoursesSortedByLive(): ArrayCollection
{
$coursesIterator = $this->courses->getIterator();
$sortOrder = [true];
$coursesIterator->uasort(function ($a, $b) use ($sortOrder) {
return array_search($a->isLive(), $sortOrder) - array_search($b->isLive(), $sortOrder);
});
return new ArrayCollection(iterator_to_array($sitesIterator));
}

Drupal - get the field of view

Hello!
I am trying to get the fields of views
There is a code:
$variables = module_invoke('views', 'block_view', 'news-block');
print render($variables['content']);
to display unit software.
Whether it is possible to obtain the field at such a conclusion. Rather get views across the fields from variable $variables
Advance all grateful
Sorry for my English.
You can use views_get_view_result function:
$view = views_get_view_result($name, $display_id); // returns an array conatining the result of the view
print_r($view);
If you prefer to get whole node objects, you can use node_load function with nids of each row:
$view = views_get_view_result($name, $display_id); // returns an array conatining the result of the view
$nodes = array(); // create an empty array to push each node objects
foreach ($view as $row) {
$node = node_load($row->nid); // get the node object by nid
$nodes[] = $node; // push node to $nodes array
}
print_r($nodes);
Also see: https://drupal.stackexchange.com/questions/32825/get-a-views-result-using-php-code-and-iterate-the-proper-way

Accessing array values of a field collection in a node with Drupal?

Please bare with a very recent user of Drupal.
I want to create an array out of all examples of the string "url" on a Drupal site.
I've used the method "field_get_items" previously to do something very similar, but I am now trying to access a field collection that is many levels deep into the node's array and I'm not sure that method would work.
$website_urls = array();
$faculty_members = field_get_items('node', $node, 'field_faculty_member');
for ($i = 0; $i < count($faculty_members); $i++) {
$value = field_view_value('node', $node, 'field_faculty_member', $faculty_members[$i]);
$field_collection = $value['entity']['field_collection_item'][key($value['entity']['field_collection_item'])];
$website_urls[] = render($field_collection['field_link']['#items'][0]['url']);
}
An example of one url's location is...
['field_faculty_program'][0]['entity']['field_collection_item'][1842]['field_faculty_member'][0]['entity']['field_collection_item'][1843]['field_link']['#items'][0]['url']
..and another...
['field_faculty_program'][4]['entity']['field_collection_item'][1854]['field_faculty_member'][0]['entity']['field_collection_item'][1855]['field_link']['#items'][0]['url']
What is the method I should be using to collect al of the 'url' strings for placement in an array?
You can actually still use the field_get_items() function but eventually pass it 'field_collection_item' instead for the node type.
Something like this should work:
if ($items = field_get_items('node', $node, 'field_faculty_member')) {
//loop through to get the ids so we can take
//advantage of field_collection_item_load_multiple for
//greater efficiency
$field_collection_item_ids = array();
foreach ($items as $item) {
$field_collection_item_ids[] = $item['value'];
}
if ($field_collection_items = field_collection_item_load_multiple($field_collection_item_ids)) {
foreach ($field_collection_items as $subitem) {
//now we load the items within the field collection
if ($items = field_get_items('field_collection_item', $subitem, 'field_faculty_member')) {
//And you can then repeat to go deeper and deeper
//e.g. a field collection item within a field collection
//for instance to get the urls within your faculty members
//item. Best to break this into functions or a class
//to keep your code readable and not have so many nested
//if statements and for loops
}
}
}
}
Hope that helps!
Scott

How to sort get_terms() results in a specific order

I am populating an unordered list by the results from get_terms() assigned to a variable. What I would like to do is order the results in a specific order in the unordered list. How would I do this? I looked into using the orderby argument for the get_terms() function but none of the parameters for that seem to work the way I need them to. How do I define a specific order for them to be displayed in? So basically my unordered list looks like this once populated:
Atletics
Community
Corporate
Healthcare
Higher Education
k-12
And I want it to look like this:
k-12
higher education
healthcare
atletics
Corporate
community
The best option is to write a wrapper function for get_terms and then use usort() to sort the terms in the order you want.
Here is the code, I have commented the code to make it easy to follow and to understand (NOTE: This code requires PHP 5.4+)
function get_terms_ordered( $taxonomy = '', $args = [], $term_order = '', $sort_by = 'slug' )
{
// Check if we have a taxonomy set and if the taxonomy is valid. Return false on failure
if ( !$taxonomy )
return false;
if ( !taxonomy_exists( $taxonomy ) )
return false;
// Get our terms
$terms = get_terms( $taxonomy, $args );
// Check if we have terms to display. If not, return false
if ( empty( $terms ) || is_wp_error( $terms ) )
return false;
/**
* We have made it to here, lets continue to output our terms
* Lets first check if we have a custom sort order. If not, return our
* object of terms as is
*/
if ( !$term_order )
return $terms;
// Check if $term_order is an array, if not, convert the string to an array
if ( !is_array( $term_order ) ) {
// Remove white spaces before and after the comma and convert string to an array
$no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $term_order, FILTER_SANITIZE_STRING ) );
$term_order = explode( ',', $no_whitespaces );
}
// Remove the set of terms from the $terms array so we can move them to the front in our custom order
$array_a = [];
$array_b = [];
foreach ( $terms as $term ) {
if ( in_array( $term->$sort_by, $term_order ) ) {
$array_a[] = $term;
} else {
$array_b[] = $term;
}
}
/**
* If we have a custom term order, lets sort our array of terms
* $term_order can be a comma separated string of slugs or names or an array
*/
usort( $array_a, function ( $a, $b ) use( $term_order, $sort_by )
{
// Flip the array
$term_order = array_flip( $term_order );
return $term_order[$a->$sort_by] - $term_order[$b->$sort_by];
});
return array_merge( $array_a, $array_b );
}
There are four parameters to the function
$taxonomy This is the taxonomy from which to get terms from. Default: empty string
$args This is all the valid arguments that can be passed to get_terms. You can check out get_terms for valid arguments. Default: empty array
$term_order The slugs or names or ids of the terms in the specific order you want them sorted. This can be an array of slugs/names/ids or a comma separated string of slugs/names/ids. Default empty string
Examples
string: $term_order = 'term-3, term-1, term-2';
array: $term_order = ['term-3', 'term-1', 'term-2'];
This will display the terms in order of term-3, term-1, term-2
$sort_by By which field the terms must be sorted. The default value is slugs, so this means that you should pass a string or an array of terms slugs to the $term_order parameter. If you need to pass term names to the $term_order parameter, then you need to set the value of $sort_by to name. You can also pass, if you wish, term ids to $term_order, in which case you then need to set the $sort_by value to term_id
USAGE
In your template, you will use the function as follow with the following example
Taxonomy name is category, we don't want to set any specific argument, we need sort the terms by name in the following order Term C, Term A, Term B
You will then do the following: ($term_order as an array)
$terms = get_terms_ordered( 'category', [], ['Term C', 'Term A', 'Term B'], 'name');
var_dump( $terms);
($term_order as a string)
$terms = get_terms_ordered( 'category', [], 'Term C, Term A, Term B', 'name');
var_dump( $terms);
One problem I've found with setting an order that the client wants, is that the client will later want to re-order the list so another way to allow a desired order and ability to alter that later without adjusting the code would be the following:
Create a custom field for the taxonomy terms. A great way is using Advanced Custom Fields plugin which makes this field editable in the dashboard.
Give that custom field a default value of '0'.
Use the get_terms() function and include the following settings in the array. In this example jht_order is the name of the custom field.
'orderby' => 'meta_value',
'meta_key' => 'jht_order',
Now the terms will be ordered by the value of this field. Note: if the term doesn't have this field populated, it won't be returned by get_terms()
Update: If the custom field is a number, you'll want to change 'orderby' to be 'meta_value_num' so it will sort it as a number and not as ascii.
'orderby' => 'meta_value_num'

drupal_write_record doesn't take object

In drupal 6 i used to do something like this:
<?php
/*
* CLASS Example
*/
class example {
var $id = NULL;
var $title;
var $body;
.....
// Save
function save() {
$primary_key = ($this->id == NULL ? NULL : 'id');
if (drupal_write_record('mytabble', $this, $primary_key)) {
return TRUE;
} else {
return FALSE;
}
}
}
?>
This worked quite well. But in Drupal 7, the drupal_write_record only takes an array and no longer the object $this. The new db_merge also only takes an array.
Since i want to save the properties of my object to the database, the above code was very handy and generic for all kinds of classes.
Is there an alternative way to write an object to database, or a method to place objectproperties into a an array?
Any help will be appreciated!
Robert
drupal_write_record does take an object or an array. Guess your problem is caused somewhere else.
drupal_write_record($table, &$record, $primary_keys = array())
$record: An object or array representing the record to write, passed in by reference. If inserting a new record, values not provided in $record will be populated in $record and in the database with the default values from the schema, as well as a single serial (auto-increment) field (if present). If updating an existing record, only provided values are updated in the database, and $record is not modified.
More info on drupal_write_record for D7.

Resources