Commit 3b8fc764 authored by Damjan's avatar Damjan

[TASK] Addition of view tree

Related: forge.typo3.org/issues/31889
parent fa632ac8
......@@ -597,11 +597,9 @@ class MainController extends AbstractController {
try {
$this->view->assign('mainMenuSelection', 'renameConstant');
/** @var array $extensionOptions */
$extensionOptions = $this->configurationService->menuExtList();
$this->assignViewWidthMenuVariables('extension', $extensionOptions);
/** @var array $languageFileOptions */
$languageFileOptions = $this->configurationService->menuLangFileList(
$this->session->getDataByKey('extensionSelection')
);
......@@ -612,9 +610,7 @@ class MainController extends AbstractController {
$this->session->getDataByKey('extensionSelection')
);
/** @var array $langData */
$langData = $this->configurationService->getFileObj()->getLocalLangData();
/** @var array $constantOptions */
$constantOptions = $this->configurationService->menuConstList(
$langData, LocalizationUtility::translate('select.nothing', 'lfeditor')
);
......@@ -821,6 +817,198 @@ class MainController extends AbstractController {
$this->view->assign('searchString', $searchString);
}
/*********************************************
* Actions called from viewTree view *
*********************************************/
/**
* Opens viewTree view.
* It is called in 2 cases:
* - on selection of viewTree option in main menu,
* - after redirection from action which must not change the view.
*
* @return void
*/
public function viewTreeAction() {
try {
$this->view->assign('mainMenuSelection', 'viewTree');
$extensionOptions = $this->configurationService->menuExtList();
$this->assignViewWidthMenuVariables('extension', $extensionOptions);
$languageFileOptions = $this->configurationService->menuLangFileList(
$this->session->getDataByKey('extensionSelection')
);
$this->assignViewWidthMenuVariables('languageFile', $languageFileOptions);
$this->configurationService->initFileObject(
$this->session->getDataByKey('languageFileSelection'),
$this->session->getDataByKey('extensionSelection')
);
$languageOptions = $this->configurationService->menuLangList(
$this->configurationService->getFileObj()->getLocalLangData()
);
$this->assignViewWidthMenuVariables('language', $languageOptions);
$this->assignViewWidthMenuVariables('referenceLanguage', $languageOptions);
$this->prepareViewTreeViewMainSectionContent();
} catch (LFException $e) {
$this->addFlashMessage($e);
}
debug($this->session->getData(), 'ses');//TODO: Delete debug.
}
/**
* This action saves in session currently selected options from selection menus in viewTree view.
* It is called on change of selection of any select menu in viewTree view.
*
* @param string $extensionSelection
* @param string $languageFileSelection
* @param string $languageSelection
* @param string $referenceLanguageSelection
* @throws UnsupportedRequestTypeException
* @return void
*/
public function viewTreeChangeSelectionAction(
$extensionSelection = NULL, $languageFileSelection = NULL, $languageSelection = NULL,
$referenceLanguageSelection = NULL
) {
$this->saveSelectionsInSession(
$extensionSelection, $languageFileSelection, $referenceLanguageSelection, NULL, $languageSelection
);
$this->redirect('viewTree');
}
/**
* Selects explodeToken.
*
* @param string $explodeToken
* @throws UnsupportedRequestTypeException
* @return void
*/
public function selectExplodeTokenAction($explodeToken) {
$this->session->setDataByKey('explodeToken', $explodeToken);
$this->redirect('viewTree');
}
/**
* Prepares main section content of deleteConstant view.
*
* @return void
*/
protected function prepareViewTreeViewMainSectionContent() {
$explodeToken = $this->session->getDataByKey('explodeToken');
if ($explodeToken === NULL) {
$explodeToken = '.';
}
$langData = $this->configurationService->getFileObj()->getLocalLangData();
$refLangSelection = $this->session->getDataByKey('referenceLanguageSelection');
$tree = Functions::genTreeInfoArray($langData['default'], $langData[$refLangSelection], $explodeToken);
$treeHide = $this->configurationService->getExtConfig()['treeHide'];
$fluidTree = [];
$levelIndex = 0;
$this->addLevelElementsToFluidTree($tree, $levelIndex, NULL, $fluidTree, $treeHide);
$this->view->assign('fluidTree', $fluidTree);
$this->view->assign('treeHide', $treeHide);
$this->view->assign('explodeToken', $explodeToken);
}
/**
* @var integer Width of margin which is added if a branch is missing.
*/
protected $marginLeftSpaceUnit = 18;
/**
* Makes tree structure which contains constants. The structure is optimised for recursive use on fluid pages.
*
* @param array $sourceTree
* @param int $level
* @param string $parentKey
* @param array $fluidTree This structure is used for setting tree-data for use in fluid.
* @param boolean $treeHide Default state of tree (TRUE - hidden, FALSE - opened)
* @return void
*/
protected function addLevelElementsToFluidTree(
array $sourceTree, $level, $parentKey, array &$fluidTree, $treeHide
) {
$constKeys = array_keys($sourceTree[$level]);
$index = 0;
foreach ($sourceTree[$level] as $constKey => $treeNode) {
if ($level === 0 || $treeNode['parent'] === $parentKey) {
$fluidTreeElem = [];
$fluidTreeElem['label'] = $treeNode['name'];
$fluidTreeElem['parent'] = $fluidTree; //$treeNode['parent'];//; //
$fluidTreeElem['type'] = $treeNode['type'];
$fluidTreeElem['isBottom'] = (!array_key_exists($index + 1, $constKeys) ||
$sourceTree[$level][$constKeys[$index + 1]]['parent'] !== $treeNode['parent']) ? 1 : 0;
$icons = $this->prepareTreeIcons($level, $treeHide, $fluidTreeElem, $treeNode['childs'] !== NULL);
$fluidTreeElem['icons'] = $icons;
if ($sourceTree[$level + 1]) {
$this->addLevelElementsToFluidTree(
$sourceTree, $level + 1, $constKey, $fluidTreeElem, $treeHide
);
}
if ($level > 0) {
$fluidTree['children'][$constKey] = $fluidTreeElem;
} else {
$fluidTree[$constKey] = $fluidTreeElem;
}
}
$index++;
}
}
/**
* Sorts and adds icons in tree structure.
*
* @param int $level Tree level of constant.
* @param boolean $treeHide Indicator which shows should all tree elements be closed (hidden) by default.
* @param array $fluidTreeElem Element of tree which is built for use on fluid page.
* @param boolean $hasChildren Indicator does this tree element have children
* @return array
*/
protected function prepareTreeIcons($level, $treeHide, array $fluidTreeElem, $hasChildren) {
$icons = [];
$leftMargins = [];
$marginLeftSpaceCounter = 0;
for ($iconLevel = $level, $currentFluidTreeElem = $fluidTreeElem;
$currentFluidTreeElem;
$iconLevel--, $currentFluidTreeElem = $currentFluidTreeElem['parent']) {
$iconName = '.gif';
if ($iconLevel === $level) {
if ($currentFluidTreeElem['isBottom']) {
$iconName = 'Bottom' . $iconName;
}
if ($hasChildren) { // TODO: rename key in structure to 'children'
$iconName = 'tree' . ($treeHide && $level != 0 ? 'Plus' : 'Minus') . $iconName;
} else {
$iconName = 'join' . $iconName;
}
} else {
if (!$currentFluidTreeElem['isBottom']) {
$iconName = 'line' . $iconName;
$leftMargins[] = $marginLeftSpaceCounter;
$marginLeftSpaceCounter = 0;
} else {
$marginLeftSpaceCounter += $this->marginLeftSpaceUnit;
continue;
}
}
$icons[] = ['name' => $iconName];
}
$leftMargins[] = $marginLeftSpaceCounter;
for ($iterator = 0, $iconsSize = count($icons); $iterator < $iconsSize; $iterator++) {
$icons[$iterator]['marginLeft'] = $leftMargins[$iterator];
}
return $icons;
}
/**************************
* Additional functions *
**************************/
......@@ -832,11 +1020,12 @@ class MainController extends AbstractController {
* @param string $languageFileSelection
* @param string $referenceLanguageSelection
* @param string $constantSelection
* @param string $languageSelection
* @return void
*/
protected function saveSelectionsInSession(
$extensionSelection = NULL, $languageFileSelection = NULL, $referenceLanguageSelection = NULL,
$constantSelection = NULL
$constantSelection = NULL, $languageSelection = NULL
) {
if ($extensionSelection === 'NULL') {
$extensionSelection = NULL;
......@@ -857,6 +1046,11 @@ class MainController extends AbstractController {
$constantSelection = NULL;
}
$this->session->setDataByKey('constantSelection', $constantSelection);
if ($languageSelection === 'NULL') {
$languageSelection = NULL;
}
$this->session->setDataByKey('languageSelection', $languageSelection);
}
/**
......@@ -985,6 +1179,7 @@ class MainController extends AbstractController {
);
}
}
}
?>
\ No newline at end of file
......@@ -330,7 +330,7 @@ class Functions {
$curAbsName = '';
$tree = [];
foreach ($langConsts as $constant) {
// add root
// add root TODO: Init rootLabel out of loop.
$rootLabel = LocalizationUtility::translate('function.const.treeview.root', 'lfeditor');
$tree[0][$rootLabel]['name'] = $rootLabel;
......
{namespace lfe=SGalinski\Lfeditor\ViewHelpers}
<lfe:addJavaScriptFile javaScriptFile="{f:uri.resource(path: 'Scripts/FormUtility.js')}" />
<lfe:addJavaScriptFile javaScriptFile="{f:uri.resource(path: 'Scripts/Lfeditor.js')}" />
<lfe:addCssFile cssFile="{f:uri.resource(path: 'StyleSheets/Lfeditor.css')}" />
<f:be.container enableClickMenu="FALSE" loadPrototype="FALSE" loadExtJs="FALSE">
......@@ -41,6 +42,9 @@
<f:be.menus.actionMenuItem label="{f:translate(key:'function.const.search.search')}"
controller="Main"
action="searchConstant" />
<f:be.menus.actionMenuItem label="{f:translate(key:'function.const.treeview.treeview')}"
controller="Main"
action="viewTree" />
</f:be.menus.actionMenu>
</div>
</div>
......
{namespace lfe=SGalinski\Lfeditor\ViewHelpers}
<lfe:extendedIf condition="{extensionSelection}" and="{languageFileSelection}" and2="{referenceLanguageOptions}">
<h2 class="uppercase">
<f:translate key="select.languageAndPattern" />
</h2>
<f:form.select name="languageSelection"
value="{languageSelection}"
options="{languageOptions}"
additionalAttributes="{onchange: 'submitForm(\'mainMenuForm\')'}"
/>
<f:form.select name="referenceLanguageSelection"
value="{referenceLanguageSelection}"
options="{referenceLanguageOptions}"
additionalAttributes="{onchange: 'submitForm(\'mainMenuForm\')'}"
/>
</lfe:extendedIf>
\ No newline at end of file
{namespace lfe=SGalinski\Lfeditor\ViewHelpers}
<f:for each="{fluidTree}" as="treeNode" key="constantKey">
<li>
<f:for each="{treeNode.icons}" iteration="iterator" as="icon" reverse="TRUE">
<lfe:extendedIf condition="{iterator.isLast}" and="{treeNode.children}">
<f:then>
<a href="javascript:openCloseTreeEntry(
'{f:uri.resource(path: 'Icons')}',
'ul-{constantKey}', 'icon-{constantKey}',
{treeNode.isBottom})">
<img id="icon-{constantKey}" src="{f:uri.resource(path: 'Icons/{icon.name}')}"
alt="{icon.name}" style="margin-left: {icon.marginLeft}px;" />
</a>
</f:then>
<f:else>
<img src="{f:uri.resource(path: 'Icons/{icon.name}')}" alt="{icon.name}"
style="margin-left: {icon.marginLeft}px;" />
</f:else>
</lfe:extendedIf>
</f:for>
<f:if condition="{treeNode.children}">
<f:then>
<a href="javascript:openCloseTreeEntry(
'{f:uri.resource(path: 'Icons')}', 'ul-{constantKey}', 'icon-{constantKey}', {treeNode.isBottom})">
{treeNode.label}
</a>
<ul id="ul-{constantKey}" class="tx-lfeditor-treeview"
style="{f:if(condition: '{treeHide}', then: 'display: none')}">
<f:render partial="TreeElement"
arguments="{fluidTree: '{treeNode.children}', treeHide: '{treeHide}'}" />
</ul>
</f:then>
<f:else>
<f:link.action action="prepareEditConstant"
arguments="{constantKey: '{constantKey}', closedNode: '{closedNode}'}">
<span class="tx-lfeditor-{f:if(condition: '{treeNode.type} == 2', then: 'specialMarkup')}{f:if(condition: '{treeNode.type} == 1', then: 'badMarkup')}{f:if(condition: '{treeNode.type} == 0', then: 'goodMarkup')}">
{treeNode.label}
</span>
</f:link.action>
</f:else>
</f:if>
</li>
</f:for>
\ No newline at end of file
{namespace lfe=SGalinski\Lfeditor\ViewHelpers}
<f:layout name="Default" />
<f:section name="selectItems">
<f:render partial="SelectLanguageFile" arguments="{_all}" />
<f:render partial="SelectLanguageAndReference" arguments="{_all}" />
</f:section>
<f:section name="main">
<lfe:extendedIf condition="{extensionSelection}" and="{languageFileSelection}">
<f:form id="contentForm" action="selectExplodeToken">
<h2 class="uppercase">
<f:translate key="select.explodeToken" />
</h2>
<p>
<f:form.textfield name="explodeToken" size="30" value="{explodeToken}" />
<span class="tx-lfeditor-submit">
<button type="submit">
<f:translate key="select.explodeToken" />
</button>
</span>
</p>
<h2 class="uppercase">
<f:translate key="function.const.treeview.treeview" />
</h2>
<fieldset class="tx-lfeditor-fieldset bgColor5">
<legend class="bgColor3">
<f:translate key="function.const.treeview.treeview" />
</legend>
<p class="tx-lfeditor-goodMarkup">
xyz -- <f:translate key="function.const.treeview.goodMarkupHint" />
</p>
<p class="tx-lfeditor-badMarkup">
xyz -- <f:translate key="function.const.treeview.badMarkupHint" />
</p>
<p class="tx-lfeditor-specialMarkup">
xyz -- <f:translate key="function.const.treeview.specialMarkupHint" />
</p>
<fieldset class="bgColor4">
<legend class="bgColor3">
<a href="javascript:hideUnHideAll()">
<f:translate key="function.const.treeview.hideUnhideAll" />
</a>
</legend>
<ul class="tx-lfeditor-treeview">
<li>
<a href="javascript:openCloseTreeEntry('{f:uri.resource(path: 'Icons')}', 'ul-Root', 'icon-Root', 1)">
<img id="icon-Root"
src="{f:uri.resource(path: 'Icons/{fluidTree.Root.icons.0.name}')}"
alt="{fluidTree.Root.icons.0.name}"
style="margin-left: {fluidTree.Root.icons.0.marginLeft}px;" />
{fluidTree.Root.label}
</a>
<f:if condition="{fluidTree.Root.children}">
<ul id="ul-Root" class="tx-lfeditor-treeview">
<f:render partial="TreeElement"
arguments="{fluidTree: '{fluidTree.Root.children}', treeHide: '{treeHide}'}" />
</ul>
</f:if>
</li>
</ul>
</fieldset>
</fieldset>
</f:form>
</lfe:extendedIf>
</f:section>
\ No newline at end of file
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
function submitBackupForm(filename, langFile, del, restore, deleteAll, origDiff) {
document.mainForm.elements['delete'].value = del;
document.mainForm.elements['restore'].value = restore;
......@@ -55,7 +79,61 @@ function openCloseTreeEntry(prefix, args) {
pic = pic + 'Bottom';
}
document.getElementById(arguments[i + 1]).src = prefix + 'res/images/tree' + pic + '.gif';
document.getElementById(arguments[i + 1]).alt = 'tree' + pic;
document.getElementById(arguments[i + 1]).src = prefix + '/tree' + pic + '.gif';
document.getElementById(arguments[i + 1]).alt = 'tree' + pic + '.gif';
}
}
var hideAll = null;
/**
* Folds and un folds all constants in tree, on tree view.
*/
function hideUnHideAll() {
if (hideAll === null) {
hideAll = document.getElementById('ul-Root').style.display !== 'none';
}
var ulIdRegex = /^ul-/;
var treeUlElements = [];
var allUl = document.getElementsByTagName('ul');
for (var iterator = allUl.length; iterator--;) {
if (ulIdRegex.test(allUl[iterator].id)) {
treeUlElements.push(allUl[iterator]);
}
}
var imageIdRegex = /^icon-/;
var imageMinusSrcRegex = /treeMinus/;
var imagePlusSrcRegex = /treePlus/;
var treeImgMinusElements = [];
var treeImgPlusElements = [];
var allImg = document.getElementsByTagName('img');
for (var iterator = allImg.length; iterator--;) {
if (imageIdRegex.test(allImg[iterator].id)) {
if (imageMinusSrcRegex.test(allImg[iterator].src)) {
treeImgMinusElements.push(allImg[iterator]);
} else if (imagePlusSrcRegex.test(allImg[iterator].src)) {
treeImgPlusElements.push(allImg[iterator]);
}
}
}
if (hideAll) {
for (var iterator = treeUlElements.length; iterator--;) {
treeUlElements[iterator].style.display = 'none';
}
for (var iterator = treeImgMinusElements.length; iterator--;) {
treeImgMinusElements[iterator].src = treeImgMinusElements[iterator].src.replace(imageMinusSrcRegex, 'treePlus');
}
hideAll = false;
} else {
for (var iterator = treeUlElements.length; iterator--;) {
treeUlElements[iterator].style.display = '';
}
for (var iterator = treeImgPlusElements.length; iterator--;) {
treeImgPlusElements[iterator].src = treeImgPlusElements[iterator].src.replace(imagePlusSrcRegex, 'treeMinus');
}
hideAll = true;
}
}
\ No newline at end of file
......@@ -199,22 +199,21 @@ fieldset.tx-lfeditor-fieldset fieldset dd {
}
/* tree view */
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview,
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview dt,
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview dd {
.tx-lfeditor-fieldset ul.tx-lfeditor-treeview {
margin: 0;
padding: 0;
}
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview dt,
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview dd {
list-style-type: none;
clear: left;
}
.tx-lfeditor-fieldset dl.tx-lfeditor-treeview img {
.tx-lfeditor-fieldset ul.tx-lfeditor-treeview img {
float: left;
}
fieldset.tx-lfeditor-fieldset fieldset ul li {
font-weight: bold;
}
/* textarea resizer */
.handle-normal, .handle-highlight {
padding: 0;
......
......@@ -18,7 +18,8 @@ if (TYPO3_MODE == 'BE') {
addConstant, addConstantChangeSelection, addConstantSave,
deleteConstant, deleteConstantChangeSelection, deleteConstantSave,
renameConstant, renameConstantChangeSelection, renameConstantSave,
searchConstant, searchConstantChangeSelection, searchConstantSearch, prepareEditConstant',
searchConstant, searchConstantChangeSelection, searchConstantSearch, prepareEditConstant,
viewTree, viewTreeChangeSelection, selectExplodeToken',
],
[
'access' => 'user,group',
......
......@@ -22,6 +22,7 @@
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
......@@ -368,7 +369,7 @@ class tx_lfeditor_mod1_template {
// generate output
$content .= '<fieldset class="bgColor4"> <legend class="bgColor3">' .
'<a href="javascript:openCloseTreeEntry(\'' . t3lib_extMgm::extRelPath(
'<a href="javascript:openCloseTreeEntry(\'' . ExtensionManagementUtility::extRelPath(
'lfeditor'
) . '\', ' . $JSArgs . ');">' .
LocalizationUtility::translate('function.const.treeview.hideUnhideAll') . '</a>' .
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment