*/ class twIf_Widget_Table extends twIf_Object_Access { const IMAGE_PATH = '/images'; const ERROR_INVALID_DATA = -2001; // {{{ getImagePath /** * Retrive path where we *sould* **/ private static function getImagePath () { if (defined ('TWIF_IMAGE_PATH')) return TWIF_IMAGE_PATH; return self::IMAGE_PATH; } // }}} // {{{ formatOutput /** * Try to put an input-value into the right output-format * * @param mixed $Value Input-Value to format * @param string $Format Output-Format * @param mixed $Default (optional) Unused * @param bool $Table (optional) Output as table-cell * @param bool $Wrap (optional) Allow Word-Wrapping * @param string $Style (optional) Add these Style-Flags * * @access private * @return string */ protected function formatOutput ($Value, $Format, $Default = '', $Table = true, $Wrap = false, $Style = '', $Prefix = '', $Suffix = '') { if (is_array ($Value) && !$Table) { $buf = ''; foreach ($Value as $V) $buf .= '* ' . parent::formatOutput ($V, $Format, $Default, $Prefix, $Suffix) . "\n"; return rtrim ($buf); } return parent::formatOutput ($Value, $Format, $Default, $Prefix, $Suffix); } // }}} // {{{ generateTable /** * Generate a table from an array filled with objects * * @param array $Objects Array with objects * @param array $Fields (optional) Field-Definition for table * @param array $Options (optional) Additional Option-Fields for table * @param array $Highlight (optional) Conditions to highlight records * @param bool $addEnableToggle (optional) Add buttons for isEnabled()-Support * @param bool $addSelectToggle (optional) Allow to select some items * @param string $baseURL (optional) Use this URL for Linking * @param array $sortParams (optional) * @param string $GroupBy (optional) * @param bool $showHeader (optional) * @param callback $selectFunc (optional) * * @access public * @return string * * @todo Implement Auto-Generation of Field-Def */ public function generateTable (&$Objects, $Fields = array (), $Options = array (), $Highlight = array (), $addEnableToggle = false, $addSelectToggle = false, $baseURL = '', $sortParams = null, $GroupBy = null, $showHeader = true, $selectFunc = null) { // Validate input-values if (!is_array ($Objects) && !($Objects instanceof Traversable)) $Objects = array (); // Autogenerate Field-Data if (!is_array ($Fields) || (count ($Fields) < 1)) # TODO: Implement this $Fields = array (); // Pick the first object $First = null; foreach ($Objects as $First) break; // Post-process fields $myFields = array (); foreach ($Fields as $ID=>$Definition) if (is_array ($Definition)) { if (isset ($Definition ['Field'])) { $newDef = array ( 'Caption' => (isset ($Definition ['Caption']) ? $Definition ['Caption'] : $ID), 'Read' => $Definition ['Field'], 'ReadParams' => (isset ($Definition ['Params']) ? $Definition ['Params'] : array ()), 'Enum' => (isset ($Definition ['Enum']) ? $Definition ['Enum'] : null), 'Type' => (isset ($Definition ['Output']) ? $Definition ['Output'] : twIf_Widget_Control::TYPE_TEXT), 'Class' => ltrim ((isset ($Definition ['Class']) ? $Definition ['Class'] : '') . ($ID == $GroupBy ? ' twIfTableGroup' : '')), 'OrderKey' => (isset ($Definition ['OrderKey']) ? $Definition ['OrderKey'] : null), 'Multiplier' => (isset ($Definition ['Multiplier']) ? $Definition ['Multiplier'] : 1), 'Total' => (isset ($Definition ['Total']) ? $Definition ['Total'] : false), 'Wrap' => (isset ($Definition ['Wrap']) ? $Definition ['Wrap'] : false), 'PrintF' => (isset ($Definition ['PrintF']) ? $Definition ['PrintF'] : null), 'Filter' => (isset ($Definition ['Filter']) ? $Definition ['Filter'] : null), 'Prefix' => (isset ($Definition ['Prefix']) ? $Definition ['Prefix'] : ''), 'Suffix' => (isset ($Definition ['Suffix']) ? $Definition ['Suffix'] : ''), ); if (is_array ($newDef ['Enum'])) $newDef ['Type'] = twIf_Widget_Control::TYPE_ENUM; # Fields from Options # Link # Target # Enable # Confirm $myFields [$newDef ['Caption']] = parent::parseFieldDef ($Definition ['Field'], $newDef, $First, 0); } else { $myFields [(isset ($Definition ['Caption']) ? $Definition ['Caption'] : $ID)] = parent::parseFieldDef ($ID, $Definition, $First, 0); } } else $myFields [$ID] = parent::parseFieldDef ($Definition, array ('Caption' => $ID, 'Read' => $Definition), $First, 0); // Collect all data $FieldTotal = array (); $Rows = array (); if ($addSelectToggle && $selectFunc) $selectDefinition = parent::parseFieldDef ($selectFunc, array ('Read' => $selectFunc), $First, 0, true); else $selectDefinition = null; foreach ($Objects as $Object) { // Check wheter to enable/disable this item if ($addEnableToggle && isset ($_REQUEST ['enObj']) && (md5 ($Object->getID ()) == $_REQUEST ['enObj'])) $Object->isEnabled ($_REQUEST ['tok'] % 2 == 1); // Collect all data for row $Row = array ($Object); if ($addSelectToggle) { if (is_array ($selectDefinition)) $Row [] = parent::getFieldValue ($Object, $selectDefinition); else $Row [] = false; } foreach ($myFields as $ID=>$Definition) { // Change callback on read-func if (is_array ($Definition ['Read'])) $Definition ['Read'][0] = $Object; // Retrive value from object $Value = parent::getFieldValue ($Object, $Definition); // Apply Enumeration if there is one $Value = self::handleEnum ($Definition, $Value); // Handle multiplier $Value = self::handleMultiplier ($Definition, $Object, $Value); // Increase the counter (if neccessary) if ($Definition ['Total']) { if (!isset ($FieldTotal [$ID])) $FieldTotal [$ID] = 0; $FieldTotal [$ID] += $Value; } // Append the value to current row $Row [$ID] = self::formatOutput ( $Value, $Definition ['Type'], '', !defined ('TWIF_ON_TERMINAL'), !(!isset ($Definition ['Wrap']) || ($Definition ['Wrap'] != true)), '', $Definition ['Prefix'], $Definition ['Suffix'] ); } // Append this row to our collection $Rows [] = $Row; } // Regroup the rows if (($GroupBy !== null) && isset ($myFields [$GroupBy])) { $Groups = array (); foreach ($Rows as $Row) { $gn = $Row [$Group]; if (!isset ($Groups [$gn])) $Groups [$gn] = array (); $Groups [$gn][] = $Row; } $Rows = array (); foreach ($Groups as $gn=>$Items) foreach ($Items as $Item) $Rows [] = $Item; } if (defined ('TWIF_ON_TERMINAL')) return self::generateTerminalTable ($myFields, $Rows, $FieldTotal, $GroupBy, $addSelectToggle, $showHeader); return self::generateWebTable ($myFields, $Rows, $Options, $FieldTotal, $baseURL, $sortParams, $addSelectToggle, $addEnableToggle, $GroupBy, $showHeader, $Highlight); } // }}} // {{{ generateTerminalTable /** * Generate a text-only table for a terminal * * @access private * @return string **/ private function generateTerminalTable ($myFields, $Rows, $FieldTotal, $Group, $addSelectToggle, $showHeader) { // Retrive terminal size exec ('/bin/stty size', $rd, $rc); if ($rc != 0) return false; $termSize = explode (' ', $rd [0]); $Height = intval ($termSize [0]); $Width = intval ($termSize [1]) - count ($myFields) - 1; // Find field-length $tWidths = array (); $tWidth = 0; $tHeights = array (); if ($addSelectToggle) $s = 2; else $s = 1; foreach ($Rows as $rid=>$Row) { $tHeights [$rid] = 1; $c = 0; foreach ($Row as $idx=>$Cell) { if ($c++ < $s) continue; if (!isset ($tWidths [$idx])) $tWidths [$idx] = 0; if (strpos ($Cell, "\n") === false) $w = strlen ($Cell); else { $L = explode ("\n", $Cell); $w = 0; if (count ($L) > $tHeights [$rid]) $tHeights [$rid] = count ($L); foreach ($L as $l) if (strlen ($l) > $w) $w = strlen ($l); } if ($w > $tWidths [$idx]) { $tWidth += $w - $tWidths [$idx]; $tWidths [$idx] = $w; } } } // Adjuist values $Overhead = $Width - $tWidth; $avgAdd = $Overhead / count ($myFields); $minAdd = floor ($avgAdd); $curAdd = 0; foreach ($tWidths as $idx=>$w) { $curAdd += $avgAdd; $tWidths [$idx] += $minAdd; if (round ($curAdd) > $curAdd) $tWidths [$idx]++; } // Initialize output $buf = "\n"; // Output the header $c = 0; $buf .= ' '; $b2 = ' '; foreach ($myFields as $Caption=>$Data) { $w = $tWidths [$Caption]; $Caption = twIf_i18n::getText (!isset ($Data ['Caption']) ? $Caption : $Data ['Caption']); if ($c++ > 0) { if ($showHeader) $buf .= '|'; $b2 .= '+'; } if ($showHeader) $buf .= self::terminalCell ($Caption, $w); $b2 .= str_repeat ('-', $w); } $buf .= "\n" . $b2 . "\n"; // Output all rows $lG = null; foreach ($Rows as $rid=>$Row) { $Object = array_shift ($Row); if ($addSelectToggle) $isSelected = array_shift ($Row); for ($i = 0; $i < $tHeights [$rid]; $i++) { $c = 0; $buf .= ' '; foreach ($Row as $col=>$Cell) { if ($c++ > 0) $buf .= '|'; $buf .= self::terminalCell ($Cell, $tWidths [$col], $i); } $buf .= "\n"; } } $buf .= "\n"; return $buf; } // }}} // {{{ terminalCell /** * Prepare a string to be outputed on a terminal-table * * @param string $Content * @param int $Width * @param int $Row (optional) * * @access private * @return string **/ private static function terminalCell ($Content, $Width, $Row = 0) { if (($p = strpos ($Content, "\n")) !== false) { if ($Row == 0) $Content = rtrim (substr ($Content, 0, $p)); else { $buf = explode ("\n", $Content); $Content = rtrim ($buf [$Row]); } } elseif ($Row != 0) $Content = ''; $l = strlen ($Content); if ($Width > $l + 1) return ' ' . $Content . str_repeat (' ', $Width - $l - 1); elseif ($Width == $l + 1) return ' ' . $Content; else return ' ' . substr ($Content, 0, $Width - 1); } // }}} private function generateCell ($Definition, $Content, $RowSpanOpen = false) { return '' . ($Definition ["Wrap"] ? nl2br ($Content) : $Content) . ''; } // {{{ generateWebTable /** * Output HTML-based table * * @access private * @return string **/ private function generateWebTable ($myFields, $Rows, $Options, $FieldTotal, $baseURL, $sortParams, $addSelectToggle, $addEnableToggle, $Group, $showHeader, $Highlight) { // Do the web-stuff $imgPath = self::getImagePath (); if (strpos ($baseURL, '?') === false) $baseURL .= '?'; else $baseURL .= '&'; if (!is_array ($sortParams) || !isset ($sortParams ['Enable'])) $sortParams = array ('Enable' => false); // Start the table $buf = "\n"; // Output the header if ($showHeader) { $buf .= ''; if ($addSelectToggle) $buf .= ''; } else $buf .= '' . twIf_i18n::getText (!isset ($Data ['Caption']) ? $Caption : $Data ['Caption']) . ''; } // Append space for options and close header $buf .= (($c = count ($Options)) > 0 ? '\n"; } // Output "no data available" if neccessary if (count ($Rows) == 0) $buf .= '\n"; $gP = 0; $gV = null; $gC = 0; $i = 0; // Fill the table with rows foreach ($Rows as $Row) { // Load the associated object from row $Object = array_shift ($Row); // Check wheter to highlight row $doHighlight = false; if (is_array ($Highlight)) foreach ($Highlight as $Field=>$Rules) { $Value = self::getFieldValueSimple ($Object, $Field); if (!is_array ($Rules)) $Rules = array ($Rules); foreach ($Rules as $Rule) { switch ($Rule [0]) { case '<': $doHighlight = (substr ($Rule, 1) > $Value); break; case '>': $doHighlight = (substr ($Rule, 1) < $Value); break; default: $doHighlight = ($Rule == $Value); break; } if ($doHighlight) break; } if ($doHighlight) break; } $id5 = md5 ($Object->getID ()); $rowStart = ''; if ($addSelectToggle) { $isSelected = array_shift ($Row); $rowStart .= ''; } if ($f = $addEnableToggle) $rowStart .= ''; $buf .= $rowStart; foreach ($Row as $col=>$Cell) { if ($op = ($col == $Group)) { if ($gV != $Cell) { if ($gP > 0) { $buf = substr ($buf, 0, $gP) . $gC . substr ($buf, $gP); $buf = substr ($buf, 0, $gP = (strlen ($buf) - strlen ($rowStart))) . '\n" . substr ($buf, $gP); } $gP = strlen ($buf) + 13; # $buf .= self::generateCell ($myFields [$col], $Cell, true); $gC = 1; $gV = $Cell; } else { $gC++; continue; } } if ($f) { $f = false; $Cell = ''; } $buf .= self::generateCell ($myFields [$col], $Cell, $op); } // Output option-fields to current row foreach ($Options as $Caption=>$Data) { if (!is_array($Data)) { $Link = $Data; $Target = '_self'; } else { $Link = $Data ['Link']; $Target = (isset ($Data ['Target']) ? $Data ['Target'] : ''); if (isset ($Data ['Enable'])) { $Enable = (is_array ($Data ['Enable']) ? $Data ['Enable'] : array ($Data ['Enable'])); $doEnable = true; foreach ($Enable as $Name=>$Condition) { if (!is_array ($Condition)) $Condition = array ($Condition); if (is_array ($Condition)) { if (strpos ($Name, '()') > 0) $rc = @call_user_func_array (array (&$Object, substr ($Name, 0, strlen ($Name) - 2)), array ()); else $rc = $Object->$Name; if (!($doEnable = in_array ($rc, $Condition))) break; } } if (!$doEnable) { $buf .= ''; } $buf .= "\n"; unset ($Object); } if (($gP > 0) && ($gC > 1)) $buf = substr ($buf, 0, $gP) . $gC . substr ($buf, $gP); // Check if we have to output some counters if (count ($FieldTotal) > 0) { $buf .= '' . ($addSelectToggle ? '\n"; } // Finish the table $buf .= "
'; if ($addEnableToggle) $buf .= ''; foreach ($myFields as $Caption=>$Data) { if ($sortParams ['Enable'] && (!self::isReadFunction ($Data) || ($Data ['OrderKey'] !== null))) { $sortFieldURL = md5 ($sortField = ($Data ['OrderKey'] !== null ? $Data ['OrderKey'] : $Data ['Read'])); $sortUp = $baseURL . 'twIfsO=D&twIfsF=' . $sortFieldURL; $sortDown = $baseURL . 'twIfsO=A&twIfsF=' . $sortFieldURL; if ($sortParams ['Field'] == $sortField) $sortHead = ($sortParams ['Order'] == 'D' ? $sortDown : $sortUp); else $sortHead = $sortDown; $buf .= '' . '' . twIf_i18n::getText ($Data ['Caption']) . ' '; $buf .= '' . ''; $buf .= '' : '') . "
Keine Daten verfügbar
' . '' . '' . '' . '
'; continue; } } } $Link = self::parseExpression ($Link, $Object, true); $Confirm = ''; if (is_array ($Data) && isset ($Data ['Confirm'])) $Confirm = "onclick=\"return confirm('" . self::parseExpression (twIf_i18n::getText ($Data ['Confirm']), $Object) . "');\" "; $buf .= '' . twIf_i18n::getText ($Caption) . '
' : '') . ($addEnableToggle ? '' : ''); foreach ($myFields as $Caption=>$Data) if (isset ($FieldTotal [$Caption])) { $Data ['Class'] .= ' twIfTableSummary'; $buf .= self::generateCell ($Data, self::formatOutput ($FieldTotal [$Caption], $Data ['Type'], '', true, false)); } else $buf .= ''; $buf .= "
\n"; return $buf; } // }}} // {{{ filterSelected /** * Filter selected Items * * @param array $Objects Array where to filter selected Items from * @param array $Request (optional) Use this as selection data-source * * @access public * @return array */ public function filterSelected ($Objects, $Request = null) { if (!is_array ($Request)) $Request = $_REQUEST; $Out = array (); foreach ($Objects as $Object) if (isset ($Request ['sel_' . md5 ($Object->getID ())])) $Out [$Object->getID ()] = $Object; return $Out; } // }}} // {{{ getSortParams /** * Retrive parameters for sorted listings * * @param array $fieldDef * @param bool $Enable (optional) Enable sorted output (Default) * * @access public * @return array **/ public static function getSortParams ($fieldDef, $Enable = true, $DefaultField = null, $DefaultOrder = null, $cPrefix = '') { global $_SESSION; // Check wheter to start the session if (count ($_SESSION) == 0) { session_start (); $_SESSION ['twIf'] = true; } // Initialize strucutre if (($DefaultOrder == 'D') || ($DefaultOrder == 'DESC') ? 'D' : 'A') $DefaultOrder = 'D'; elseif ($DefaultOrder !== null) $DefaultOrder = 'A'; $Result = array ( 'Field' => $DefaultField, 'Order' => $DefaultOrder, 'Enable' => $Enable, ); // Check wheter sorting is disabled at all if (!$Enable) return $Result; if (isset ($_SESSION [$cPrefix . '_twIfsO'])) $Result ['Order'] = $_SESSION [$cPrefix . '_twIfsO']; if (isset ($_SESSION [$cPrefix . '_twIfsF'])) $Result ['Field'] = $_SESSION [$cPrefix . '_twIfsF']; // Override the Order-Parameter by URL if (isset ($_REQUEST ['twIfsO']) && (($_REQUEST ['twIfsO'] == 'A') || ($_REQUEST ['twIfsO'] == 'D'))) $Result ['Order'] = $_REQUEST ['twIfsO']; // Search the order-field if (isset ($_REQUEST ['twIfsF']) && is_array ($fieldDef)) foreach ($fieldDef as $Key=>$Data) { if (is_array ($Data)) { if ($f = (isset ($Data ['OrderKey']) && (md5 ($Data ['OrderKey']) == $_REQUEST ['twIfsF']))) $Result ['Field'] = $Data ['OrderKey']; elseif ($f = (isset ($Data ['Field']) && (md5 ($Data ['Field']) == $_REQUEST ['twIfsF']))) $Result ['Field'] = $Data ['Field']; elseif ($f = (isset ($Data ['Read']) && (md5 ($Data ['Read']) == $_REQUEST ['twIfsF']))) $Result ['Field'] = $Data ['Read']; if ($f) break; continue; } // Check Data itself if (md5 ($Data) == $_REQUEST ['twIfsF']) { $Result ['Field'] = $Data; break; } } // Check wheter to store these values $_SESSION [$cPrefix . '_twIfsO'] = $Result ['Order']; $_SESSION [$cPrefix . '_twIfsF'] = $Result ['Field']; return $Result; } // }}} } ?>