*/
/**
* Class syntax_plugin_data_related
*/
class syntax_plugin_data_related extends syntax_plugin_data_table
{
/**
* Connect pattern to lexer
*/
public function connectTo($mode)
{
$this->Lexer->addSpecialPattern(
'----+ *datarelated(?: [ a-zA-Z0-9_]*)?-+\n.*?\n----+',
$mode,
'plugin_data_related'
);
}
/**
* Handles the actual output creation.
*
* @param string $format output format being rendered
* @param Doku_Renderer $renderer the current renderer object
* @param array $data data created by handler()
* @return boolean rendered correctly? (however, returned value is not used at the moment)
*/
public function render($format, Doku_Renderer $renderer, $data)
{
if ($format != 'xhtml') return false;
if (is_null($data)) return false;
if (!$this->dthlp->ready()) return false;
$sqlite = $this->dthlp->getDB();
if (!$sqlite) return false;
if (!$data['sql']) return true; // sql build
$this->dthlp->replacePlaceholdersInSQL($data);
$rows = $sqlite->queryAll($data['sql']);
if (!$rows) return true; // no rows matched
$renderer->doc .= '
';
$renderer->doc .= '- ' . htmlspecialchars($data['title']) . '
';
$renderer->doc .= '- ';
$renderer->listu_open();
foreach ($rows as $row) {
$renderer->listitem_open(1);
$renderer->internallink($row['page']);
$renderer->listitem_close();
}
$renderer->listu_close();
$renderer->doc .= '
';
$renderer->doc .= '
';
return true;
}
/**
* Builds the SQL query from the given data
*/
public function buildSQL(&$data, $id = null)
{
global $ID;
if (is_null($id)) $id = $ID;
$cnt = 1;
$tables = [];
$cond = [];
$from = '';
$where = '';
$sqlite = $this->dthlp->getDB();
if (!$sqlite) return false;
// prepare the columns to match against
$found = false;
foreach (array_keys($data['cols']) as $col) {
// get values for current page:
$sql = "SELECT A.value
FROM data A, pages B
WHERE key = ?
AND A.pid = B.pid
AND B.page = ?";
$rows = $sqlite->queryAll($sql, $col, $id);
if (!$rows) continue; // no values? ignore the column.
$values = array_column($rows, 'value');
$found = true;
$in = implode(',', array_map([$sqlite->getPdo(), 'quote'], $values));
$cond[] = " ( T1.key = " . $sqlite->getPdo()->quote($col) .
" AND T1.value IN (" . $in . ") )\n";
}
$where .= ' AND (' . implode(' OR ', $cond) . ') ';
// any tags to compare?
if (!$found) return false;
// prepare sorting
if ($data['sort'][0]) {
$col = $data['sort'][0];
if ($col == '%pageid%') {
$order = ', pages.page ' . $data['sort'][1];
} elseif ($col == '%title%') {
$order = ', pages.title ' . $data['sort'][1];
} else {
// sort by hidden column?
if (!$tables[$col]) {
$tables[$col] = 'T' . (++$cnt);
$from .= ' LEFT JOIN data AS ' . $tables[$col] . ' ON ' . $tables[$col] . '.pid = pages.pid';
$from .= ' AND ' . $tables[$col] . ".key = " . $sqlite->getPdo()->quote($col);
}
$order = ', ' . $tables[$col] . '.value ' . $data['sort'][1];
}
} else {
$order = ', pages.page';
}
// add filters
if (is_array($data['filter']) && count($data['filter'])) {
$where .= ' AND ( 1=1 ';
foreach ($data['filter'] as $filter) {
// note: value is already escaped
$col = $filter['key'];
$closecompare = ($filter['compare'] == 'IN(' ? ')' : '');
if ($col == '%pageid%') {
$where .= " " . $filter['logic'] . " pages.page "
. $filter['compare'] . " "
. $filter['value'] . $closecompare;
} elseif ($col == '%title%') {
$where .= " "
. $filter['logic'] . " pages.title "
. $filter['compare'] . " "
. $filter['value'] . $closecompare;
} else {
// filter by hidden column?
if (!$tables[$col]) {
$tables[$col] = 'T' . (++$cnt);
$from .= ' LEFT JOIN data AS ' . $tables[$col] . ' ON ' . $tables[$col] . '.pid = pages.pid';
$from .= ' AND ' . $tables[$col] . ".key = " . $sqlite->getPdo()->quote($col);
}
$where .= ' ' . $filter['logic'] . ' ' . $tables[$col] . '.value ' . $filter['compare'] .
" " . $filter['value'] . $closecompare;
}
}
$where .= ' ) ';
}
// build the query
$sql = "SELECT pages.pid, pages.page as page, pages.title as title, COUNT(*) as rel
FROM pages, data as T1 $from
WHERE pages.pid = T1.pid
AND pages.page != " . $sqlite->getPdo()->quote($id) . "
$where
GROUP BY pages.pid
ORDER BY rel DESC$order";
// limit
if ($data['limit']) {
$sql .= ' LIMIT ' . ($data['limit']);
}
return $sql;
}
}