mirror of
https://github.com/processwire/processwire.git
synced 2025-08-24 15:23:11 +02:00
Significant improvements to FieldtypeComments::find() method, adding support for selectors containing multiple sort values, OR values (for most properties), fulltext index searching of comment text, and matching comments based on field values present on the page that contains the comment field.
This commit is contained in:
@@ -1004,33 +1004,87 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
public function find($field, $selectorString) {
|
public function find($field, $selectorString) {
|
||||||
if(is_string($field)) $field = $this->wire('fields')->get($field);
|
if(is_string($field)) $field = $this->wire('fields')->get($field);
|
||||||
if(!$field instanceof Field) throw new WireException('Arg 1 to find() must be a field');
|
if(!$field instanceof Field) throw new WireException('Arg 1 to find() must be a field');
|
||||||
|
|
||||||
|
$intColumns = array(
|
||||||
|
'id',
|
||||||
|
'status',
|
||||||
|
'created',
|
||||||
|
'pages_id',
|
||||||
|
'parent_id',
|
||||||
|
'created_users_id',
|
||||||
|
'upvotes',
|
||||||
|
'downvotes',
|
||||||
|
'stars'
|
||||||
|
);
|
||||||
|
|
||||||
|
$sortColumns = array(
|
||||||
|
'sort',
|
||||||
|
'status',
|
||||||
|
'id',
|
||||||
|
'pages_id',
|
||||||
|
'created_users_id',
|
||||||
|
'created',
|
||||||
|
'upvotes',
|
||||||
|
'downvotes',
|
||||||
|
'stars'
|
||||||
|
);
|
||||||
|
|
||||||
$limit = 10;
|
$limit = 10;
|
||||||
$start = 0;
|
$start = 0;
|
||||||
$desc = true;
|
$sorts = array();
|
||||||
$sort = 'created';
|
|
||||||
$database = $this->wire('database');
|
$database = $this->wire('database');
|
||||||
|
|
||||||
|
$selectQuery = new DatabaseQuerySelect();
|
||||||
|
$countQuery = new DatabaseQuerySelect();
|
||||||
|
|
||||||
|
$this->wire($selectQuery);
|
||||||
|
$this->wire($countQuery);
|
||||||
|
|
||||||
$table = $database->escapeTable($field->getTable());
|
$table = $database->escapeTable($field->getTable());
|
||||||
$sql = "SELECT * FROM `$table` WHERE id>0 ";
|
|
||||||
$sqlCount = "SELECT COUNT(*) FROM `$table` WHERE id>0 ";
|
$selectQuery->select("$table.*")->from($table)->where('id>0');
|
||||||
|
$countQuery->select('COUNT(*)')->from($table)->where('id>0');
|
||||||
|
|
||||||
$selectors = $this->wire(new Selectors($selectorString));
|
$selectors = $this->wire(new Selectors($selectorString));
|
||||||
|
$wheres = array();
|
||||||
|
$joins = array();
|
||||||
|
$leftJoins = array();
|
||||||
|
$binds = array();
|
||||||
|
$cnt = 0;
|
||||||
|
|
||||||
foreach($selectors as $selector) {
|
foreach($selectors as $selector) {
|
||||||
|
|
||||||
$f = $database->escapeCol($selector->field);
|
$cnt++;
|
||||||
|
$f = $selector->field;
|
||||||
|
if(is_array($selector->field)) throw new WireException("OR not supported for field in: $selector");
|
||||||
|
$f = $database->escapeCol($f);
|
||||||
$operator = $selector->operator;
|
$operator = $selector->operator;
|
||||||
$value = $selector->value;
|
$value = $selector->value;
|
||||||
$_sql = '';
|
|
||||||
|
|
||||||
if(!$database->isOperator($operator)) continue;
|
|
||||||
if(is_array($f)) $f = reset($f);
|
if(is_array($f)) $f = reset($f);
|
||||||
if(is_array($value)) $value = reset($value);
|
if(is_array($value)) {
|
||||||
|
$values = $value;
|
||||||
|
$value = reset($value);
|
||||||
|
} else {
|
||||||
|
$values = array($value);
|
||||||
|
}
|
||||||
|
|
||||||
if($f == 'page') $f = 'pages_id';
|
if($f == 'page') $f = 'pages_id';
|
||||||
if($f == 'user') $f = 'created_users_id';
|
if($f == 'user') $f = 'created_users_id';
|
||||||
|
if(strpos($f, 'page.') === 0) $f = 'page_' . substr($f, 6);
|
||||||
|
|
||||||
if(in_array($f, array('id', 'status', 'created', 'pages_id', 'parent_id', 'created_users_id', 'upvotes', 'downvotes', 'stars'))) {
|
if(in_array($f, $intColumns)) {
|
||||||
$_sql .= "AND $f$operator" . ((int) $value) . " ";
|
if(!$database->isOperator($operator)) $operator = '=';
|
||||||
|
if(count($values) > 1 && ($operator == '=' || $operator == '!=')) {
|
||||||
|
$intValues = array();
|
||||||
|
foreach($values as $v) {
|
||||||
|
if(is_object($v)) $v = (string) $v;
|
||||||
|
$intValues[] = (int) $v;
|
||||||
|
}
|
||||||
|
$wheres[] = "$table.$f " . ($operator == '=' ? 'IN(' : 'NOT IN(') . implode(',', $intValues) . ')';
|
||||||
|
} else {
|
||||||
|
$wheres[] = "$table.$f$operator" . ((int) $value);
|
||||||
|
}
|
||||||
|
|
||||||
} else if($f == 'start') {
|
} else if($f == 'start') {
|
||||||
$start = (int) $value;
|
$start = (int) $value;
|
||||||
@@ -1041,28 +1095,93 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
} else if($f == 'sort') {
|
} else if($f == 'sort') {
|
||||||
$desc = substr($value, 0, 1) == '-';
|
$desc = substr($value, 0, 1) == '-';
|
||||||
$value = trim($value, '-');
|
$value = trim($value, '-');
|
||||||
if(in_array($value, array('sort', 'status', 'id', 'pages_id', 'created_users_id', 'created', 'upvotes', 'downvotes', 'stars'))) {
|
if(in_array($value, $sortColumns)) {
|
||||||
$sort = $database->escapeCol($value);
|
$sort = $database->escapeCol($value);
|
||||||
|
$sorts[] = "$table.$sort" . ($desc ? ' DESC' : ' ASC');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if($f == 'cite' || $f == 'email' || $f == 'ip') {
|
} else if($f == 'cite' || $f == 'email' || $f == 'ip') {
|
||||||
$value = $database->escapeStr($value);
|
if(!$database->isOperator($operator)) $operator = '=';
|
||||||
$_sql .= "AND $f$operator'$value' ";
|
if(count($values) > 1) {
|
||||||
|
$ors = array();
|
||||||
|
foreach($values as $v) {
|
||||||
|
$ors[] = "$table.$f$operator:cnt$cnt";
|
||||||
|
$binds["cnt$cnt"] = $v;
|
||||||
|
$cnt++;
|
||||||
|
}
|
||||||
|
$wheres[] = '(' . implode(' OR ', $ors) . ')';
|
||||||
|
} else {
|
||||||
|
$wheres[] = "$table.$f$operator:cnt$cnt";
|
||||||
|
$binds["cnt$cnt"] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if($f == 'text' || $f == 'data') {
|
||||||
|
$f = 'data';
|
||||||
|
foreach(array($selectQuery, $countQuery) as $q) {
|
||||||
|
$fulltext = new DatabaseQuerySelectFulltext($q);
|
||||||
|
$this->wire($fulltext);
|
||||||
|
$fulltext->match($table, $f, $operator, $value);
|
||||||
|
}
|
||||||
|
} else if(strpos($f, 'page_') === 0) {
|
||||||
|
list($f, $fieldName) = explode('_', $f, 2);
|
||||||
|
if($f) {} // ignore
|
||||||
|
if(strpos($fieldName, '.')) {
|
||||||
|
list($fieldName, $colName) = explode('.', $fieldName);
|
||||||
|
$colName = $database->escapeCol($colName);
|
||||||
|
} else {
|
||||||
|
$colName = 'data';
|
||||||
|
}
|
||||||
|
/** @var Field $field */
|
||||||
|
$field = $this->wire('fields')->get($fieldName);
|
||||||
|
if(!$field) continue;
|
||||||
|
$fieldTable = $field->getTable();
|
||||||
|
if(!$database->isOperator($operator)) $operator = '=';
|
||||||
|
if(count($values) > 1) {
|
||||||
|
$ors = array();
|
||||||
|
foreach($values as $v) {
|
||||||
|
$ft = $fieldTable . $cnt;
|
||||||
|
$leftJoins[] = "$fieldTable AS $ft ON $ft.pages_id=$table.pages_id AND $ft.$colName$operator:cnt$cnt";
|
||||||
|
$binds["cnt$cnt"] = $v;
|
||||||
|
$ors[] = "$ft.$colName IS NOT NULL";
|
||||||
|
$cnt++;
|
||||||
|
}
|
||||||
|
$wheres[] = '(' . implode(' OR ', $ors) . ')';
|
||||||
|
} else {
|
||||||
|
$ft = $fieldTable . $cnt;
|
||||||
|
$joins[] = "$fieldTable AS $ft ON $ft.pages_id=$table.pages_id AND $ft.$colName$operator:cnt$cnt";
|
||||||
|
$binds["cnt$cnt"] = $value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= $_sql;
|
|
||||||
$sqlCount .= $_sql;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= "ORDER BY $sort " . ($desc ? "DESC" : "ASC") . " ";
|
foreach($wheres as $where) {
|
||||||
$sql .= "LIMIT $start, $limit";
|
$selectQuery->where($where);
|
||||||
|
$countQuery->where($where);
|
||||||
|
}
|
||||||
|
foreach($joins as $join) {
|
||||||
|
$selectQuery->join($join);
|
||||||
|
$countQuery->join($join);
|
||||||
|
}
|
||||||
|
foreach($leftJoins as $leftJoin) {
|
||||||
|
$selectQuery->leftjoin($leftJoin);
|
||||||
|
$countQuery->leftjoin($leftJoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($sorts)) $sorts[] = "$table.created DESC";
|
||||||
|
|
||||||
|
$selectQuery->orderby(implode(',', $sorts));
|
||||||
|
$selectQuery->limit("$start,$limit");
|
||||||
|
|
||||||
$comments = $this->wire(new CommentArray());
|
$comments = $this->wire(new CommentArray());
|
||||||
$comments->setField($field);
|
$comments->setField($field);
|
||||||
$comments->setStart($start);
|
$comments->setStart($start);
|
||||||
$comments->setLimit($limit);
|
$comments->setLimit($limit);
|
||||||
|
|
||||||
|
$sql = $selectQuery->getQuery();
|
||||||
$query = $database->prepare($sql);
|
$query = $database->prepare($sql);
|
||||||
|
foreach($binds as $key => $value) {
|
||||||
|
$query->bindValue(":$key", $value);
|
||||||
|
}
|
||||||
$query->execute();
|
$query->execute();
|
||||||
$commentPages = array();
|
$commentPages = array();
|
||||||
|
|
||||||
@@ -1087,7 +1206,10 @@ class FieldtypeComments extends FieldtypeMulti {
|
|||||||
$comment->setIsLoaded(true);
|
$comment->setIsLoaded(true);
|
||||||
}
|
}
|
||||||
$query->closeCursor();
|
$query->closeCursor();
|
||||||
$query = $database->prepare($sqlCount);
|
$query = $database->prepare($countQuery->getQuery());
|
||||||
|
foreach($binds as $key => $value) {
|
||||||
|
$query->bindValue(":$key", $value);
|
||||||
|
}
|
||||||
$query->execute();
|
$query->execute();
|
||||||
list($total) = $query->fetch(\PDO::FETCH_NUM);
|
list($total) = $query->fetch(\PDO::FETCH_NUM);
|
||||||
$comments->resetTrackChanges();
|
$comments->resetTrackChanges();
|
||||||
|
@@ -39,7 +39,7 @@ class MarkupPageArray extends WireData implements Module {
|
|||||||
|
|
||||||
public function init() {
|
public function init() {
|
||||||
$this->addHook("PageArray::render", $this, "renderPageArray");
|
$this->addHook("PageArray::render", $this, "renderPageArray");
|
||||||
$this->addHook("PageArray::renderPager", $this, "renderPager");
|
$this->addHook("PaginatedArray::renderPager", $this, "renderPager");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user