Project

General

Profile

Bug #68463 ยป CollectionService.php

Torsten Fink, 2016-03-01 16:19

 
<?php
namespace TYPO3\CMS\Workspaces\Service\Dependency;

/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Workspaces\Service\GridDataService;
use TYPO3\CMS\Version\Dependency;

/**
* Service to collect dependent elements.
*
* @author Oliver Hader <oliver.hader@typo3.org>
*/
class CollectionService implements \TYPO3\CMS\Core\SingletonInterface {

/**
* @var \TYPO3\CMS\Core\DataHandling\DataHandler
*/
protected $dataHandler;

/**
* @var \TYPO3\CMS\Version\Dependency\ElementEntityProcessor
*/
protected $elementEntityProcessor;

/**
* @var Dependency\DependencyResolver
*/
protected $dependencyResolver;

/**
* @var array
*/
protected $dataArray;

/**
* @var array
*/
protected $nestedDataArray;

/**
* @var array
*/
protected $dependenciesChecked = array();

/**
* @return Dependency\DependencyResolver
*/
public function getDependencyResolver() {
if (!isset($this->dependencyResolver)) {
$this->dependencyResolver = GeneralUtility::makeInstance('TYPO3\\CMS\\Version\\Dependency\\DependencyResolver');
$this->dependencyResolver->setOuterMostParentsRequireReferences(TRUE);
$this->dependencyResolver->setWorkspace($this->getWorkspace());

$this->dependencyResolver->setEventCallback(
Dependency\ElementEntity::EVENT_Construct,
$this->getDependencyCallback('createNewDependentElementCallback')
);

$this->dependencyResolver->setEventCallback(
Dependency\ElementEntity::EVENT_CreateChildReference,
$this->getDependencyCallback('createNewDependentElementChildReferenceCallback')
);

$this->dependencyResolver->setEventCallback(
Dependency\ElementEntity::EVENT_CreateParentReference,
$this->getDependencyCallback('createNewDependentElementParentReferenceCallback')
);
}

return $this->dependencyResolver;
}

/**
* Gets a new callback to be used in the dependency resolver utility.
*
* @param string $method
* @param array $targetArguments
* @return Dependency\EventCallback
*/
protected function getDependencyCallback($method, array $targetArguments = array()) {
return GeneralUtility::makeInstance(
'TYPO3\\CMS\\Version\\Dependency\\EventCallback',
$this->getElementEntityProcessor(), $method, $targetArguments
);
}

/**
* Gets the element entity processor.
*
* @return \TYPO3\CMS\Version\Dependency\ElementEntityProcessor
*/
protected function getElementEntityProcessor() {
if (!isset($this->elementEntityProcessor)) {
$this->elementEntityProcessor = GeneralUtility::makeInstance(
'TYPO3\\CMS\\Version\\Dependency\\ElementEntityProcessor'
);
$this->elementEntityProcessor->setWorkspace($this->getWorkspace());
}
return $this->elementEntityProcessor;
}

/**
* Gets the current workspace id.
*
* @return int
*/
protected function getWorkspace() {
return (int)$GLOBALS['BE_USER']->workspace;
}

/**
* Processes the data array
*
* @param array $dataArray
* @return array
*/
public function process(array $dataArray) {
$collection = 0;
$this->dataArray = $dataArray;
$this->nestedDataArray = array();

$outerMostParents = $this->getDependencyResolver()->getOuterMostParents();

if (empty($outerMostParents)) {
return $this->dataArray;
}

// For each outer most parent, get all nested child elements:
foreach ($outerMostParents as $outerMostParent) {
$this->resolveDataArrayChildDependencies(
$outerMostParent,
++$collection
);
}

$processedDataArray = $this->finalize($this->dataArray);

unset($this->dataArray);
unset($this->nestedDataArray);

return $processedDataArray;
}

/**
* Applies structures to instance data array and
* ensures children are added below accordant parent
*
* @param array $dataArray
* @return array
*/
protected function finalize(array $dataArray) {
$processedDataArray = array();
foreach ($dataArray as $dataElement) {
$dataElementIdentifier = $dataElement['id'];
$processedDataArray[] = $dataElement;
// Insert children (if any)
if (!empty($this->nestedDataArray[$dataElementIdentifier])) {
$processedDataArray = array_merge(
$processedDataArray,
$this->finalize($this->nestedDataArray[$dataElementIdentifier])
);
unset($this->nestedDataArray[$dataElementIdentifier]);
}
}

return $processedDataArray;
}

/**
* Resolves nested child dependencies.
*
* @param Dependency\ElementEntity $parent
* @param int $collection
* @param string $nextParentIdentifier
* @param int $collectionLevel
*/
protected function resolveDataArrayChildDependencies(Dependency\ElementEntity $parent, $collection, $nextParentIdentifier = '', $collectionLevel = 0) {
$parentIdentifier = $parent->__toString();
if(!isset($this->dependenciesChecked[$parentIdentifier])) {
$this->dependenciesChecked[$parentIdentifier] = true;
}

$parentIsSet = isset($this->dataArray[$parentIdentifier]);

if ($parentIsSet) {
$this->dataArray[$parentIdentifier][GridDataService::GridColumn_Collection] = $collection;
$this->dataArray[$parentIdentifier][GridDataService::GridColumn_CollectionLevel] = $collectionLevel;
$this->dataArray[$parentIdentifier][GridDataService::GridColumn_CollectionCurrent] = md5($parentIdentifier);
$this->dataArray[$parentIdentifier][GridDataService::GridColumn_CollectionChildren] = count($parent->getChildren());
$nextParentIdentifier = $parentIdentifier;
$collectionLevel++;
}

foreach ($parent->getChildren() as $child) {
$childIdentifier = $child->getElement()->__toString();

if(isset($this->dependenciesChecked[$childIdentifier])) {
continue;
}

$this->resolveDataArrayChildDependencies(
$child->getElement(),
$collection,
$nextParentIdentifier,
$collectionLevel
);

if (!empty($nextParentIdentifier) && isset($this->dataArray[$childIdentifier])) {
// Remove from dataArray, but collect to process later
// and add it just next to the accordant parent element
$this->dataArray[$childIdentifier][GridDataService::GridColumn_CollectionParent] = md5($nextParentIdentifier);
$this->nestedDataArray[$nextParentIdentifier][] = $this->dataArray[$childIdentifier];
unset($this->dataArray[$childIdentifier]);
}
}
}

}
    (1-1/1)