Skip to content

Commit

Permalink
First working version.
Browse files Browse the repository at this point in the history
  • Loading branch information
Szymon Olewniczak committed Mar 26, 2019
1 parent ae80df3 commit 000e80f
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 4 deletions.
3 changes: 2 additions & 1 deletion action.php
Expand Up @@ -23,7 +23,7 @@ class action_plugin_structjoin extends DokuWiki_Action_Plugin
*/
public function register(Doku_Event_Handler $controller)
{
$controller->register_hook('PLUGIN_STRUCT_TYPECLASS_INIT', 'FIXME', $this, 'handle_plugin_struct_typeclass_init');
$controller->register_hook('PLUGIN_STRUCT_TYPECLASS_INIT', 'BEFORE', $this, 'handle_plugin_struct_typeclass_init');

}

Expand All @@ -40,6 +40,7 @@ public function register(Doku_Event_Handler $controller)
*/
public function handle_plugin_struct_typeclass_init(Doku_Event $event, $param)
{
$event->data['Join'] = \dokuwiki\plugin\structjoin\types\Join::class;
}

}
Expand Down
2 changes: 1 addition & 1 deletion plugin.info.txt
@@ -1,7 +1,7 @@
base structjoin
author Szymon Olewniczak
email it@rid.pl
date 2019-03-22
date 2019-03-26
name structjoin plugin
desc Introduces new struct type that allows perform inner joins between schemas
url https://www.dokuwiki.org/plugin:structjoin
189 changes: 187 additions & 2 deletions types/Join.php
@@ -1,8 +1,193 @@
<?php
namespace dokuwiki\plugin\structjoin\types;

use dokuwiki\plugin\struct\types\AbstractMultiBaseType;
use dokuwiki\plugin\struct\meta\QueryBuilder;
use dokuwiki\plugin\struct\meta\QueryBuilderWhere;
use dokuwiki\plugin\struct\meta\StructException;
use dokuwiki\plugin\struct\types\AbstractBaseType;
use dokuwiki\plugin\struct\types\Lookup;
use ReflectionClass;

class Join extends AbstractMultiBaseType {
class Join extends Lookup {

public function valueEditor($name, $rawvalue, $htmlID)
{
return "<strong>{$this->config['schema']}.{$this->config['field']}</strong>";
}

/**
* Render using linked field
*
* @param int|string $value
* @param \Doku_Renderer $R
* @param string $mode
* @return bool
*/
public function renderValue($value, \Doku_Renderer $R, $mode) {
$column = $this->getLookupColumn();
if(!$column) return false;
return $column->getType()->renderValue($value, $R, $mode);
}

/**
* Render using linked field
*
* @param \int[]|\string[] $values
* @param \Doku_Renderer $R
* @param string $mode
* @return bool
*/
public function renderMultiValue($values, \Doku_Renderer $R, $mode) {
$column = $this->getLookupColumn();
if(!$column) return false;
return $column->getType()->renderMultiValue($values, $R, $mode);
}

/**
* @param string $value
* @return string
*/
public function rawValue($value) {
return $value;
}

/**
* @param string $value
* @return string
*/
public function displayValue($value) {
$column = $this->getLookupColumn();
if($column) {
return $column->getType()->displayValue($value);
} else {
return '';
}
}

/**
* This is the value to be used as argument to a filter for another column.
*
* In a sense this is the counterpart to the @see filter() function
*
* @param string $value
*
* @return string
*/
public function compareValue($value) {
$column = $this->getLookupColumn();
if($column) {
return $column->getType()->rawValue($value);
} else {
return '';
}
}

/**
* Merge with lookup table
*
* @param QueryBuilder $QB
* @param string $tablealias
* @param string $colname
* @param string $alias
* @throws \ReflectionException
*/
public function select(QueryBuilder $QB, $tablealias, $colname, $alias) {
$column = $this->getLookupColumn();
if(!$column) {
AbstractBaseType::select($QB, $tablealias, $colname, $alias);
return;
}

$rightalias = $this->findRightAlias($QB);
if (!$rightalias) {
throw new StructException("Select Lookup column to use Join.");
}

$field = $column->getColName();
$column->getType()->select($QB, $rightalias, $field, $alias);
}

/**
* @param QueryBuilder $QB
* @return false|int|string
* @throws \ReflectionException
*/
protected function findRightAlias(QueryBuilder $QB) {
$from = $this->getProtectedPropertyFromQB($QB, 'from');
$leftJoinAliases = array_filter(array_map(function($from) {
if (preg_match('/^LEFT OUTER JOIN data_([^\s]*)/', $from, $matches)) {
return $matches[1];
}
return false;
}, $from));

return array_search($this->config['schema'], $leftJoinAliases);
}

/**
* @param QueryBuilder $QB
* @param $property
* @return mixed
* @throws \ReflectionException
*/
protected function getProtectedPropertyFromQB(QueryBuilder $QB, $property) {
$reflectionClass = new ReflectionClass(QueryBuilder::class);
$reflectionProperty = $reflectionClass->getProperty($property);
$reflectionProperty->setAccessible(true);

return $reflectionProperty->getValue($QB);
}

/**
* Compare against lookup table
*
* @param QueryBuilderWhere $add
* @param string $tablealias
* @param string $colname
* @param string $comp
* @param string|\string[] $value
* @param string $op
*/
public function filter(QueryBuilderWhere $add, $tablealias, $colname, $comp, $value, $op) {
$schema = 'data_' . $this->config['schema'];
$column = $this->getLookupColumn();
if(!$column) {
AbstractBaseType::filter($add, $tablealias, $colname, $comp, $value, $op);
return;
}
$field = $column->getColName();

// compare against lookup field
$QB = $add->getQB();
$rightalias = $this->findRightAlias($QB);
if (!$rightalias) {
throw new StructException("Select Lookup column to use Join.");
}
$column->getType()->filter($add, $rightalias, $field, $comp, $value, $op);
}

/**
* Sort by lookup table
*
* @param QueryBuilder $QB
* @param string $tablealias
* @param string $colname
* @param string $order
* @throws \ReflectionException
*/
public function sort(QueryBuilder $QB, $tablealias, $colname, $order) {
$schema = 'data_' . $this->config['schema'];
$column = $this->getLookupColumn();
if(!$column) {
AbstractBaseType::sort($QB, $tablealias, $colname, $order);
return;
}
$field = $column->getColName();

$rightalias = $this->findRightAlias($QB);
if (!$rightalias) {
throw new StructException("Select Lookup column to use Join.");
}
$column->getType()->sort($QB, $rightalias, $field, $order);
}
}

0 comments on commit 000e80f

Please sign in to comment.