You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

323 lines
12 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
function wikiplugin_split_info()
{
return [
'name' => tra('Split'),
'documentation' => 'PluginSplit',
'description' => tra('Arrange content on a page into rows and columns'),
'prefs' => [ 'wikiplugin_split' ],
'filter' => 'wikicontent',
'iconname' => 'th-large',
'introduced' => 1,
'tags' => [ 'basic' ],
'body' => tra('Text to display in a table. Use "---" to separate the columns and "@@@" to separate rows.'),
'params' => [
'joincols' => [
'required' => false,
'name' => tra('Join Columns'),
'description' => tra('Generate the colspan attribute if columns are missing'),
'since' => '1',
'filter' => 'alpha',
'default' => 'y',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Yes'), 'value' => 'y'],
['text' => tra('No'), 'value' => 'n']
]
],
'fixedsize' => [
'required' => false,
'name' => tra('Fixed Size'),
'description' => tra('Generate the width attribute for the columns'),
'since' => '1',
'filter' => 'alpha',
'default' => 'y',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Yes'), 'value' => 'y'],
['text' => tra('No'), 'value' => 'n']
]
],
'colsize' => [
'required' => false,
'name' => tra('Column Sizes'),
'description' => tr('Specify all column widths in number of pixels or percent, separating each width
by a pipe (%0)', '<code>|</code>'),
'since' => '1',
'seprator' => '|',
'filter' => 'text',
'default' => '',
],
'first' => [
'required' => false,
'name' => tra('First'),
'description' => tra('Cells specified are ordered first left to right across rows (default) or top to
bottom down columns'),
'since' => '1',
'filter' => 'alpha',
'default' => 'line',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Column'), 'value' => 'col'],
['text' => tra('Line'), 'value' => 'line']
]
],
'edit' => [
'required' => false,
'name' => tra('Editable'),
'description' => tr('Display edit icon for each section. Works when used on a wiki page and the %0
parameter is set to %1', '<code>first</code>', '<code>col</code>'),
'since' => '1',
'filter' => 'alpha',
'default' => 'n',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Yes'), 'value' => 'y'],
['text' => tra('No'), 'value' => 'n']
]
],
'customclass' => [
'required' => false,
'name' => tra('Custom Class'),
'description' => tra('Add a class to customize the design'),
'since' => '3.0',
'filter' => 'text',
'default' => '',
],
],
];
}
function wikiplugin_split_rollback($data, $hashes)
{
foreach ($hashes as $hash => $match) {
$data = str_replace($hash, $match, $data);
}
return $data;
}
/*
* \note This plugin should carefuly change text it have to parse
* because some of wiki syntaxes are sensitive for
* start of new line ('\n' character - e.g. lists and headers)... such
* user lines must stay with the same layout when applying
* this plugin to render them properly after...
* $data = the preparsed data (plugin, code, np.... already parsed)
* $pos is the position in the object where the non-parsed data begins
*/
function wikiplugin_split($data, $params, $pos)
{
global $tikilib, $tiki_p_admin_wiki, $tiki_p_admin, $section;
global $replacement;
preg_match_all('/{(SPLIT|CODE|HTML|FADE|JQ|JS|MOUSEOVER|VERSIONS).+{\1}/ismU', $data, $matches);
$hashes = [];
foreach ($matches[0] as $match) {
if (empty($match)) {
continue;
}
$hash = md5($match);
$hashes[$hash] = $match;
$data = str_replace($match, $hash, $data);
}
// Remove first <ENTER> if exists...
// it may be here if present after {SPLIT()} in original text
if (substr($data, 0, 2) == "\r\n") {
$data2 = substr($data, 2);
} else {
$data2 = $data;
}
extract($params, EXTR_SKIP);
$fixedsize = (! isset($fixedsize) || $fixedsize == 'y' || $fixedsize == 1 ? true : false);
$joincols = (! isset($joincols) || $joincols == 'y' || $joincols == 1 ? true : false);
// Split data by rows and cells
$sections = preg_split("/@@@+/", $data2);
$rows = [];
$maxcols = 0;
foreach ($sections as $i) {
// split by --- but not by ----
// $rows[] = preg_split("/([^\-]---[^\-]|^---[^\-]|[^\-]---$|^---$)+/", $i);
// not to eat the character close to - and to split on --- and not ----
$rows[] = preg_split("/(?<!-)---(?!-)/", $i);
$maxcols = max($maxcols, count(end($rows)));
}
// Is there split sections present?
// Do not touch anything if no... even don't generate <table>
if (count($rows) <= 1 && count($rows[0]) <= 1) {
return wikiplugin_split_rollback($data, $hashes);
}
$percent = false;
if (isset($colsize)) {
$tdsize = explode("|", $colsize);
$tdtotal = 0;
for ($i = 0; $i < $maxcols; $i++) {
if (! isset($tdsize[$i])) {
$tdsize[$i] = 0;
} else {
$tdsize[$i] = trim($tdsize[$i]);
if (strstr($tdsize[$i], '%')) {
$percent = true;
}
}
$tdtotal += (float)$tdsize[$i];
}
$tdtotaltd = floor($tdtotal / 100 * 100);
if ($tdtotaltd == 100) { // avoir IE to do to far
$class = 'class="table split"';
} else {
$class = 'class="split" width="' . $tdtotaltd . '%"';
}
} elseif ($fixedsize) {
$columnSize = floor(100 / $maxcols);
$class = 'class="table split"';
$percent = true;
}
if (! isset($edit)) {
$edit = 'n';
}
$result = "<div class='table-responsive'><div><table class='table" . ($percent ? " normalnoborder" : "") . ( ! empty($customclass) ? " $customclass" : "") . "'>";
// Attention: Dont forget to remove leading empty line in section ...
// it should remain from previous '---' line...
// Attention: original text must be placed between \n's!!!
if (! isset($first) || $first != 'col') {
foreach ($rows as $r) {
$result .= "<tr>";
$idx = 1;
foreach ($r as $i) {
// Remove first <ENTER> if exists
if (substr($i, 0, 2) == "\r\n") {
$i = substr($i, 2);
}
// Generate colspan for last element if needed
$colspan = ((count($r) == $idx) && (($maxcols - $idx) > 0) ? ' colspan="' . ($maxcols - $idx + 1) . '"' : '');
$idx++;
// Add cell to table
if (isset($colsize)) {
$width = ' width="' . $tdsize[$idx - 2] . '"';
} elseif ($fixedsize) {
$width = ' width="' . $columnSize . '%" ';
} else {
$width = '';
}
$result .= '<td' . $width . $colspan . '>'
// Insert "\n" at data begin (so start-of-line-sensitive syntaxes will be parsed OK)
. "\n"
// now prepend any carriage return and newline char with br
. preg_replace("/\r?\n/", "<br />\r\n", $i)
. '</td>';
}
$result .= "</tr>";
}
} else { // column first
if ($edit == 'y') {
global $user;
if (isset($_REQUEST['page'])) {
$type = 'wiki page';
$object = $_REQUEST['page'];
if ($tiki_p_admin_wiki == 'y' || $tiki_p_admin == 'y') {
$perm = true;
} else {
$perm = $tikilib->user_has_perm_on_object($user, $object, $type, 'tiki_p_edit');
}
} else { // TODO: other object type
$perm = false;
}
}
$ind = 0;
$icell = 0;
$result .= '<tr>';
$idx = 0;
foreach ($rows as $r) {
$result .= '<td ' . (($fixedsize && isset($tdsize)) ? ' width="' . $tdsize[$idx] . (strstr($tdsize[$idx], '%') ? '' : '%') . '"' : '') . '>';
foreach ($r as $i) {
if (substr($i, 0, 2) == "\r\n") {
$i = substr($i, 2);
$ind += 2;
}
if ($edit == 'y' && $perm && $section == 'wiki page') {
$result .= '<div class="split"><div style="float:right">';
$result .= "$pos-$icell-" . htmlspecialchars(substr($data, $pos, 10));
$result .= '<a href="tiki-editpage.php?page=' . $object . '&amp;pos=' . $pos . '&amp;cell=' . $icell . '">'
. '<img src="img/icons/page_edit.png" alt="' . tra('Edit') . '" title="' . tra('Edit') . '" width="16" height="16" /></a></div><br />';
$ind += strlen($i);
while (isset($data[$ind]) && ($data[$ind] == '-' || $data[$ind] == '@')) {
++$ind;
}
} else {
$result .= '<div>';
}
$result .= "\n" . preg_replace("/\r?\n/", "<br />\r\n", $i) . '</div>';
++$icell;
}
++$idx;
$result .= '</td>';
}
$result .= '</tr>';
}
// Close HTML table (no \n at end!)
$result .= "</table></div></div>";
return wikiplugin_split_rollback($result, $hashes);
}
// find the real start and the real end of a cell
// $pos = start pos in the non parsed data of all the split cells
// $cell = cellule indice
function wikiplugin_split_cell($data, $pos, $cell)
{
$start = $pos;
$end = $pos;
$no_parsed = '~np~|~pp~|\\<pre\\>|\\<PRE\\>';
$no_parsed_end = '';
$match = '@@@+|----*|\{SPLIT\}|\{SPLIT\(|~np~|~pp~|\\<pre\\>|\\<PRE\\>';
while (true) {
if (! preg_match("#($match)#m", substr($data, $pos), $matches)) {
if ($cell) {
$end = $start;
}
break;
} else {
$end = $pos + strpos(substr($data, $pos), $matches[1]);
$start_next_tag = $end + strlen($matches[1]);
if (substr($matches[1], 0, 3) == '@@@' || $matches[1] == '---') {
if (! $cell) {
break;
}
--$cell;
if (! $cell) {
$start = $start_next_tag;
}
} elseif ($matches[1] == $match) {
$match = '@@@+|----*|\{SPLIT\}|\{SPLIT\(|~np~|~pp~|\\<pre\\>|\\<PRE\\>';
} elseif ($matches[1] == '{SPLIT}') {
if (! $cell) {
break;
}
} elseif ($matches[1] == '{SPLIT(') {
$match = '{SPLIT}';
} elseif ($matches[1] == '~np~') {
$match = '~/np~';
} elseif ($matches[1] == '~pp~') {
$match = '~/pp~';
} elseif ($matches[1] == '<pre>') {
$match = '</pre>';
} elseif ($matches[1] == '<PRE>') {
$match = '</PRE>';
}
$pos = $start_next_tag;
}
}
return [$start, $end - $start];
}