Skip to content

Instantly share code, notes, and snippets.

@somatonic
Created August 31, 2012 21:05
Show Gist options
  • Save somatonic/3558974 to your computer and use it in GitHub Desktop.
Save somatonic/3558974 to your computer and use it in GitHub Desktop.
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