Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Find related pages using Fieldtype Page for tagging. Returns PageArray with added property "score" for later use.
<?php
/**
* TagsHelper ProcessWire2.+ Module
*
*
* @author Soma
* modified 2012/08/31
*
* ProcessWire 2.x
* Copyright (C) 2010 by Ryan Cramer
* Licensed under GNU/GPL v2, see LICENSE.TXT
*
* http://www.processwire.com
* http://www.ryancramer.com
*
*
*
*/
class TagsHelper extends WireData implements Module {
/**
* getModuleInfo is a module required by all modules to tell ProcessWire about them
*
* @return array
*
*/
public static function getModuleInfo() {
return array(
'title' => 'Tags Helper',
'version' => 1,
'summary' => 'Finds related pages using a Fieltype Page field with multiple tags. Returns PageArray with added [score] property to page objects or null if none found. Usage: $result = $pages->findRelated( Page $page, PageArray $tags, string $field [, string $tmpl, int $limit] );',
'href' => '',
'singular' => true,
'autoload' => true
);
}
public function init() {
// add method to $pages var
$this->addHook('Pages::findRelated', $this, 'findRelated');
}
/**
* Find related pages using Page reference field
*
* findRelated( Page $page, PageArray $tags, string $field [, string $tmpl, int $limit] );
*
* @param HookEvent $event
* @return PageArray|null
*/
public function findRelated( HookEvent $event ) {
// get arguments
$page = $event->arguments[0];
if(!$page->id) throw new WireException("findRelated() Error: first argument page is not found.");
$tags = $event->arguments[1];
$field = $event->arguments[2];
//$tmplq = isset($event->arguments[3]) ? ",template=".$event->arguments[3] : '';
if(isset($event->arguments[3])){
$tmpl = $event->arguments[3];
if(strpos($tmpl,"|") !== false){
$tmpls = explode("|",$tmpl);
foreach($tmpls as $t) {
if( $tt = wire("templates")->get($t) )
$tmplIDs[] = $tt->id;
else throw new WireException("findRelated() Error: template '$t' could not be found.");
}
$tmplq = " AND pages.templates_id in(" . implode(',',$tmplIDs) . ")";
} else {
$tmplID = wire("templates")->get($tmpl)->id;
$tmplq = " AND pages.templates_id=$tmplID";
}
} else {
$tmplq = '';
}
$limit = isset($event->arguments[4]) ? $event->arguments[4] : 100;
/* mysql plain query method, this way we can sort multiple rows
----------------------------------------------------------------- */
if(count($tags) < 1) return $event->return = null;
foreach($tags as $tag) $tagIDs .= "$tag->id,";
$tagIDs = substr($tagIDs,0,-1);
$query = "
SELECT data,pages_id,modified, COUNT(pages_id) as score
FROM field_$field LEFT JOIN pages ON (field_$field.pages_id=pages.id)
WHERE field_$field.data in($tagIDs)
AND field_$field.pages_id != $page->id AND pages.status < 2048 $tmplq
GROUP BY pages_id
ORDER BY score DESC, modified DESC
LIMIT $limit";
$res = $this->db->query($query);
if(!$res->num_rows) return $event->return = null;
$pa = new PageArray();
while($r = $res->fetch_object()){
$pa->add(wire("pages")->get($r->pages_id)->set("score",$r->score));
}
$event->return = $pa;
/* PW query method, this way we can only sort on one field
----------------------------------------------------------------- */
/*
foreach($tags as $tag) {
$found = wire("pages")->find("$field=$tag,id!=$page->id,limit=$limit" . $tmplq);
foreach($found as $r) $rel[$r->id]++;
}
// if none found return
if(empty($rel)) return $event->return = null;
// build PageArray and add "score" property
$pa = new PageArray();
foreach($rel as $key => $score) {
$pa->add( wire('pages')->get($key)->set("score",$score) );
}
$event->return = $pa;
*/
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.