*/
namespace dokuwiki\plugin\structprogress\types;
use dokuwiki\plugin\struct\meta\QueryBuilder;
use dokuwiki\plugin\struct\meta\QueryBuilderWhere;
use dokuwiki\plugin\struct\meta\ValidationException;
use dokuwiki\plugin\struct\types\AbstractMultiBaseType;
class Progress extends AbstractMultiBaseType
{
protected $config = array(
'max' => '100',
'prefix' => '',
'postfix' => '',
'type' => 'default',
);
/**
* @inheritDoc
*/
public function validate($rawvalue)
{
$rawvalue = parent::validate($rawvalue);
$rawvalue = str_replace(',', '.', $rawvalue); // we accept both
$minvalue = 0;
$maxvalue = 100;
if ($this->config['max'] !== '' && floatval($this->config['max']) > 0) {
$maxvalue = floatval($this->config['max']);
}
if ((string)$rawvalue != (string)floatval($rawvalue)) {
throw new ValidationException('Decimal needed');
}
if (floatval($rawvalue) < $minvalue) {
throw new ValidationException('Decimal min', $minvalue);
}
if ($maxvalue !== 0 && floatval($rawvalue) > $maxvalue) {
throw new ValidationException('Decimal max', $maxvalue);
}
return $rawvalue;
}
/**
* @inheritDoc
*/
public function renderValue($value, \Doku_Renderer $R, $mode)
{
if ($mode == 'xhtml') {
$maxvalue = 100;
if ($this->config['max'] !== '' && floatval($this->config['max']) > 0) {
$maxvalue = floatval($this->config['max']);
}
$progress = 100 * $value / $maxvalue;
$progress = (int)($progress > 0) ? (($progress > 100) ? 100 : $progress) : 0; // Prevents overflow of the bar for imported data (<0 || >max)
$R->doc .= '
';
$R->doc .= '
';
$R->doc .= '
' . hsc($this->config['prefix'] . $value . $this->config['postfix']) . '
';
$R->doc .= '
';
$R->doc .= '
';
} else {
$R->cdata($value);
}
return true;
}
/**
* @inheritDoc
*/
public function renderMultiValue($values, \Doku_Renderer $R, $mode)
{
if ($mode == 'xhtml') {
$R->doc .= '';
foreach ($values as $value) {
$this->renderValue($value, $R, $mode);
}
$R->doc .= '
';
} else {
$R->cdata(join(', ', $values));
}
return true;
}
/**
* Works like number_format but keeps the decimals as is
*
* @link http://php.net/manual/en/function.number-format.php#91047
* @author info at daniel-marschall dot de
* @param float $number
* @param string $dec_point
* @param string $thousands_sep
* @return string
*/
protected function formatWithoutRounding($number, $dec_point, $thousands_sep)
{
$was_neg = $number < 0; // Because +0 == -0
$tmp = explode('.', $number);
$out = number_format(abs(floatval($tmp[0])), 0, $dec_point, $thousands_sep);
if (isset($tmp[1])) {
$out .= $dec_point . $tmp[1];
}
if ($was_neg) {
$out = "-$out";
}
return $out;
}
/**
* Decimals need to be casted to the proper type for sorting
*
* @param QueryBuilder $QB
* @param string $tablealias
* @param string $colname
* @param string $order
*/
public function sort(QueryBuilder $QB, $tablealias, $colname, $order)
{
$QB->addOrderBy("CAST($tablealias.$colname AS DECIMAL) $order");
}
/**
* Decimals need to be casted to proper type for comparison
*
* @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)
{
$add = $add->where($op); // open a subgroup
$add->where('AND', "$tablealias.$colname != ''"); // make sure the field isn't empty
$op = 'AND';
/** @var QueryBuilderWhere $add Where additionional queries are added to */
if (is_array($value)) {
$add = $add->where($op); // sub where group
$op = 'OR';
}
foreach ((array)$value as $item) {
$pl = $add->getQB()->addValue($item);
$add->where($op, "CAST($tablealias.$colname AS DECIMAL) $comp CAST($pl AS DECIMAL)");
}
}
/**
* Only exact matches for numbers
*
* @return string
*/
public function getDefaultComparator()
{
return '=';
}
}