createParams(); $tsparams = $ts->params; unset($tsparams['server']); } else { $tsparams = []; } $params = array_merge( [ 'head' => [ 'required' => false, 'name' => tra('Heading Row'), 'description' => tr('Header rows of the table. Use %0 to separate multiple rows.', '>>'), 'default' => '', 'since' => '1' ], 'headclass' => [ 'required' => false, 'name' => tra('Heading CSS Class'), 'description' => tra('CSS class to apply to the heading row.'), 'default' => '', 'since' => '1' ], 'headaligns' => [ 'required' => false, 'name' => tra('Header Horizontal Alignment'), 'description' => tr( 'Horizontal alignments for header cells, separated by %0. Choices: %1', '|', 'left, right, center, justify' ), 'default' => '', 'since' => '4.1', 'filter' => 'text', ], 'headvaligns' => [ 'required' => false, 'name' => tra('Header Vertical Alignment'), 'description' => tr( 'Vertical alignments for header cells, separated by %0". Choices: %1', '|', 'top, middle, bottom, baseline' ), 'default' => '', 'since' => '4.1', 'filter' => 'text', ], 'colwidths' => [ 'required' => false, 'name' => tra('Column Widths'), 'description' => tr('Column widths followed by "px" for pixels or "%" for percentages. Each column separated by %0.', '|'), 'default' => '', 'since' => '4.1' ], 'colaligns' => [ 'required' => false, 'name' => tra('Cell Horizontal Align'), 'description' => tr( 'Table body column horizontal alignments, separated by %0. Choices: %1', '|', 'left, right, center, justify' ), 'default' => '', 'since' => '4.1', 'filter' => 'text', ], 'colvaligns' => [ 'required' => false, 'name' => tra('Cell Vertical Align'), 'description' => tr( 'Table body column vertical alignments, separated by %0. Choices: %1', '|', 'top, middle, bottom, baseline' ), 'default' => '', 'since' => '4.1', 'filter' => 'text', ], ], $tsparams ); return [ 'name' => tra('Fancy Table'), 'documentation' => 'PluginFancyTable', 'description' => tra('Create a formatted table that can be filtered and sorted'), 'prefs' => ['wikiplugin_fancytable'], 'body' => tr( 'Rows separated by %0 in the header; for the table body, one row per line. Cells separated by %1 (since Tiki4) or %2 in both cases.', '>>', '|', '~|~' ), 'iconname' => 'table', 'introduced' => 1, 'tags' => [ 'basic' ], 'params' => $params, ]; } function wikiplugin_fancytable($data, $params) { global $prefs; $tagremove = []; $pluginremove = []; static $iFancytable = 0; ++$iFancytable; extract($params, EXTR_SKIP); if (empty($sortable)) { $sortable = 'n'; } $msg = ''; if ((isset($sortable) && $sortable != 'n')) { if (Table_Check::isEnabled()) { $ts = new Table_Plugin(); $ts->setSettings( 'wpfancytable' . $iFancytable, 'n', $sortable, isset($sortList) ? $sortList : null, isset($tsortcolumns) ? $tsortcolumns : null, isset($tsfilters) ? $tsfilters : null, isset($tsfilteroptions) ? $tsfilteroptions : null, isset($tspaginate) ? $tspaginate : null, isset($tscolselect) ? $tscolselect : null, null, null, isset($tstotals) ? $tstotals : null, isset($tstotalformat) ? $tstotalformat : null, isset($tstotaloptions) ? $tstotaloptions : null ); if (is_array($ts->settings)) { $ts->settings['resizable'] = true; Table_Factory::build('plugin', $ts->settings); $sort = true; } else { $sort = false; } } else { $sort = false; } if ($sort === false) { if ($prefs['feature_jquery_tablesorter'] === 'n') { $msg = '' . tra('The jQuery Sortable Tables feature must be activated for the sort feature to work.') . ''; } elseif ($prefs['javascript_enabled'] !== 'y') { $msg = '' . tra('JavaScript must be enabled for the sort feature to work.') . ''; } else { $msg = '' . tra('Unable to load the jQuery Sortable Tables feature.') . ''; } } } else { $sort = false; } //Start the table $style = $sort === true ? ' style="visibility:hidden"' : ''; $wret = '
' . "\r\t"; $wret .= '' . "\r\t"; //Header if (isset($head)) { //set header class if (! empty($headclass)) { $tdhdr = "\r\t\t\t" . '', isset($colwidths) ? $colwidths : '', isset($headaligns) ? $headaligns : '', isset($headvaligns) ? $headvaligns : '' ); //restore original tags and plugin syntax $headhtml = $headrows['html']; postprocess_section($headhtml, $tagremove, $pluginremove); $wret .= '' . $headhtml . "\r\t" . '' . "\r\t"; } //Body //replace tiki tags, plugins and other enclosing characters with hash strings before creating table so that any //pipes (| or ~|~) inside aren't mistaken for cell dividers preprocess_section($data, $tagremove, $pluginremove); if ($sort) { $type = 'bs'; //sortable body rows - do not assign odd/even class to these since jquery will do it } else { $type = 'b'; //plain body rows } //now create table body rows $bodyrows = process_section( $data, $type, "\n", "\r\t\t\t" . '', isset($colwidths) ? $colwidths : '', isset($colaligns) ? $colaligns : '', isset($colvaligns) ? $colvaligns : '' ); //restore original tags and plugin syntax $bodyhtml = $bodyrows['html']; postprocess_section($bodyhtml, $tagremove, $pluginremove); //end the tbody $wret .= '' . $bodyhtml . "\r\t" . ''; if (isset($ts->settings)) { $footer = Table_Totals::getTotalsHtml($ts->settings, $bodyrows['cols']); if ($footer) { $wret .= $footer; } } $wret .= "\r" . '
>', $tdhdr, '
' . "\r" . $msg; return $wret; } /** * To keep pipes (| or ~|~) inside other Tiki tags or plugins, or other "enclosing" characters from being mistaken as * cell dividers, replace them with hash strings until after the table is created * * @param string $data Header or body text with tags and plugins removed * @param array $tagremove Key => value pairs of Hash => data for tags or enclosing characters * @param array $pluginremove Key => value pairs of Hash => data for plugins */ function preprocess_section(&$data, &$tagremove, &$pluginremove) { $parserlib = TikiLib::lib('parser'); //first replace plugins with hash strings since they may contain pipe characters $parserlib->plugins_remove($data, $pluginremove); //then replace tags or other enclosing charcters that could enclose a pipe (| or ~|~) character with a hash string $tikilib = TikiLib::lib('tiki'); $tags = [ [ 'start' => '\(\(', // (( )) 'end' => '\)\)', ], [ 'start' => '\[', // [ ] 'end' => '\]', ], [ 'start' => '~np~', // ~np~ ~/np~ 'end' => '~\/np~', ], [ 'start' => '~tc~', // ~tc~ ~/tc~ 'end' => '~\/tc~', ], [ 'start' => '~hc~', // ~hc~ ~/hc~ 'end' => '~\/hc~', ], [ 'start' => '\^', // ^ ^ 'end' => '\^', ], [ 'start' => '__', // __ __ 'end' => '__', ], [ 'start' => '\:\:', // :: :: 'end' => '\:\:', ], [ 'start' => '\:\:\:', // ::: ::: 'end' => '\:\:\:', ], [ 'start' => '\'\'', // '' '' 'end' => '\'\'', ], [ 'start' => '-\+', // -+ +- 'end' => '\+-', ], [ 'start' => '-=', // -= =- 'end' => '=-', ], [ 'start' => '===', // === === 'end' => '===', ], [ 'start' => '--', // -- -- 'end' => '--', ], [ 'start' => '\(', // ( ) 'end' => '\)', ], [ 'start' => '\"', // " " 'end' => '\"', ], ]; $count = count($tags) - 1; $pattern = '/('; foreach ($tags as $key => $tag) { $pattern .= $tag['start'] . '(?:(?!' . $tag['end'] . ').)*' . $tag['end']; if ($key < $count) { $pattern .= '|'; } } $pattern .= ')/'; preg_match_all($pattern, $data, $matches); foreach ($matches[0] as $match) { $tagremove['key'][] = '§' . md5($tikilib->genPass()) . '§'; $tagremove['data'][] = $match; $data = isset($tagremove['data']) ? str_replace($tagremove['data'], $tagremove['key'], $data) : $data; } } /** * Process header or body string to convert to table rows * * @param string $data Header or body string to be broken down into table rows * @param string $type Indicates whether rows are sortable or not, which impacts class assigned * @param string $line_sep Row separator (>> for header and \n for body) * @param string $cellbeg HTML or ending tags * @param numeric $widths User input for column widths * @param string $aligns User input for horizontal text alignment within cells * @param string $valigns User input for vertical text alignment within cells * * @return string $wret HTML string for the header or body rows processed */ function process_section($data, $type, $line_sep, $cellbeg, $cellend, $widths, $aligns, $valigns) { $separator = strpos($data, '~|~') === false ? '|' : '~|~'; $lines = explode($line_sep, $data); $widths = ! empty($widths) ? explode('|', $widths) : ''; $aligns = ! empty($aligns) ? explode('|', $aligns) : ''; $valigns = ! empty($valigns) ? explode('|', $valigns) : ''; $trbeg = "\r\t\t"; $trend = "\r\t\t"; $l = 0; $rnum1 = ''; $rnum2 = ''; $wret = ''; $row_is_odd = true; //Each row foreach ($lines as $line) { $line = trim($line); if (strlen($line) > 0) { if ($type == 'b') { // if ($row_is_odd) { // $cellbeg = "\r\t\t\t" . ' 0) { $c++; } } //Note the info for this new rowspan ${$colnum}['col'] = $c; ${$colnum}['line'] = $l; ${$colnum}['span'] = $rnum; } } //set column style $colstyle = ''; if (! empty($widths) || ! empty($aligns) || ! empty($valigns)) { //If there's another rowspan still in force, bump up the column number if (isset(${$colnum}['col']) && ${$colnum}['col'] == $c && ($l > ${$colnum}['line'])) { if ((${$colnum}['span'] - ($l - ${$colnum}['line'])) > 0) { $c++; } } $colstyle = ' style="'; $colstyle .= ! empty($widths[$c]) ? ' width: ' . $widths[$c] . ';' : ''; $colstyle .= ! empty($aligns[$c]) ? ' text-align: ' . $aligns[$c] . ';' : ''; $colstyle .= ! empty($valigns[$c]) ? ' vertical-align: ' . $valigns[$c] : ''; $colstyle .= '"'; } $row .= $cellbeg . $colspan . $rowspan . $colstyle . '>' . $column . $cellend; $c++;//increment column number } $wret .= $trbeg . $row . $trend; } $l++;//increment row number } $ret['html'] = $wret; $ret['cols'] = count($parts); return $ret; } /** * Replace hash strings with original tag and plugin content * * @param string $data Header or body text processed into table rows with hash strings replacing * tags and plugins * @param array $tagremove Tag hash => data pairs for tags that were replaced with hash strings * @param array $pluginremove Plugin Hash => data pairs for plugins that were replaced with hash strings */ function postprocess_section(&$data, &$tagremove, &$pluginremove) { //first restore tag strings $parserlib = TikiLib::lib('parser'); if ( isset($tagremove['key']) and count($tagremove['key']) and count($tagremove['key']) == count($tagremove['data']) ) { $data = str_replace($tagremove['key'], $tagremove['data'], $data); } //then restore plugin strings $parserlib->plugins_replace($data, $pluginremove); //reset variables since this function is run for both the header and body $tagremove = []; $pluginremove = []; }