'one, two, three', 'schema' => '', 'field' => '' ); /** @var Schema */ protected $schema = null; /** @var Column */ protected $column = null; /** * Dropdown constructor. * * @param array|null $config * @param string $label * @param bool $ismulti * @param int $tid */ public function __construct($config = null, $label = '', $ismulti = false, $tid = 0) { global $conf; parent::__construct($config, $label, $ismulti, $tid); $this->config['schema'] = Schema::cleanTableName($this->config['schema']); if($this->usesLookup()) { $this->schema = new Schema($this->config['schema']); if(!$this->schema->getId()) { // schema does not exist msg(sprintf('Schema %s does not exist', $this->config['schema']), -1); $this->schema = null; $this->config['schema'] = ''; return; } // apply language replacement $field = str_replace('$LANG', $conf['lang'], $this->config['field']); $this->column = $this->schema->findColumn($field); if(!$this->column) { $field = str_replace('$LANG', 'en', $this->config['field']); // fallback to en $this->column = $this->schema->findColumn($field); } if(!$this->column) { // field does not exist msg(sprintf('Field %s.%s does not exist', $this->config['schema'], $this->config['field']), -1); $this->column = null; $this->config['field'] = ''; return; } if($this->column->isMulti()) { // field is multi msg(sprintf('Field %s.%s is a multi field - not allowed for lookup', $this->config['schema'], $this->config['field']), -1); $this->column = null; $this->config['field'] = ''; return; } } } /** * @return bool is this dropdown configured to use a lookup? */ protected function usesLookup() { return !blank($this->config['schema']) && !blank($this->config['field']); } /** * Creates the options array * * @return array */ protected function getOptions() { if($this->usesLookup()) { $options = $this->loadLookupData(); } else { $options = explode(',', $this->config['values']); $options = array_map('trim', $options); $options = array_filter($options); array_unshift($options, ''); $options = array_combine($options, $options); } return $options; } /** * Loads all available lookup values * * @return array */ protected function loadLookupData() { $schema = $this->schema->getTable(); $field = $this->column->getLabel(); $search = new Search(); $search->addSchema($schema); $search->addColumn($field); $search->addSort($field); $result = $search->execute(); $pids = $search->getPids(); $len = count($result); /** @var Value[][] $result */ $options = array('' => ''); for($i = 0; $i < $len; $i++) { $options[$pids[$i]] = $result[$i][0]->getDisplayValue(); } return $options; } /** * 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) { if(!$this->usesLookup()) { return parent::renderValue($value, $R, $mode); } else { list(, $value) = json_decode($value); return $this->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) { if(!$this->usesLookup()) { return parent::renderMultiValue($values, $R, $mode); } else { $values = array_map( function ($val) { list(, $val) = json_decode($val); return $val; }, $values ); return $this->column->getType()->renderMultiValue($values, $R, $mode); } } /** * A Dropdown with a single value to pick * * @param string $name * @param string $rawvalue * @return string */ public function valueEditor($name, $rawvalue) { $class = 'struct_' . strtolower($this->getClass()); $name = hsc($name); $html = "'; return $html; } /** * A dropdown that allows to pick multiple values * * @param string $name * @param \string[] $rawvalues * @return string */ public function multiValueEditor($name, $rawvalues) { $class = 'struct_' . strtolower($this->getClass()); $name = hsc($name); $html = " '; $html .= '' . $this->getLang('multidropdown') . ''; return $html; } /** * @param string $value * @return string */ public function rawValue($value) { if($this->usesLookup()) { list($value) = json_decode($value); } return $value; } /** * @param string $value * @return string */ public function displayValue($value) { if($this->usesLookup()) { list(, $value) = json_decode($value); $value = $this->column->getType()->displayValue($value); } return $value; } /** * Merge with lookup table * * @param QueryBuilder $QB * @param string $tablealias * @param string $colname * @param string $alias */ public function select(QueryBuilder $QB, $tablealias, $colname, $alias) { if(!$this->usesLookup()) { parent::select($QB, $tablealias, $colname, $alias); return; } $schema = 'data_' . $this->schema->getTable(); $field = $this->column->getColName(); $rightalias = $QB->generateTableAlias(); $QB->addLeftJoin($tablealias, $schema, $rightalias, "$tablealias.$colname = $rightalias.pid"); $this->column->getType()->select($QB, $rightalias, $field, $alias); $sql = $QB->getSelectStatement($alias); $QB->addSelectStatement("JSON($tablealias.$colname, $sql)", $alias); } /** * Compare against lookup table * * @param QueryBuilder $QB * @param string $tablealias * @param string $colname * @param string $comp * @param string|\string[] $value * @param string $op */ public function filter(QueryBuilder $QB, $tablealias, $colname, $comp, $value, $op) { if(!$this->usesLookup()) { parent::filter($QB, $tablealias, $colname, $comp, $value, $op); return; } $schema = 'data_' . $this->schema->getTable(); $field = $this->column->getColName(); // compare against lookup field $rightalias = $QB->generateTableAlias(); $QB->addLeftJoin($tablealias, $schema, $rightalias, "$tablealias.$colname = $rightalias.pid"); $this->column->getType()->filter($QB, $rightalias, $field, $comp, $value, $op); } /** * Sort by lookup table * * @param QueryBuilder $QB * @param string $tablealias * @param string $colname * @param string $order */ public function sort(QueryBuilder $QB, $tablealias, $colname, $order) { if(!$this->usesLookup()) { parent::sort($QB, $tablealias, $colname, $order); return; } $schema = 'data_' . $this->schema->getTable(); $field = $this->column->getColName(); $rightalias = $QB->generateTableAlias(); $QB->addLeftJoin($tablealias, $schema, $rightalias, "$tablealias.$colname = $rightalias.pid"); $this->column->getType()->sort($QB, $rightalias, $field, $order); } }