TYPO3 CMS  TYPO3_6-2
PagePositionMap.php
Go to the documentation of this file.
1 <?php
3 
21 
29 
30  // EXTERNAL, static:
34  public $moveOrCopy = 'move';
35 
40 
44  public $backPath = '';
45 
46  // How deep the position page tree will go.
50  public $depth = 2;
51 
52  // Can be set to the sys_language uid to select content elements for.
57 
58  // INTERNAL, dynamic:
59  // Request uri
63  public $R_URI = '';
64 
65  // Element id.
69  public $elUid = '';
70 
71  // tt_content element uid to move.
75  public $moveUid = '';
76 
77  // Caching arrays:
81  public $getModConfigCache = array();
82 
86  public $checkNewPageCache = array();
87 
88  // Label keys:
92  public $l_insertNewPageHere = 'insertNewPageHere';
93 
97  public $l_insertNewRecordHere = 'insertNewRecordHere';
98 
102  public $modConfigStr = 'mod.web_list.newPageWiz';
103 
109  protected $pageTreeClassName = 'localPageTree';
110 
116  public function __construct($pageTreeClassName = NULL) {
117  if ($pageTreeClassName !== NULL) {
118  $this->pageTreeClassName = $pageTreeClassName;
119  }
120  }
121 
122  /*************************************
123  *
124  * Page position map:
125  *
126  **************************************/
137  public function positionTree($id, $pageinfo, $perms_clause, $R_URI) {
138  $code = '';
139  // Make page tree object:
141  $t3lib_pageTree = GeneralUtility::makeInstance($this->pageTreeClassName);
142  $t3lib_pageTree->init(' AND ' . $perms_clause);
143  $t3lib_pageTree->addField('pid');
144  // Initialize variables:
145  $this->R_URI = $R_URI;
146  $this->elUid = $id;
147  // Create page tree, in $this->depth levels.
148  $t3lib_pageTree->getTree($pageinfo['pid'], $this->depth);
149  if (!$this->dontPrintPageInsertIcons) {
150  $code .= $this->JSimgFunc();
151  }
152  // Initialize variables:
153  $saveBlankLineState = array();
154  $saveLatestUid = array();
155  $latestInvDepth = $this->depth;
156  // Traverse the tree:
157  foreach ($t3lib_pageTree->tree as $cc => $dat) {
158  // Make link + parameters.
159  $latestInvDepth = $dat['invertedDepth'];
160  $saveLatestUid[$latestInvDepth] = $dat;
161  if (isset($t3lib_pageTree->tree[$cc - 1])) {
162  $prev_dat = $t3lib_pageTree->tree[$cc - 1];
163  // If current page, subpage?
164  if ($prev_dat['row']['uid'] == $id) {
165  // 1) It must be allowed to create a new page and 2) If there are subpages there is no need to render a subpage icon here - it'll be done over the subpages...
166  if (!$this->dontPrintPageInsertIcons && $this->checkNewPageInPid($id) && !($prev_dat['invertedDepth'] > $t3lib_pageTree->tree[$cc]['invertedDepth'])) {
167  $code .= '<span class="nobr">' . $this->insertQuadLines($dat['blankLineCode']) . '<img src="clear.gif" width="18" height="8" align="top" alt="" />' . '<a href="#" onclick="' . htmlspecialchars($this->onClickEvent($id, $id, 1)) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImgSubpage' . $cc . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImgSubpage' . $cc . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord_marker_d.gif', 'width="281" height="8"') . ' name="mImgSubpage' . $cc . '" border="0" align="top" title="' . $this->insertlabel() . '" alt="" />' . '</a></span><br />';
168  }
169  }
170  // If going down
171  if ($prev_dat['invertedDepth'] > $t3lib_pageTree->tree[$cc]['invertedDepth']) {
172  $prevPid = $t3lib_pageTree->tree[$cc]['row']['pid'];
173  } elseif ($prev_dat['invertedDepth'] < $t3lib_pageTree->tree[$cc]['invertedDepth']) {
174  // If going up
175  // First of all the previous level should have an icon:
176  if (!$this->dontPrintPageInsertIcons && $this->checkNewPageInPid($prev_dat['row']['pid'])) {
177  $prevPid = -$prev_dat['row']['uid'];
178  $code .= '<span class="nobr">' . $this->insertQuadLines($dat['blankLineCode']) . '<img src="clear.gif" width="18" height="1" align="top" alt="" />' . '<a href="#" onclick="' . htmlspecialchars($this->onClickEvent($prevPid, $prev_dat['row']['pid'], 2)) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImgAfter' . $cc . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImgAfter' . $cc . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord_marker_d.gif', 'width="281" height="8"') . ' name="mImgAfter' . $cc . '" border="0" align="top" title="' . $this->insertlabel() . '" alt="" />' . '</a></span><br />';
179  }
180  // Then set the current prevPid
181  $prevPid = -$prev_dat['row']['pid'];
182  } else {
183  // In on the same level
184  $prevPid = -$prev_dat['row']['uid'];
185  }
186  } else {
187  // First in the tree
188  $prevPid = $dat['row']['pid'];
189  }
190  if (!$this->dontPrintPageInsertIcons && $this->checkNewPageInPid($dat['row']['pid'])) {
191  $code .= '<span class="nobr">' . $this->insertQuadLines($dat['blankLineCode']) . '<a href="#" onclick="' . htmlspecialchars($this->onClickEvent($prevPid, $dat['row']['pid'], 3)) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImg' . $cc . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImg' . $cc . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord_marker_d.gif', 'width="281" height="8"') . ' name="mImg' . $cc . '" border="0" align="top" title="' . $this->insertlabel() . '" alt="" />' . '</a></span><br />';
192  }
193  // The line with the icon and title:
194  $t_code = '<span class="nobr">' . $dat['HTML'] . $this->linkPageTitle($this->boldTitle(htmlspecialchars(GeneralUtility::fixed_lgd_cs($dat['row']['title'], $GLOBALS['BE_USER']->uc['titleLen'])), $dat, $id), $dat['row']) . '</span><br />';
195  $code .= $t_code;
196  }
197  // If the current page was the last in the tree:
198  $prev_dat = end($t3lib_pageTree->tree);
199  if ($prev_dat['row']['uid'] == $id) {
200  if (!$this->dontPrintPageInsertIcons && $this->checkNewPageInPid($id)) {
201  $code .= '<span class="nobr">' . $this->insertQuadLines($saveLatestUid[$latestInvDepth]['blankLineCode'], 1) . '<img src="clear.gif" width="18" height="8" align="top" alt="" />' . '<a href="#" onclick="' . $this->onClickEvent($id, $id, 4) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImgSubpage' . $cc . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImgSubpage' . $cc . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord_marker_d.gif', 'width="281" height="8"') . ' name="mImgSubpage' . $cc . '" border="0" align="top" title="' . $this->insertlabel() . '" alt="" />' . '</a></span><br />';
202  }
203  }
204  for ($a = $latestInvDepth; $a <= $this->depth; $a++) {
205  $dat = $saveLatestUid[$a];
206  $prevPid = -$dat['row']['uid'];
207  if (!$this->dontPrintPageInsertIcons && $this->checkNewPageInPid($dat['row']['pid'])) {
208  $code .= '<span class="nobr">' . $this->insertQuadLines($dat['blankLineCode'], 1) . '<a href="#" onclick="' . htmlspecialchars($this->onClickEvent($prevPid, $dat['row']['pid'], 5)) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImgEnd' . $a . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImgEnd' . $a . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord_marker_d.gif', 'width="281" height="8"') . ' name="mImgEnd' . $a . '" border="0" align="top" title="' . $this->insertlabel() . '" alt="" />' . '</a></span><br />';
209  }
210  }
211  return $code;
212  }
213 
221  public function JSimgFunc($prefix = '') {
222  $code = $GLOBALS['TBE_TEMPLATE']->wrapScriptTags('
223 
224  var img_newrecord_marker=new Image();
225  img_newrecord_marker.src = "' . IconUtility::skinImg($this->backPath, ('gfx/newrecord' . $prefix . '_marker.gif'), '', 1) . '";
226 
227  var img_newrecord_marker_d=new Image();
228  img_newrecord_marker_d.src = "' . IconUtility::skinImg($this->backPath, ('gfx/newrecord' . $prefix . '_marker_d.gif'), '', 1) . '";
229 
230  function changeImg(name,d) { //
231  if (document[name]) {
232  if (d) {
233  document[name].src = img_newrecord_marker_d.src;
234  } else {
235  document[name].src = img_newrecord_marker.src;
236  }
237  }
238  }
239  ');
240  return $code;
241  }
242 
252  public function boldTitle($t_code, $dat, $id) {
253  if ($dat['row']['uid'] == $id) {
254  $t_code = '<strong>' . $t_code . '</strong>';
255  }
256  return $t_code;
257  }
258 
270  public function onClickEvent($pid, $newPagePID) {
271  $TSconfigProp = $this->getModConfig($newPagePID);
272  if ($TSconfigProp['overrideWithExtension']) {
273  if (ExtensionManagementUtility::isLoaded($TSconfigProp['overrideWithExtension'])) {
274  $onclick = 'window.location.href=\'' . ExtensionManagementUtility::extRelPath($TSconfigProp['overrideWithExtension']) . 'mod1/index.php?cmd=crPage&positionPid=' . $pid . '\';';
275  return $onclick;
276  }
277  }
278  $params = '&edit[pages][' . $pid . ']=new&returnNewPageId=1';
279  return BackendUtility::editOnClick($params, '', $this->R_URI);
280  }
281 
288  public function insertlabel() {
289  return $GLOBALS['LANG']->getLL($this->l_insertNewPageHere, 1);
290  }
291 
300  public function linkPageTitle($str, $rec) {
301  return $str;
302  }
303 
312  public function checkNewPageInPid($pid) {
313  if (!isset($this->checkNewPageCache[$pid])) {
314  $pidInfo = BackendUtility::getRecord('pages', $pid);
315  $this->checkNewPageCache[$pid] = $GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess($pidInfo, 8);
316  }
317  return $this->checkNewPageCache[$pid];
318  }
319 
328  public function getModConfig($pid) {
329  if (!isset($this->getModConfigCache[$pid])) {
330  // Acquiring TSconfig for this PID:
331  $this->getModConfigCache[$pid] = BackendUtility::getModTSconfig($pid, $this->modConfigStr);
332  }
333  return $this->getModConfigCache[$pid]['properties'];
334  }
335 
344  public function insertQuadLines($codes, $allBlank = FALSE) {
345  $codeA = GeneralUtility::trimExplode(',', $codes . ',line', TRUE);
346  $lines = array();
347  foreach ($codeA as $code) {
348  if ($code == 'blank' || $allBlank) {
349  $lines[] = '<img src="clear.gif" width="18" height="8" align="top" alt="" />';
350  } else {
351  $lines[] = '<img' . IconUtility::skinImg($this->backPath, 'gfx/ol/halfline.gif', 'width="18" height="8"') . ' align="top" alt="" />';
352  }
353  }
354  return implode('', $lines);
355  }
356 
357  /*************************************
358  *
359  * Content element positioning:
360  *
361  **************************************/
373  public function printContentElementColumns($pid, $moveUid, $colPosList, $showHidden, $R_URI) {
374  $this->R_URI = $R_URI;
375  $this->moveUid = $moveUid;
376  $colPosArray = GeneralUtility::trimExplode(',', $colPosList, TRUE);
377  $lines = array();
378  foreach ($colPosArray as $kk => $vv) {
379  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$pid . ($showHidden ? '' : BackendUtility::BEenableFields('tt_content')) . ' AND colPos=' . (int)$vv . ((string)$this->cur_sys_language !== '' ? ' AND sys_language_uid=' . (int)$this->cur_sys_language : '') . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting');
380  $lines[$vv] = array();
381  $lines[$vv][] = $this->insertPositionIcon('', $vv, $kk, $moveUid, $pid);
382  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
383  BackendUtility::workspaceOL('tt_content', $row);
384  if (is_array($row)) {
385  $lines[$vv][] = $this->wrapRecordHeader($this->getRecordHeader($row), $row);
386  $lines[$vv][] = $this->insertPositionIcon($row, $vv, $kk, $moveUid, $pid);
387  }
388  }
389  $GLOBALS['TYPO3_DB']->sql_free_result($res);
390  }
391  return $this->printRecordMap($lines, $colPosArray, $pid);
392  }
393 
403  public function printRecordMap($lines, $colPosArray, $pid = 0) {
404  $row1 = '';
405  $row2 = '';
406  $count = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(count($colPosArray), 1);
407  $backendLayout = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getSelectedBackendLayout', $pid, $this);
408  if (isset($backendLayout['__config']['backend_layout.'])) {
409  $table = '<div class="t3-gridContainer"><table border="0" cellspacing="0" cellpadding="0" id="typo3-ttContentList">';
410  $colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
411  $rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
412  $table .= '<colgroup>';
413  for ($i = 0; $i < $colCount; $i++) {
414  $table .= '<col style="width:' . 100 / $colCount . '%"></col>';
415  }
416  $table .= '</colgroup>';
417  $tcaItems = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getColPosListItemsParsed', $pid, $this);
418  // Cycle through rows
419  for ($row = 1; $row <= $rowCount; $row++) {
420  $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
421  if (!isset($rowConfig)) {
422  continue;
423  }
424  $table .= '<tr>';
425  for ($col = 1; $col <= $colCount; $col++) {
426  $columnConfig = $rowConfig['columns.'][$col . '.'];
427  if (!isset($columnConfig)) {
428  continue;
429  }
430  // Which tt_content colPos should be displayed inside this cell
431  $columnKey = (int)$columnConfig['colPos'];
432  $head = '';
433  foreach ($tcaItems as $item) {
434  if ($item[1] == $columnKey) {
435  $head = $GLOBALS['LANG']->sL($item[0], TRUE);
436  }
437  }
438  // Render the grid cell
439  $table .= '<td valign="top"' . (isset($columnConfig['colspan']) ? ' colspan="' . $columnConfig['colspan'] . '"' : '') . (isset($columnConfig['rowspan']) ? ' rowspan="' . $columnConfig['rowspan'] . '"' : '') . ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey . (!isset($columnConfig['colPos']) ? ' t3-gridCell-unassigned' : '') . (isset($columnConfig['colPos']) && !$head ? ' t3-gridCell-restricted' : '') . (isset($columnConfig['colspan']) ? ' t3-gridCell-width' . $columnConfig['colspan'] : '') . (isset($columnConfig['rowspan']) ? ' t3-gridCell-height' . $columnConfig['rowspan'] : '') . '">';
440  $table .= '<div class="t3-page-colHeader t3-row-header">';
441  if (isset($columnConfig['colPos']) && $head) {
442  $table .= $this->wrapColumnHeader($head, '', '') . '</div>' . implode('<br />', $lines[$columnKey]);
443  } elseif ($columnConfig['colPos']) {
444  $table .= $this->wrapColumnHeader($GLOBALS['LANG']->getLL('noAccess'), '', '') . '</div>';
445  } elseif ($columnConfig['name']) {
446  $table .= $this->wrapColumnHeader($columnConfig['name'], '', '') . '</div>';
447  } else {
448  $table .= $this->wrapColumnHeader($GLOBALS['LANG']->getLL('notAssigned'), '', '') . '</div>';
449  }
450  $table .= '</td>';
451  }
452  $table .= '</tr>';
453  }
454  $table .= '</table></div>';
455  } else {
456  // Traverse the columns here:
457  foreach ($colPosArray as $kk => $vv) {
458  $row1 .= '<td align="center" width="' . round(100 / $count) . '%"><div class="t3-page-colHeader t3-row-header">' . $this->wrapColumnHeader($GLOBALS['LANG']->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $vv, $pid), TRUE), $vv) . '</div></td>';
459  $row2 .= '<td valign="top" nowrap="nowrap">' . implode('<br />', $lines[$vv]) . '</td>';
460  }
461  $table = '
462 
463  <!--
464  Map of records in columns:
465  -->
466  <table border="0" cellpadding="0" cellspacing="0" id="typo3-ttContentList">
467  <tr>' . $row1 . '</tr>
468  <tr>' . $row2 . '</tr>
469  </table>
470 
471  ';
472  }
473  return $this->JSimgFunc('2') . $table;
474  }
475 
485  public function wrapColumnHeader($str, $vv) {
486  return $str;
487  }
488 
501  public function insertPositionIcon($row, $vv, $kk, $moveUid, $pid) {
502  if (is_array($row) && !empty($row['uid'])) {
503  // Use record uid for the hash when inserting after this content element
504  $uid = $row['uid'];
505  } else {
506  // No uid means insert at first position in the column
507  $uid = '';
508  }
509  $cc = hexdec(substr(md5($uid . '-' . $vv . '-' . $kk), 0, 4));
510  return '<a href="#" onclick="' . htmlspecialchars($this->onClickInsertRecord($row, $vv, $moveUid, $pid, $this->cur_sys_language)) . '" onmouseover="' . htmlspecialchars(('changeImg(\'mImg' . $cc . '\',0);')) . '" onmouseout="' . htmlspecialchars(('changeImg(\'mImg' . $cc . '\',1);')) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/newrecord2_marker_d.gif', 'width="100" height="8"') . ' name="mImg' . $cc . '" border="0" align="top" title="' . $GLOBALS['LANG']->getLL($this->l_insertNewRecordHere, 1) . '" alt="" />' . '</a>';
511  }
512 
525  public function onClickInsertRecord($row, $vv, $moveUid, $pid, $sys_lang = 0) {
526  $table = 'tt_content';
527  if (is_array($row)) {
528  $location = 'tce_db.php?cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=-' . $row['uid'] . '&prErr=1&uPT=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility::getUrlToken('tceAction');
529  } else {
530  $location = 'tce_db.php?cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=' . $pid . '&data[' . $table . '][' . $moveUid . '][colPos]=' . $vv . '&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility::getUrlToken('tceAction');
531  }
532  $location .= '&redirect=' . rawurlencode($this->R_URI);
533  // returns to prev. page
534  return 'window.location.href=\'' . $location . '\';return false;';
535  }
536 
545  public function wrapRecordHeader($str, $row) {
546  return $str;
547  }
548 
556  public function getRecordHeader($row) {
557  $line = IconUtility::getSpriteIconForRecord('tt_content', $row, array('title' => htmlspecialchars(BackendUtility::getRecordIconAltText($row, 'tt_content'))));
558  $line .= BackendUtility::getRecordTitle('tt_content', $row, TRUE);
559  return $this->wrapRecordTitle($line, $row);
560  }
561 
570  public function wrapRecordTitle($str, $row) {
571  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('uid' => (int)$row['uid'], 'moveUid' => ''))) . '">' . $str . '</a>';
572  }
573 
574 }