Count number of pages with an attribute?

Permalink 1 user found helpful
Hi all

How would I efficiently count the number of pages that have a particular attribute? Ideally using the API (although whatever works is fine!)

I want to use the number to amend another page count (num of children - number of children with attribute X)

mel

melat0nin
 
Doki replied on at Permalink Reply
Doki
Without DB access? The only thing I can think of is to go Dashboard->Sitemap->Page Search. On the top row of the pages table, click the + sign and add the attribute in question to the table. Then, do a search with both the Page Name and Full Page Index blank (which should give you every page in the system). Order the pages by the attribute by clicking on the attribute name at the top of the table. Start counting.

Drawback -- you have to hand count the rows.
melat0nin replied on at Permalink Reply
melat0nin
Sorry I meant using the API rather than resorting to a direct SQL query. Going into the DB is fine in that sense!
codingpenguins replied on at Permalink Reply
When I saw this question, I was like how do you do that without DB access.

So nice answer Doki.

It does display the total number of pages at the top when you search the pages, so no reason to count one by one. : )

This even works for page types...
melat0nin replied on at Permalink Reply
melat0nin
I'm not making myself clear.. I don't want to know the count for my own amusement, it's to be used in another piece of code! :)
codingpenguins replied on at Permalink Reply
So what you are looking for is some $object->getAllPageAttributes() and $pageAttributeObject->getCount() kind of API return, that is built into concrete?
melat0nin replied on at Permalink Reply
melat0nin
Yes, something like that, so that I can subtract from a given page count the number of pages which have a particular attribute enabled (in this case an 'inactive' attribute)
codingpenguins replied on at Permalink Reply
What I think you want to do is create a PageList if you do this
Loader::model('page_list');
$pl = new PageList();


The file for this model is at /concrete5/models/page_list, so if you want to look at all the methods involved.

You can get the count at any time. The ability to use filters and sorting are also involved. Filter by name, alias, sort by date, filter by collection type id, by handle, or set your own query. This is complete OO so I believe this is the API route you wanted to go. The above example will have all the pages that are in the system.

echo $pl->getTotal(); //display 15 which matches my sitemap count (no system pages)
melat0nin replied on at Permalink Reply
melat0nin
Thanks for your replies. I had a look through the page_list.php model and there's a method at the top which looks like it might fit the bill.

I'm actually trying to edit Matogertel's Search Tools addons (specifically the Tag Cloud block) to make it show tag counts for pages only when they have a specific attribute set ('active').

I looked at the code of the controller for the addon but couldn't work it out, so I thought I would hack at it by subtracting the number without the attribute set from the total number, thereby leaving an accurate count. Messy but it would work. That said, I think i'll keep going with trying to edit the block's functionality directly. Matogertel's not very quick with support queries though, so I'm a bit in the dark.

Thanks for your suggestions & time spent looking - much appreciated! :)
melat0nin replied on at Permalink Reply
melat0nin
Going back to the count by attribute approach, I need to filter first by a select attribute and then by the 'isActive' attribue (boolean).

I tried the following, to see if I could filter by the select attribute on its own:

Loader::model('page_list');
   $pl = new PageList();
   $pl->filterByAttribute('attr_name','attr_value','like');
   echo $pl->getTotal();


..but no joy. I think this is related to a known bug re spaces being inserted into the array of attribute values, but i'm not sure to what extent that affects this.
Doki replied on at Permalink Best Answer Reply
Doki
Got it. Below is an example on how to get all pages where the 'Exclude from Nav' attribute is true. Included code to get both an array of handles and an array of ids.

$pl = new PageList();
$pl->filterByAttribute('exclude_nav',true,'=');
$totals = $pl->getTotal();
$cIDlist = array();
$cHandlelist = array();
for($x = 0; $x < $totals; $x++)
{
   $page = $pl->get(1,$x);
   $cIDlist[$x] = $page[0]->getCollectionID();
   $cHandlelist[$x] = $page[0]->getCollectionHandle();
}


This should solve it.
melat0nin replied on at Permalink Reply
melat0nin
Thanks!

This worked.. I was able to filter first by pages with the active attribute, then by the given select attribute to get the right count:

$currentSector = '%'.$value['word'].'%';
$pl = new PageList();
$pl->filterByAttribute('job_active',true,'=');
$pl->filterByAttribute('sector',$currentSector,'like');
$sectorTotal = $pl->getTotal();


Thanks again :)
Doki replied on at Permalink Reply
Doki
I think thats what he wants.

I took 15 minutes to spin through the APIs, but I didn't see anything like that. (Reference: you can see the complete list of APIs at:http://www.concrete5.org/api/).... The only think I can think of at the moment is to do several API calls, one to get a list of all cIDs (aka the id number for every existing page), get a list of the maximum cvIDs for each cID (aka get the latest page version) then run something to the extent of:

Loader::model('attribute/categories/collection');
$attributes = CollectionAttributeKey::getAttributes($cID, $cvID, [ $method = 'getValue']);


..for each cID/cvID. Search the list for the akHandle of the attribute you're interested in (aka, if you want Exclude from Nav, look for 'exclude_nav' as the akhandle). Store if found. Rinse, repeat until list of cIDs/cvIDs are exhuasted. That should get you your list.

Sorry I couldn't find an easier method. Hopefully someone else can build on this to get a simpler answer....