| @@ -58,8 +58,7 @@ | ||
| 58 | 58 |      { | 
| 59 | 59 | // Resolve the table name. | 
| 60 | 60 | self::$currentTable = $tableNameOrContentObject instanceof Content ? | 
| 61 | - $tableNameOrContentObject->getDataType() : | |
| 62 | - $tableNameOrContentObject; | |
| 61 | + $tableNameOrContentObject->getDataType() : $tableNameOrContentObject; | |
| 63 | 62 | return $this; | 
| 64 | 63 | } | 
| 65 | 64 | |
| @@ -18,92 +18,92 @@ | ||
| 18 | 18 | */ | 
| 19 | 19 | class Field implements SingletonInterface | 
| 20 | 20 |  { | 
| 21 | - /** | |
| 22 | - * @var string | |
| 23 | - */ | |
| 24 | - protected static $currentField; | |
| 21 | + /** | |
| 22 | + * @var string | |
| 23 | + */ | |
| 24 | + protected static $currentField; | |
| 25 | 25 | |
| 26 | - /** | |
| 27 | - * @var string | |
| 28 | - */ | |
| 29 | - protected static $currentTable; | |
| 26 | + /** | |
| 27 | + * @var string | |
| 28 | + */ | |
| 29 | + protected static $currentTable; | |
| 30 | 30 | |
| 31 | - /** | |
| 32 | - * @var array | |
| 33 | - */ | |
| 34 | - protected $storage = []; | |
| 31 | + /** | |
| 32 | + * @var array | |
| 33 | + */ | |
| 34 | + protected $storage = []; | |
| 35 | 35 | |
| 36 | - /** | |
| 37 | - * @param string $fieldName | |
| 38 | - * @return $this | |
| 39 | - * @throws \InvalidArgumentException | |
| 40 | - */ | |
| 41 | - public static function name($fieldName) | |
| 42 | -    { | |
| 43 | - self::$currentField = $fieldName; | |
| 44 | - self::$currentTable = ''; // reset the table name value. | |
| 45 | - return GeneralUtility::makeInstance(self::class); | |
| 46 | - } | |
| 36 | + /** | |
| 37 | + * @param string $fieldName | |
| 38 | + * @return $this | |
| 39 | + * @throws \InvalidArgumentException | |
| 40 | + */ | |
| 41 | + public static function name($fieldName) | |
| 42 | +	{ | |
| 43 | + self::$currentField = $fieldName; | |
| 44 | + self::$currentTable = ''; // reset the table name value. | |
| 45 | + return GeneralUtility::makeInstance(self::class); | |
| 46 | + } | |
| 47 | 47 | |
| 48 | - /** | |
| 49 | - * @param string|Content $tableNameOrContentObject | |
| 50 | - * @return $this | |
| 51 | - */ | |
| 52 | - public function of($tableNameOrContentObject) | |
| 53 | -    { | |
| 54 | - // Resolve the table name. | |
| 55 | - self::$currentTable = $tableNameOrContentObject instanceof Content ? | |
| 56 | - $tableNameOrContentObject->getDataType() : | |
| 57 | - $tableNameOrContentObject; | |
| 58 | - return $this; | |
| 59 | - } | |
| 48 | + /** | |
| 49 | + * @param string|Content $tableNameOrContentObject | |
| 50 | + * @return $this | |
| 51 | + */ | |
| 52 | + public function of($tableNameOrContentObject) | |
| 53 | +	{ | |
| 54 | + // Resolve the table name. | |
| 55 | + self::$currentTable = $tableNameOrContentObject instanceof Content ? | |
| 56 | + $tableNameOrContentObject->getDataType() : | |
| 57 | + $tableNameOrContentObject; | |
| 58 | + return $this; | |
| 59 | + } | |
| 60 | 60 | |
| 61 | - public function toPropertyName() | |
| 62 | -    { | |
| 63 | - $fieldName = $this->getFieldName(); | |
| 64 | - $tableName = $this->getTableName(); | |
| 61 | + public function toPropertyName() | |
| 62 | +	{ | |
| 63 | + $fieldName = $this->getFieldName(); | |
| 64 | + $tableName = $this->getTableName(); | |
| 65 | 65 | |
| 66 | -        if (empty($this->storage[$tableName][$fieldName])) { | |
| 67 | -            if (!array_key_exists($tableName, $this->storage)) { | |
| 68 | - $this->storage[$tableName] = []; | |
| 69 | - } | |
| 66 | +		if (empty($this->storage[$tableName][$fieldName])) { | |
| 67 | +			if (!array_key_exists($tableName, $this->storage)) { | |
| 68 | + $this->storage[$tableName] = []; | |
| 69 | + } | |
| 70 | 70 | |
| 71 | - // Special case when the field name does not follow the conventions "field_name" => "fieldName". | |
| 72 | - // Rely on mapping for those cases. | |
| 73 | -            if (!empty($GLOBALS['TCA'][$tableName]['vidi']['mappings'][$fieldName])) { | |
| 74 | - $propertyName = $GLOBALS['TCA'][$tableName]['vidi']['mappings'][$fieldName]; | |
| 75 | -            } else { | |
| 76 | - $propertyName = GeneralUtility::underscoredToLowerCamelCase($fieldName); | |
| 77 | - } | |
| 71 | + // Special case when the field name does not follow the conventions "field_name" => "fieldName". | |
| 72 | + // Rely on mapping for those cases. | |
| 73 | +			if (!empty($GLOBALS['TCA'][$tableName]['vidi']['mappings'][$fieldName])) { | |
| 74 | + $propertyName = $GLOBALS['TCA'][$tableName]['vidi']['mappings'][$fieldName]; | |
| 75 | +			} else { | |
| 76 | + $propertyName = GeneralUtility::underscoredToLowerCamelCase($fieldName); | |
| 77 | + } | |
| 78 | 78 | |
| 79 | - $this->storage[$tableName][$fieldName] = $propertyName; | |
| 80 | - } | |
| 79 | + $this->storage[$tableName][$fieldName] = $propertyName; | |
| 80 | + } | |
| 81 | 81 | |
| 82 | - return $this->storage[$tableName][$fieldName]; | |
| 83 | - } | |
| 82 | + return $this->storage[$tableName][$fieldName]; | |
| 83 | + } | |
| 84 | 84 | |
| 85 | - /** | |
| 86 | - * @return string | |
| 87 | - * @throws \RuntimeException | |
| 88 | - */ | |
| 89 | - protected function getFieldName() | |
| 90 | -    { | |
| 91 | - $fieldName = self::$currentField; | |
| 92 | -        if (empty($fieldName)) { | |
| 93 | -            throw new \RuntimeException('I could not find a field name value.', 1403203290); | |
| 94 | - } | |
| 95 | - return $fieldName; | |
| 96 | - } | |
| 85 | + /** | |
| 86 | + * @return string | |
| 87 | + * @throws \RuntimeException | |
| 88 | + */ | |
| 89 | + protected function getFieldName() | |
| 90 | +	{ | |
| 91 | + $fieldName = self::$currentField; | |
| 92 | +		if (empty($fieldName)) { | |
| 93 | +			throw new \RuntimeException('I could not find a field name value.', 1403203290); | |
| 94 | + } | |
| 95 | + return $fieldName; | |
| 96 | + } | |
| 97 | 97 | |
| 98 | - /** | |
| 99 | - * @return string | |
| 100 | - */ | |
| 101 | - protected function getTableName() | |
| 102 | -    { | |
| 103 | - $tableName = self::$currentTable; | |
| 104 | -        if (empty($tableName)) { | |
| 105 | -            throw new \RuntimeException('I could not find a table name value.', 1403203291); | |
| 106 | - } | |
| 107 | - return $tableName; | |
| 108 | - } | |
| 98 | + /** | |
| 99 | + * @return string | |
| 100 | + */ | |
| 101 | + protected function getTableName() | |
| 102 | +	{ | |
| 103 | + $tableName = self::$currentTable; | |
| 104 | +		if (empty($tableName)) { | |
| 105 | +			throw new \RuntimeException('I could not find a table name value.', 1403203291); | |
| 106 | + } | |
| 107 | + return $tableName; | |
| 108 | + } | |
| 109 | 109 | } | 
| @@ -105,7 +105,7 @@ | ||
| 105 | 105 | $replace = $structure[2]; | 
| 106 | 106 | |
| 107 | 107 | // Perhaps needs to be improved here if $search contains "/" precisely. | 
| 108 | -            $updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue); | |
| 108 | +            $updateValue = preg_replace('/'.$search.'/isU', $replace, $currentValue); | |
| 109 | 109 | } | 
| 110 | 110 | return $updateValue; | 
| 111 | 111 | } | 
| @@ -20,109 +20,109 @@ | ||
| 20 | 20 | */ | 
| 21 | 21 | class MarkerProcessor implements SingletonInterface | 
| 22 | 22 |  { | 
| 23 | - /** | |
| 24 | - * @var array | |
| 25 | - */ | |
| 26 | - protected $wellKnownMarkers = array( | |
| 27 | -        '{*}', | |
| 28 | -        '{counter}', | |
| 29 | -        '{date}', | |
| 30 | -        '{creation_date}' | |
| 31 | - ); | |
| 23 | + /** | |
| 24 | + * @var array | |
| 25 | + */ | |
| 26 | + protected $wellKnownMarkers = array( | |
| 27 | +		'{*}', | |
| 28 | +		'{counter}', | |
| 29 | +		'{date}', | |
| 30 | +		'{creation_date}' | |
| 31 | + ); | |
| 32 | 32 | |
| 33 | - /** | |
| 34 | - * @param ProcessContentDataSignalArguments $signalArguments | |
| 35 | - * @return array | |
| 36 | - */ | |
| 37 | - public function processMarkers(ProcessContentDataSignalArguments $signalArguments) | |
| 38 | -    { | |
| 39 | - $contentData = $signalArguments->getContentData(); | |
| 40 | - $creationTime = $this->getCreationTime($signalArguments); | |
| 33 | + /** | |
| 34 | + * @param ProcessContentDataSignalArguments $signalArguments | |
| 35 | + * @return array | |
| 36 | + */ | |
| 37 | + public function processMarkers(ProcessContentDataSignalArguments $signalArguments) | |
| 38 | +	{ | |
| 39 | + $contentData = $signalArguments->getContentData(); | |
| 40 | + $creationTime = $this->getCreationTime($signalArguments); | |
| 41 | 41 | |
| 42 | - // Process markers | |
| 43 | -        foreach ($signalArguments->getContentData() as $fieldName => $updateValue) { | |
| 44 | -            if (is_scalar($updateValue)) { | |
| 45 | - $currentValue = $this->getContentObjectResolver()->getValue( | |
| 46 | - $signalArguments->getContentObject(), | |
| 47 | - $signalArguments->getFieldNameAndPath(), | |
| 48 | - $fieldName, | |
| 49 | - $signalArguments->getLanguage() | |
| 50 | - ); | |
| 51 | - $counter = $signalArguments->getCounter(); | |
| 42 | + // Process markers | |
| 43 | +		foreach ($signalArguments->getContentData() as $fieldName => $updateValue) { | |
| 44 | +			if (is_scalar($updateValue)) { | |
| 45 | + $currentValue = $this->getContentObjectResolver()->getValue( | |
| 46 | + $signalArguments->getContentObject(), | |
| 47 | + $signalArguments->getFieldNameAndPath(), | |
| 48 | + $fieldName, | |
| 49 | + $signalArguments->getLanguage() | |
| 50 | + ); | |
| 51 | + $counter = $signalArguments->getCounter(); | |
| 52 | 52 | |
| 53 | - $updateValue = $this->searchAndReplace($updateValue, $currentValue); | |
| 54 | - $updateValue = $this->replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime); | |
| 53 | + $updateValue = $this->searchAndReplace($updateValue, $currentValue); | |
| 54 | + $updateValue = $this->replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime); | |
| 55 | 55 | |
| 56 | - $contentData[$fieldName] = $updateValue; | |
| 57 | - } | |
| 58 | - } | |
| 56 | + $contentData[$fieldName] = $updateValue; | |
| 57 | + } | |
| 58 | + } | |
| 59 | 59 | |
| 60 | - $signalArguments->setContentData($contentData); | |
| 61 | - return array($signalArguments); | |
| 62 | - } | |
| 60 | + $signalArguments->setContentData($contentData); | |
| 61 | + return array($signalArguments); | |
| 62 | + } | |
| 63 | 63 | |
| 64 | - /** | |
| 65 | - * @param string $updateValue | |
| 66 | - * @param string $currentValue | |
| 67 | - * @param int $counter | |
| 68 | - * @param $creationTime | |
| 69 | - * @return string | |
| 70 | - */ | |
| 71 | - protected function replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime) | |
| 72 | -    { | |
| 73 | - // Replaces values. | |
| 74 | - $replaces = array( | |
| 75 | - $currentValue, | |
| 76 | - $counter, | |
| 77 | - date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']), | |
| 78 | - date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $creationTime), | |
| 79 | - ); | |
| 64 | + /** | |
| 65 | + * @param string $updateValue | |
| 66 | + * @param string $currentValue | |
| 67 | + * @param int $counter | |
| 68 | + * @param $creationTime | |
| 69 | + * @return string | |
| 70 | + */ | |
| 71 | + protected function replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime) | |
| 72 | +	{ | |
| 73 | + // Replaces values. | |
| 74 | + $replaces = array( | |
| 75 | + $currentValue, | |
| 76 | + $counter, | |
| 77 | + date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']), | |
| 78 | + date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $creationTime), | |
| 79 | + ); | |
| 80 | 80 | |
| 81 | - // Replace me! | |
| 82 | - return str_replace($this->wellKnownMarkers, $replaces, $updateValue); | |
| 83 | - } | |
| 81 | + // Replace me! | |
| 82 | + return str_replace($this->wellKnownMarkers, $replaces, $updateValue); | |
| 83 | + } | |
| 84 | 84 | |
| 85 | - /** | |
| 86 | - * @param string $updateValue | |
| 87 | - * @param string $currentValue | |
| 88 | - * @return string | |
| 89 | - */ | |
| 90 | - protected function searchAndReplace($updateValue, $currentValue) | |
| 91 | -    { | |
| 92 | -        if (strpos($updateValue, 's/') !== false) { | |
| 93 | -            $structure = explode('/', $updateValue); | |
| 94 | - $search = $structure[1]; | |
| 95 | - $replace = $structure[2]; | |
| 85 | + /** | |
| 86 | + * @param string $updateValue | |
| 87 | + * @param string $currentValue | |
| 88 | + * @return string | |
| 89 | + */ | |
| 90 | + protected function searchAndReplace($updateValue, $currentValue) | |
| 91 | +	{ | |
| 92 | +		if (strpos($updateValue, 's/') !== false) { | |
| 93 | +			$structure = explode('/', $updateValue); | |
| 94 | + $search = $structure[1]; | |
| 95 | + $replace = $structure[2]; | |
| 96 | 96 | |
| 97 | - // Perhaps needs to be improved here if $search contains "/" precisely. | |
| 98 | -            $updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue); | |
| 99 | - } | |
| 100 | - return $updateValue; | |
| 101 | - } | |
| 97 | + // Perhaps needs to be improved here if $search contains "/" precisely. | |
| 98 | +			$updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue); | |
| 99 | + } | |
| 100 | + return $updateValue; | |
| 101 | + } | |
| 102 | 102 | |
| 103 | - /** | |
| 104 | - * @param ProcessContentDataSignalArguments $signalArguments | |
| 105 | - * @return int | |
| 106 | - */ | |
| 107 | - protected function getCreationTime(ProcessContentDataSignalArguments $signalArguments) | |
| 108 | -    { | |
| 109 | - $creationTime = 0; | |
| 110 | - $creationTimeField = Tca::table($signalArguments->getContentObject()->getDataType())->getTimeCreationField(); | |
| 111 | -        if ($creationTimeField) { | |
| 112 | - $creationTime = $this->getContentObjectResolver()->getValue( | |
| 113 | - $signalArguments->getContentObject(), | |
| 114 | - $signalArguments->getFieldNameAndPath(), | |
| 115 | - $creationTimeField | |
| 116 | - ); | |
| 117 | - } | |
| 118 | - return $creationTime; | |
| 119 | - } | |
| 103 | + /** | |
| 104 | + * @param ProcessContentDataSignalArguments $signalArguments | |
| 105 | + * @return int | |
| 106 | + */ | |
| 107 | + protected function getCreationTime(ProcessContentDataSignalArguments $signalArguments) | |
| 108 | +	{ | |
| 109 | + $creationTime = 0; | |
| 110 | + $creationTimeField = Tca::table($signalArguments->getContentObject()->getDataType())->getTimeCreationField(); | |
| 111 | +		if ($creationTimeField) { | |
| 112 | + $creationTime = $this->getContentObjectResolver()->getValue( | |
| 113 | + $signalArguments->getContentObject(), | |
| 114 | + $signalArguments->getFieldNameAndPath(), | |
| 115 | + $creationTimeField | |
| 116 | + ); | |
| 117 | + } | |
| 118 | + return $creationTime; | |
| 119 | + } | |
| 120 | 120 | |
| 121 | - /** | |
| 122 | - * @return ContentObjectResolver | |
| 123 | - */ | |
| 124 | - protected function getContentObjectResolver() | |
| 125 | -    { | |
| 126 | - return GeneralUtility::makeInstance(ContentObjectResolver::class); | |
| 127 | - } | |
| 121 | + /** | |
| 122 | + * @return ContentObjectResolver | |
| 123 | + */ | |
| 124 | + protected function getContentObjectResolver() | |
| 125 | +	{ | |
| 126 | + return GeneralUtility::makeInstance(ContentObjectResolver::class); | |
| 127 | + } | |
| 128 | 128 | } | 
| @@ -71,7 +71,7 @@ | ||
| 71 | 71 | $relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName); | 
| 72 | 72 | |
| 73 | 73 |                  foreach ($values as $value) { | 
| 74 | - $appendOrRemove = $savingBehavior . 'Relations'; | |
| 74 | + $appendOrRemove = $savingBehavior.'Relations'; | |
| 75 | 75 | $relatedValues = $this->$appendOrRemove($value, $relatedValues); | 
| 76 | 76 | } | 
| 77 | 77 | |
| @@ -23,116 +23,116 @@ | ||
| 23 | 23 | */ | 
| 24 | 24 | class ContentObjectProcessor implements SingletonInterface | 
| 25 | 25 |  { | 
| 26 | - /** | |
| 27 | - * @param ProcessContentDataSignalArguments $signalArguments | |
| 28 | - * @return array | |
| 29 | - */ | |
| 30 | - public function processRelations(ProcessContentDataSignalArguments $signalArguments) | |
| 31 | -    { | |
| 32 | - $contentObject = $signalArguments->getContentObject(); | |
| 33 | - $fieldNameAndPath = $signalArguments->getFieldNameAndPath(); | |
| 34 | - $contentData = $signalArguments->getContentData(); | |
| 35 | - $savingBehavior = $signalArguments->getSavingBehavior(); | |
| 36 | - | |
| 37 | -        if ($savingBehavior !== SavingBehavior::REPLACE) { | |
| 38 | - $contentData = $this->appendOrRemoveRelations($contentObject, $fieldNameAndPath, $contentData, $savingBehavior); | |
| 39 | - $signalArguments->setContentData($contentData); | |
| 40 | - } | |
| 41 | - | |
| 42 | - return array($signalArguments); | |
| 43 | - } | |
| 44 | - | |
| 45 | - /** | |
| 46 | - * @param Content $object | |
| 47 | - * @param $fieldNameAndPath | |
| 48 | - * @param array $contentData | |
| 49 | - * @param string $savingBehavior | |
| 50 | - * @return array | |
| 51 | - */ | |
| 52 | - protected function appendOrRemoveRelations(Content $object, $fieldNameAndPath, array $contentData, $savingBehavior) | |
| 53 | -    { | |
| 54 | -        foreach ($contentData as $fieldName => $values) { | |
| 55 | - $resolvedObject = $this->getContentObjectResolver()->getObject($object, $fieldNameAndPath); | |
| 56 | - | |
| 57 | -            if (Tca::table($resolvedObject)->field($fieldName)->hasMany()) { | |
| 58 | - // true means CSV values must be converted to array. | |
| 59 | -                if (!is_array($values)) { | |
| 60 | -                    $values = GeneralUtility::trimExplode(',', $values); | |
| 61 | - } | |
| 62 | - $relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName); | |
| 63 | - | |
| 64 | -                foreach ($values as $value) { | |
| 65 | - $appendOrRemove = $savingBehavior . 'Relations'; | |
| 66 | - $relatedValues = $this->$appendOrRemove($value, $relatedValues); | |
| 67 | - } | |
| 68 | - | |
| 69 | - $contentData[$fieldName] = $relatedValues; | |
| 70 | - } | |
| 71 | - } | |
| 72 | - return $contentData; | |
| 73 | - } | |
| 74 | - | |
| 75 | - /** | |
| 76 | - * @param $value | |
| 77 | - * @param array $relatedValues | |
| 78 | - * @return array | |
| 79 | - */ | |
| 80 | - protected function appendRelations($value, array $relatedValues) | |
| 81 | -    { | |
| 82 | -        if (!in_array($value, $relatedValues)) { | |
| 83 | - $relatedValues[] = $value; | |
| 84 | - } | |
| 85 | - return $relatedValues; | |
| 86 | - } | |
| 87 | - | |
| 88 | - /** | |
| 89 | - * @param $value | |
| 90 | - * @param array $relatedValues | |
| 91 | - * @return array | |
| 92 | - */ | |
| 93 | - protected function removeRelations($value, array $relatedValues) | |
| 94 | -    { | |
| 95 | -        if (in_array($value, $relatedValues)) { | |
| 96 | - $key = array_search($value, $relatedValues); | |
| 97 | - unset($relatedValues[$key]); | |
| 98 | - } | |
| 99 | - return $relatedValues; | |
| 100 | - } | |
| 101 | - | |
| 102 | - /** | |
| 103 | - * @param Content $object | |
| 104 | - * @param string $fieldNameAndPath | |
| 105 | - * @param string $fieldName | |
| 106 | - * @return array | |
| 107 | - */ | |
| 108 | - protected function getRelatedValues(Content $object, $fieldNameAndPath, $fieldName) | |
| 109 | -    { | |
| 110 | - $values = []; | |
| 111 | - $relatedContentObjects = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, $fieldName); | |
| 112 | - | |
| 113 | -        if (is_array($relatedContentObjects)) { | |
| 114 | - /** @var Content $relatedContentObject */ | |
| 115 | -            foreach ($relatedContentObjects as $relatedContentObject) { | |
| 116 | - $values[] = $relatedContentObject->getUid(); | |
| 117 | - } | |
| 118 | - } | |
| 119 | - | |
| 120 | - return $values; | |
| 121 | - } | |
| 122 | - | |
| 123 | - /** | |
| 124 | - * @return ContentObjectResolver|object | |
| 125 | - */ | |
| 126 | - protected function getContentObjectResolver() | |
| 127 | -    { | |
| 128 | - return GeneralUtility::makeInstance(ContentObjectResolver::class); | |
| 129 | - } | |
| 130 | - | |
| 131 | - /** | |
| 132 | - * @return FieldPathResolver|object | |
| 133 | - */ | |
| 134 | - protected function getFieldPathResolver() | |
| 135 | -    { | |
| 136 | - return GeneralUtility::makeInstance(FieldPathResolver::class); | |
| 137 | - } | |
| 26 | + /** | |
| 27 | + * @param ProcessContentDataSignalArguments $signalArguments | |
| 28 | + * @return array | |
| 29 | + */ | |
| 30 | + public function processRelations(ProcessContentDataSignalArguments $signalArguments) | |
| 31 | +	{ | |
| 32 | + $contentObject = $signalArguments->getContentObject(); | |
| 33 | + $fieldNameAndPath = $signalArguments->getFieldNameAndPath(); | |
| 34 | + $contentData = $signalArguments->getContentData(); | |
| 35 | + $savingBehavior = $signalArguments->getSavingBehavior(); | |
| 36 | + | |
| 37 | +		if ($savingBehavior !== SavingBehavior::REPLACE) { | |
| 38 | + $contentData = $this->appendOrRemoveRelations($contentObject, $fieldNameAndPath, $contentData, $savingBehavior); | |
| 39 | + $signalArguments->setContentData($contentData); | |
| 40 | + } | |
| 41 | + | |
| 42 | + return array($signalArguments); | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * @param Content $object | |
| 47 | + * @param $fieldNameAndPath | |
| 48 | + * @param array $contentData | |
| 49 | + * @param string $savingBehavior | |
| 50 | + * @return array | |
| 51 | + */ | |
| 52 | + protected function appendOrRemoveRelations(Content $object, $fieldNameAndPath, array $contentData, $savingBehavior) | |
| 53 | +	{ | |
| 54 | +		foreach ($contentData as $fieldName => $values) { | |
| 55 | + $resolvedObject = $this->getContentObjectResolver()->getObject($object, $fieldNameAndPath); | |
| 56 | + | |
| 57 | +			if (Tca::table($resolvedObject)->field($fieldName)->hasMany()) { | |
| 58 | + // true means CSV values must be converted to array. | |
| 59 | +				if (!is_array($values)) { | |
| 60 | +					$values = GeneralUtility::trimExplode(',', $values); | |
| 61 | + } | |
| 62 | + $relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName); | |
| 63 | + | |
| 64 | +				foreach ($values as $value) { | |
| 65 | + $appendOrRemove = $savingBehavior . 'Relations'; | |
| 66 | + $relatedValues = $this->$appendOrRemove($value, $relatedValues); | |
| 67 | + } | |
| 68 | + | |
| 69 | + $contentData[$fieldName] = $relatedValues; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + return $contentData; | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * @param $value | |
| 77 | + * @param array $relatedValues | |
| 78 | + * @return array | |
| 79 | + */ | |
| 80 | + protected function appendRelations($value, array $relatedValues) | |
| 81 | +	{ | |
| 82 | +		if (!in_array($value, $relatedValues)) { | |
| 83 | + $relatedValues[] = $value; | |
| 84 | + } | |
| 85 | + return $relatedValues; | |
| 86 | + } | |
| 87 | + | |
| 88 | + /** | |
| 89 | + * @param $value | |
| 90 | + * @param array $relatedValues | |
| 91 | + * @return array | |
| 92 | + */ | |
| 93 | + protected function removeRelations($value, array $relatedValues) | |
| 94 | +	{ | |
| 95 | +		if (in_array($value, $relatedValues)) { | |
| 96 | + $key = array_search($value, $relatedValues); | |
| 97 | + unset($relatedValues[$key]); | |
| 98 | + } | |
| 99 | + return $relatedValues; | |
| 100 | + } | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * @param Content $object | |
| 104 | + * @param string $fieldNameAndPath | |
| 105 | + * @param string $fieldName | |
| 106 | + * @return array | |
| 107 | + */ | |
| 108 | + protected function getRelatedValues(Content $object, $fieldNameAndPath, $fieldName) | |
| 109 | +	{ | |
| 110 | + $values = []; | |
| 111 | + $relatedContentObjects = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, $fieldName); | |
| 112 | + | |
| 113 | +		if (is_array($relatedContentObjects)) { | |
| 114 | + /** @var Content $relatedContentObject */ | |
| 115 | +			foreach ($relatedContentObjects as $relatedContentObject) { | |
| 116 | + $values[] = $relatedContentObject->getUid(); | |
| 117 | + } | |
| 118 | + } | |
| 119 | + | |
| 120 | + return $values; | |
| 121 | + } | |
| 122 | + | |
| 123 | + /** | |
| 124 | + * @return ContentObjectResolver|object | |
| 125 | + */ | |
| 126 | + protected function getContentObjectResolver() | |
| 127 | +	{ | |
| 128 | + return GeneralUtility::makeInstance(ContentObjectResolver::class); | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * @return FieldPathResolver|object | |
| 133 | + */ | |
| 134 | + protected function getFieldPathResolver() | |
| 135 | +	{ | |
| 136 | + return GeneralUtility::makeInstance(FieldPathResolver::class); | |
| 137 | + } | |
| 138 | 138 | } | 
| @@ -484,7 +484,7 @@ | ||
| 484 | 484 | && isset($this->tca['exclude']) | 
| 485 | 485 | && $this->tca['exclude'] | 
| 486 | 486 |          ) { | 
| 487 | -            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName); | |
| 487 | +            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName.':'.$this->fieldName); | |
| 488 | 488 | } | 
| 489 | 489 | return $hasAccess; | 
| 490 | 490 | } | 
| @@ -18,765 +18,765 @@ | ||
| 18 | 18 | */ | 
| 19 | 19 | class FieldService extends AbstractTca | 
| 20 | 20 |  { | 
| 21 | - /** | |
| 22 | - * @var string | |
| 23 | - */ | |
| 24 | - protected $fieldName; | |
| 25 | - | |
| 26 | - /** | |
| 27 | - * @var string | |
| 28 | - */ | |
| 29 | - protected $compositeField; | |
| 30 | - | |
| 31 | - /** | |
| 32 | - * @var string | |
| 33 | - */ | |
| 34 | - protected $tableName; | |
| 35 | - | |
| 36 | - /** | |
| 37 | - * @var array | |
| 38 | - */ | |
| 39 | - protected $tca; | |
| 40 | - | |
| 41 | - /** | |
| 42 | - * @param string $fieldName | |
| 43 | - * @param array $tca | |
| 44 | - * @param string $tableName | |
| 45 | - * @param string $compositeField | |
| 46 | - * @return \Fab\Vidi\Tca\FieldService | |
| 47 | - */ | |
| 48 | - public function __construct($fieldName, array $tca, $tableName, $compositeField = '') | |
| 49 | -    { | |
| 50 | - $this->fieldName = $fieldName; | |
| 51 | - $this->tca = $tca; | |
| 52 | - $this->tableName = $tableName; | |
| 53 | - $this->compositeField = $compositeField; | |
| 54 | - } | |
| 55 | - | |
| 56 | - /** | |
| 57 | - * Tells whether the field is considered as system field, e.g. uid, crdate, tstamp, etc... | |
| 58 | - * | |
| 59 | - * @return bool | |
| 60 | - */ | |
| 61 | - public function isSystem() | |
| 62 | -    { | |
| 63 | - return in_array($this->fieldName, Tca::getSystemFields()); | |
| 64 | - } | |
| 65 | - | |
| 66 | - /** | |
| 67 | - * Tells the opposition of isSystem() | |
| 68 | - * | |
| 69 | - * @return bool | |
| 70 | - */ | |
| 71 | - public function isNotSystem() | |
| 72 | -    { | |
| 73 | - return !$this->isSystem(); | |
| 74 | - } | |
| 75 | - | |
| 76 | - /** | |
| 77 | - * Returns the configuration for a $field | |
| 78 | - * | |
| 79 | - * @throws \Exception | |
| 80 | - * @return array | |
| 81 | - */ | |
| 82 | - public function getConfiguration() | |
| 83 | -    { | |
| 84 | - return empty($this->tca['config']) ? [] : $this->tca['config']; | |
| 85 | - } | |
| 86 | - | |
| 87 | - /** | |
| 88 | - * Returns a key of the configuration. | |
| 89 | - * If the key can not to be found, returns null. | |
| 90 | - * | |
| 91 | - * @param string $key | |
| 92 | - * @return mixed | |
| 93 | - */ | |
| 94 | - public function get($key) | |
| 95 | -    { | |
| 96 | - $configuration = $this->getConfiguration(); | |
| 97 | - return empty($configuration[$key]) ? null : $configuration[$key]; | |
| 98 | - } | |
| 99 | - | |
| 100 | - /** | |
| 101 | - * Returns the foreign field of a given field (opposite relational field). | |
| 102 | - * If no relation exists, returns null. | |
| 103 | - * | |
| 104 | - * @return string|null | |
| 105 | - */ | |
| 106 | - public function getForeignField() | |
| 107 | -    { | |
| 108 | - $result = null; | |
| 109 | - $configuration = $this->getConfiguration(); | |
| 110 | - | |
| 111 | -        if (!empty($configuration['foreign_field'])) { | |
| 112 | - $result = $configuration['foreign_field']; | |
| 113 | -        } elseif ($this->hasRelationManyToMany()) { | |
| 114 | - $foreignTable = $this->getForeignTable(); | |
| 115 | - $manyToManyTable = $this->getManyToManyTable(); | |
| 116 | - | |
| 117 | - // Load TCA service of foreign field. | |
| 118 | - $tcaForeignTableService = Tca::table($foreignTable); | |
| 119 | - | |
| 120 | - // Look into the MM relations checking for the opposite field | |
| 121 | -            foreach ($tcaForeignTableService->getFields() as $fieldName) { | |
| 122 | -                if ($manyToManyTable == $tcaForeignTableService->field($fieldName)->getManyToManyTable()) { | |
| 123 | - $result = $fieldName; | |
| 124 | - break; | |
| 125 | - } | |
| 126 | - } | |
| 127 | - } | |
| 128 | - return $result; | |
| 129 | - } | |
| 130 | - | |
| 131 | - /** | |
| 132 | - * Returns the foreign table of a given field (opposite relational table). | |
| 133 | - * If no relation exists, returns null. | |
| 134 | - * | |
| 135 | - * @return string|null | |
| 136 | - */ | |
| 137 | - public function getForeignTable() | |
| 138 | -    { | |
| 139 | - $result = null; | |
| 140 | - $configuration = $this->getConfiguration(); | |
| 141 | - | |
| 142 | -        if (!empty($configuration['foreign_table'])) { | |
| 143 | - $result = $configuration['foreign_table']; | |
| 144 | -        } elseif ($this->isGroup()) { | |
| 145 | -            $fieldParts = explode('.', $this->compositeField, 2); | |
| 146 | - $result = $fieldParts[1] ?? null; | |
| 147 | - } | |
| 148 | - return $result; | |
| 149 | - } | |
| 150 | - | |
| 151 | - /** | |
| 152 | - * Returns the foreign clause. | |
| 153 | - * If no foreign order exists, returns empty string. | |
| 154 | - * | |
| 155 | - * @return string | |
| 156 | - */ | |
| 157 | - public function getForeignClause() | |
| 158 | -    { | |
| 159 | - $result = ''; | |
| 160 | - $configuration = $this->getConfiguration(); | |
| 161 | - | |
| 162 | -        if (!empty($configuration['foreign_table_where'])) { | |
| 163 | -            $parts = explode('ORDER BY', $configuration['foreign_table_where']); | |
| 164 | -            if (!empty($parts[0])) { | |
| 165 | - $result = $parts[0]; | |
| 166 | - } | |
| 167 | - } | |
| 168 | - | |
| 169 | - // Substitute some variables | |
| 170 | - return $this->substituteKnownMarkers($result); | |
| 171 | - } | |
| 172 | - | |
| 173 | - /** | |
| 174 | - * Substitute some known markers from the where clause in the Frontend Context. | |
| 175 | - * | |
| 176 | - * @param string $clause | |
| 177 | - * @return string | |
| 178 | - */ | |
| 179 | - protected function substituteKnownMarkers($clause) | |
| 180 | -    { | |
| 181 | -        if ($clause && $this->isFrontendMode()) { | |
| 182 | - $searches = array( | |
| 183 | - '###CURRENT_PID###', | |
| 184 | - '###REC_FIELD_sys_language_uid###' | |
| 185 | - ); | |
| 186 | - | |
| 187 | - $replaces = array( | |
| 188 | - $this->getFrontendObject()->id, | |
| 189 | -                GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id'), | |
| 190 | - ); | |
| 191 | - | |
| 192 | - $clause = str_replace($searches, $replaces, $clause); | |
| 193 | - } | |
| 194 | - return $clause; | |
| 195 | - } | |
| 196 | - | |
| 197 | - /** | |
| 198 | - * Returns the foreign order of the current field. | |
| 199 | - * If no foreign order exists, returns empty string. | |
| 200 | - * | |
| 201 | - * @return string | |
| 202 | - */ | |
| 203 | - public function getForeignOrder() | |
| 204 | -    { | |
| 205 | - $result = ''; | |
| 206 | - $configuration = $this->getConfiguration(); | |
| 207 | - | |
| 208 | -        if (!empty($configuration['foreign_table_where'])) { | |
| 209 | -            $parts = explode('ORDER BY', $configuration['foreign_table_where']); | |
| 210 | -            if (!empty($parts[1])) { | |
| 211 | - $result = $parts[1]; | |
| 212 | - } | |
| 213 | - } | |
| 214 | - return $result; | |
| 215 | - } | |
| 216 | - | |
| 217 | - /** | |
| 218 | - * Returns the MM table of a field. | |
| 219 | - * If no relation exists, returns null. | |
| 220 | - * | |
| 221 | - * @return string|null | |
| 222 | - */ | |
| 223 | - public function getManyToManyTable() | |
| 224 | -    { | |
| 225 | - $configuration = $this->getConfiguration(); | |
| 226 | - return empty($configuration['MM']) ? null : $configuration['MM']; | |
| 227 | - } | |
| 228 | - | |
| 229 | - /** | |
| 230 | - * Returns a possible additional table name used in MM relations. | |
| 231 | - * If no table name exists, returns null. | |
| 232 | - * | |
| 233 | - * @return string|null | |
| 234 | - */ | |
| 235 | - public function getAdditionalTableNameCondition() | |
| 236 | -    { | |
| 237 | - $result = null; | |
| 238 | - $configuration = $this->getConfiguration(); | |
| 239 | - | |
| 240 | -        if (!empty($configuration['MM_match_fields']['tablenames'])) { | |
| 241 | - $result = $configuration['MM_match_fields']['tablenames']; | |
| 242 | -        } elseif ($this->isGroup()) { | |
| 243 | - // @todo check if $this->fieldName could be simply used as $result | |
| 244 | -            $fieldParts = explode('.', $this->compositeField, 2); | |
| 245 | - $result = $fieldParts[1]; | |
| 246 | - } | |
| 247 | - | |
| 248 | - return $result; | |
| 249 | - } | |
| 250 | - | |
| 251 | - /** | |
| 252 | - * Returns a possible additional conditions for MM tables such as "tablenames", "fieldname", etc... | |
| 253 | - * | |
| 254 | - * @return array | |
| 255 | - */ | |
| 256 | - public function getAdditionalMMCondition() | |
| 257 | -    { | |
| 258 | - $additionalMMConditions = []; | |
| 259 | - $configuration = $this->getConfiguration(); | |
| 260 | - | |
| 261 | -        if (!empty($configuration['MM_match_fields'])) { | |
| 262 | - $additionalMMConditions = $configuration['MM_match_fields']; | |
| 263 | - } | |
| 264 | - | |
| 265 | - // Add in any case a table name for "group" | |
| 266 | -        if ($this->isGroup()) { | |
| 267 | - // @todo check if $this->fieldName could be simply used as $result | |
| 268 | -            $fieldParts = explode('.', $this->compositeField, 2); | |
| 269 | - $additionalMMConditions = array( | |
| 270 | - 'tablenames' => $fieldParts[1], | |
| 271 | - ); | |
| 272 | - } | |
| 273 | - return $additionalMMConditions; | |
| 274 | - } | |
| 275 | - | |
| 276 | - /** | |
| 277 | - * Returns whether the field name is the opposite in MM relation. | |
| 278 | - * | |
| 279 | - * @return bool | |
| 280 | - */ | |
| 281 | - public function isOppositeRelation() | |
| 282 | -    { | |
| 283 | - $configuration = $this->getConfiguration(); | |
| 284 | - return isset($configuration['MM_opposite_field']); | |
| 285 | - } | |
| 286 | - | |
| 287 | - /** | |
| 288 | - * Returns the configuration for a $field. | |
| 289 | - * | |
| 290 | - * @throws \Exception | |
| 291 | - * @return string | |
| 292 | - */ | |
| 293 | - public function getType() | |
| 294 | -    { | |
| 295 | -        if ($this->isSystem()) { | |
| 296 | - $fieldType = FieldType::NUMBER; | |
| 297 | -        } else { | |
| 298 | - $configuration = $this->getConfiguration(); | |
| 299 | - | |
| 300 | -            if (empty($configuration['type'])) { | |
| 301 | -                throw new \Exception(sprintf('No field type found for "%s" in table "%s"', $this->fieldName, $this->tableName), 1385556627); | |
| 302 | - } | |
| 303 | - | |
| 304 | - $fieldType = $configuration['type']; | |
| 305 | - | |
| 306 | -            if ($configuration['type'] === FieldType::SELECT && !empty($configuration['size']) && $configuration['size'] > 1) { | |
| 307 | - $fieldType = FieldType::MULTISELECT; | |
| 308 | - } elseif (!empty($configuration['foreign_table']) | |
| 309 | - && ($configuration['foreign_table'] == 'sys_file_reference' || $configuration['foreign_table'] == 'sys_file') | |
| 310 | -            ) { | |
| 311 | - $fieldType = FieldType::FILE; | |
| 312 | -            } elseif (!empty($configuration['eval'])) { | |
| 313 | -                $parts = GeneralUtility::trimExplode(',', $configuration['eval']); | |
| 314 | -                if (in_array('datetime', $parts)) { | |
| 315 | - $fieldType = FieldType::DATETIME; | |
| 316 | -                } elseif (in_array('date', $parts)) { | |
| 317 | - $fieldType = FieldType::DATE; | |
| 318 | -                } elseif (in_array('email', $parts)) { | |
| 319 | - $fieldType = FieldType::EMAIL; | |
| 320 | -                } elseif (in_array('int', $parts) || in_array('double2', $parts)) { | |
| 321 | - $fieldType = FieldType::NUMBER; | |
| 322 | - } | |
| 323 | - } | |
| 324 | - | |
| 325 | - // Do some legacy conversion | |
| 326 | -            if ($fieldType === 'input') { | |
| 327 | - $fieldType = FieldType::TEXT; | |
| 328 | -            } elseif ($fieldType === 'text') { | |
| 329 | - $fieldType = FieldType::TEXTAREA; | |
| 330 | - } | |
| 331 | - } | |
| 332 | - return $fieldType; | |
| 333 | - } | |
| 334 | - | |
| 335 | - /** | |
| 336 | - * Return the default value. | |
| 337 | - * | |
| 338 | - * @return bool | |
| 339 | - */ | |
| 340 | - public function getDefaultValue() | |
| 341 | -    { | |
| 342 | - $configuration = $this->getConfiguration(); | |
| 343 | - return isset($configuration['default']) ? $configuration['default'] : null; | |
| 344 | - } | |
| 345 | - | |
| 346 | - /** | |
| 347 | - * Get the translation of a label given a column. | |
| 348 | - * | |
| 349 | - * @return string | |
| 350 | - */ | |
| 351 | - public function getLabel() | |
| 352 | -    { | |
| 353 | - $label = ''; | |
| 354 | -        if ($this->hasLabel()) { | |
| 355 | -            try { | |
| 356 | - $label = LocalizationUtility::translate($this->tca['label'], ''); | |
| 357 | -            } catch (\InvalidArgumentException $e) { | |
| 358 | - } | |
| 359 | -            if (empty($label)) { | |
| 360 | - $label = $this->tca['label']; | |
| 361 | - } | |
| 362 | - } | |
| 363 | - return $label; | |
| 364 | - } | |
| 365 | - | |
| 366 | - /** | |
| 367 | - * Get the translation of a label given a column. | |
| 368 | - * | |
| 369 | - * @param string $itemValue the item value to search for. | |
| 370 | - * @return string | |
| 371 | - */ | |
| 372 | - public function getLabelForItem($itemValue) | |
| 373 | -    { | |
| 374 | - // Early return whether there is nothing to be translated as label. | |
| 375 | -        if (is_null($itemValue)) { | |
| 376 | - return ''; | |
| 377 | -        } elseif (is_string($itemValue) && $itemValue === '') { | |
| 378 | - return $itemValue; | |
| 379 | - } | |
| 380 | - | |
| 381 | - $configuration = $this->getConfiguration(); | |
| 382 | -        if (!empty($configuration['items']) && is_array($configuration['items'])) { | |
| 383 | -            foreach ($configuration['items'] as $item) { | |
| 384 | -                if ($item[1] == $itemValue) { | |
| 385 | -                    try { | |
| 386 | - $label = LocalizationUtility::translate($item[0], ''); | |
| 387 | -                    } catch (\InvalidArgumentException $e) { | |
| 388 | - } | |
| 389 | -                    if (empty($label)) { | |
| 390 | - $label = $item[0]; | |
| 391 | - } | |
| 392 | - break; | |
| 393 | - } | |
| 394 | - } | |
| 395 | - } | |
| 396 | - | |
| 397 | - // Try fetching a label from a possible itemsProcFunc | |
| 398 | -        if (!isset($label) && is_scalar($itemValue)) { | |
| 399 | - $items = $this->fetchItemsFromUserFunction(); | |
| 400 | -            if (!empty($items[$itemValue])) { | |
| 401 | - $label = $items[$itemValue]; | |
| 402 | - } | |
| 403 | - } | |
| 404 | - | |
| 405 | - // Returns a label if it has been found, otherwise returns the item value as fallback. | |
| 406 | - return isset($label) ? $label : $itemValue; | |
| 407 | - } | |
| 408 | - | |
| 409 | - /** | |
| 410 | - * Retrieve items from User Function. | |
| 411 | - * | |
| 412 | - * @return array | |
| 413 | - */ | |
| 414 | - protected function fetchItemsFromUserFunction() | |
| 415 | -    { | |
| 416 | - $values = []; | |
| 417 | - | |
| 418 | - $configuration = $this->getConfiguration(); | |
| 419 | -        if (!empty($configuration['itemsProcFunc'])) { | |
| 420 | -            $parts = explode('php:', $configuration['itemsProcFunc']); | |
| 421 | -            if (!empty($parts[1])) { | |
| 422 | -                list($class, $method) = explode('->', $parts[1]); | |
| 423 | - | |
| 424 | - $parameters['items'] = []; | |
| 425 | - $object = GeneralUtility::makeInstance($class); | |
| 426 | - $object->$method($parameters); | |
| 427 | - | |
| 428 | -                foreach ($parameters['items'] as $items) { | |
| 429 | - $values[$items[1]] = $items[0]; | |
| 430 | - } | |
| 431 | - } | |
| 432 | - } | |
| 433 | - return $values; | |
| 434 | - } | |
| 435 | - | |
| 436 | - /** | |
| 437 | - * Get a possible icon given a field name an an item. | |
| 438 | - * | |
| 439 | - * @param string $itemValue the item value to search for. | |
| 440 | - * @return string | |
| 441 | - */ | |
| 442 | - public function getIconForItem($itemValue) | |
| 443 | -    { | |
| 444 | - $result = ''; | |
| 445 | - $configuration = $this->getConfiguration(); | |
| 446 | -        if (!empty($configuration['items']) && is_array($configuration['items'])) { | |
| 447 | -            foreach ($configuration['items'] as $item) { | |
| 448 | -                if ($item[1] == $itemValue) { | |
| 449 | - $result = empty($item[2]) ? '' : $item[2]; | |
| 450 | - break; | |
| 451 | - } | |
| 452 | - } | |
| 453 | - } | |
| 454 | - return $result; | |
| 455 | - } | |
| 456 | - | |
| 457 | - /** | |
| 458 | - * Returns whether the field has a label. | |
| 459 | - * | |
| 460 | - * @return bool | |
| 461 | - */ | |
| 462 | - public function hasLabel() | |
| 463 | -    { | |
| 464 | - return empty($this->tca['label']) ? false : true; | |
| 465 | - } | |
| 466 | - | |
| 467 | - /** | |
| 468 | - * Tell whether the current BE User has access to this field. | |
| 469 | - * | |
| 470 | - * @return bool | |
| 471 | - */ | |
| 472 | - public function hasAccess() | |
| 473 | -    { | |
| 474 | - $hasAccess = true; | |
| 475 | - if ($this->isBackendMode() | |
| 476 | - && Tca::table($this->tableName)->hasAccess() | |
| 477 | - && isset($this->tca['exclude']) | |
| 478 | - && $this->tca['exclude'] | |
| 479 | -        ) { | |
| 480 | -            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName); | |
| 481 | - } | |
| 482 | - return $hasAccess; | |
| 483 | - } | |
| 484 | - | |
| 485 | - /** | |
| 486 | - * Returns whether the field is numerical. | |
| 487 | - * | |
| 488 | - * @return bool | |
| 489 | - */ | |
| 490 | - public function isNumerical() | |
| 491 | -    { | |
| 492 | - $result = $this->isSystem(); | |
| 493 | -        if ($result === false) { | |
| 494 | - $configuration = $this->getConfiguration(); | |
| 495 | - $parts = []; | |
| 496 | -            if (!empty($configuration['eval'])) { | |
| 497 | -                $parts = GeneralUtility::trimExplode(',', $configuration['eval']); | |
| 498 | - } | |
| 499 | -            $result = in_array('int', $parts) || in_array('float', $parts); | |
| 500 | - } | |
| 501 | - return $result; | |
| 502 | - } | |
| 503 | - | |
| 504 | - /** | |
| 505 | - * Returns whether the field is of type text area. | |
| 506 | - * | |
| 507 | - * @return bool | |
| 508 | - */ | |
| 509 | - public function isTextArea() | |
| 510 | -    { | |
| 511 | - return $this->getType() === FieldType::TEXTAREA; | |
| 512 | - } | |
| 513 | - /** | |
| 514 | - * Returns whether the field is of type text area. | |
| 515 | - * | |
| 516 | - * @return bool | |
| 517 | - */ | |
| 518 | - public function isText() | |
| 519 | -    { | |
| 520 | - return $this->getType() === FieldType::TEXT; | |
| 521 | - } | |
| 522 | - | |
| 523 | - /** | |
| 524 | - * Returns whether the field is displayed as a tree. | |
| 525 | - * | |
| 526 | - * @return bool | |
| 527 | - */ | |
| 528 | - public function isRenderModeTree() | |
| 529 | -    { | |
| 530 | - $configuration = $this->getConfiguration(); | |
| 531 | - return isset($configuration['renderMode']) && $configuration['renderMode'] == FieldType::TREE; | |
| 532 | - } | |
| 533 | - | |
| 534 | - /** | |
| 535 | - * Returns whether the field is of type select. | |
| 536 | - * | |
| 537 | - * @return bool | |
| 538 | - */ | |
| 539 | - public function isSelect() | |
| 540 | -    { | |
| 541 | - return $this->getType() === FieldType::SELECT; | |
| 542 | - } | |
| 543 | - | |
| 544 | - /** | |
| 545 | - * Returns whether the field is of type select. | |
| 546 | - * | |
| 547 | - * @return bool | |
| 548 | - */ | |
| 549 | - public function isMultipleSelect() | |
| 550 | -    { | |
| 551 | - return $this->getType() === FieldType::MULTISELECT; | |
| 552 | - } | |
| 553 | - | |
| 554 | - /** | |
| 555 | - * Returns whether the field is of type select. | |
| 556 | - * | |
| 557 | - * @return bool | |
| 558 | - */ | |
| 559 | - public function isCheckBox() | |
| 560 | -    { | |
| 561 | - return $this->getType() === FieldType::CHECKBOX; | |
| 562 | - } | |
| 563 | - | |
| 564 | - /** | |
| 565 | - * Returns whether the field is of type db. | |
| 566 | - * | |
| 567 | - * @return bool | |
| 568 | - */ | |
| 569 | - public function isGroup() | |
| 570 | -    { | |
| 571 | - return $this->getType() === 'group'; | |
| 572 | - } | |
| 573 | - | |
| 574 | - /** | |
| 575 | - * Returns whether the field is language aware. | |
| 576 | - * | |
| 577 | - * @return bool | |
| 578 | - */ | |
| 579 | - public function isLocalized() | |
| 580 | -    { | |
| 581 | - $isLocalized = false; | |
| 582 | -        if (isset($this->tca['l10n_mode'])) { | |
| 583 | -            if ($this->tca['l10n_mode'] == 'prefixLangTitle' || $this->tca['l10n_mode'] == 'mergeIfNotBlank') { | |
| 584 | - $isLocalized = true; | |
| 585 | - } | |
| 586 | - } | |
| 587 | - return $isLocalized; | |
| 588 | - } | |
| 589 | - | |
| 590 | - /** | |
| 591 | - * Returns whether the field is required. | |
| 592 | - * | |
| 593 | - * @return bool | |
| 594 | - */ | |
| 595 | - public function isRequired() | |
| 596 | -    { | |
| 597 | - $configuration = $this->getConfiguration(); | |
| 598 | - | |
| 599 | - $isRequired = false; | |
| 600 | -        if (isset($configuration['minitems'])) { | |
| 601 | - // is required of a select? | |
| 602 | - $isRequired = $configuration['minitems'] == 1 ? true : false; | |
| 603 | -        } elseif (isset($configuration['eval'])) { | |
| 604 | -            $parts = GeneralUtility::trimExplode(',', $configuration['eval'], true); | |
| 605 | -            $isRequired = in_array('required', $parts); | |
| 606 | - } | |
| 607 | - return $isRequired; | |
| 608 | - } | |
| 609 | - | |
| 610 | - /** | |
| 611 | - * Returns an array containing the configuration of a column. | |
| 612 | - * | |
| 613 | - * @return array | |
| 614 | - */ | |
| 615 | - public function getField() | |
| 616 | -    { | |
| 617 | - return $this->tca; | |
| 618 | - } | |
| 619 | - | |
| 620 | - /** | |
| 621 | - * Returns the relation type | |
| 622 | - * | |
| 623 | - * @return string | |
| 624 | - */ | |
| 625 | - public function relationDataType() | |
| 626 | -    { | |
| 627 | - $configuration = $this->getConfiguration(); | |
| 628 | - return empty($configuration['foreign_table']) ? '' : $configuration['foreign_table']; | |
| 629 | - } | |
| 630 | - | |
| 631 | - /** | |
| 632 | - * Returns whether the field has relation (one to many, many to many) | |
| 633 | - * | |
| 634 | - * @return bool | |
| 635 | - */ | |
| 636 | - public function hasRelation() | |
| 637 | -    { | |
| 638 | - return null !== $this->getForeignTable(); | |
| 639 | - } | |
| 640 | - | |
| 641 | - /** | |
| 642 | - * Returns whether the field has no relation (one to many, many to many) | |
| 643 | - * | |
| 644 | - * @return bool | |
| 645 | - */ | |
| 646 | - public function hasNoRelation() | |
| 647 | -    { | |
| 648 | - return !$this->hasRelation(); | |
| 649 | - } | |
| 650 | - | |
| 651 | - /** | |
| 652 | - * Returns whether the field has a "many" objects connected including "many-to-many" or "one-to-many". | |
| 653 | - * | |
| 654 | - * @return bool | |
| 655 | - */ | |
| 656 | - public function hasMany() | |
| 657 | -    { | |
| 658 | - $configuration = $this->getConfiguration(); | |
| 659 | - return $this->hasRelation() && ((isset($configuration['maxitems']) && $configuration['maxitems'] > 1) || isset($configuration['foreign_table_field'])); | |
| 660 | - } | |
| 661 | - | |
| 662 | - /** | |
| 663 | - * Returns whether the field has relation "one" object connected including of "one-to-one" or "many-to-one". | |
| 664 | - * | |
| 665 | - * @return bool | |
| 666 | - */ | |
| 667 | - public function hasOne() | |
| 668 | -    { | |
| 669 | - $configuration = $this->getConfiguration(); | |
| 670 | - return !isset($configuration['MM']) && $this->hasRelation() && ($configuration['maxitems'] == 1 || !isset($configuration['maxitems'])); | |
| 671 | - } | |
| 672 | - | |
| 673 | - /** | |
| 674 | - * Returns whether the field has many-to-one relation. | |
| 675 | - * | |
| 676 | - * @return bool | |
| 677 | - */ | |
| 678 | - public function hasRelationManyToOne() | |
| 679 | -    { | |
| 680 | - $result = false; | |
| 681 | - | |
| 682 | - $foreignField = $this->getForeignField(); | |
| 683 | -        if (!empty($foreignField)) { | |
| 684 | - // Load TCA service of the foreign field. | |
| 685 | - $foreignTable = $this->getForeignTable(); | |
| 686 | - $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasMany(); | |
| 687 | - } | |
| 688 | - return $result; | |
| 689 | - } | |
| 690 | - | |
| 691 | - /** | |
| 692 | - * Returns whether the field has one-to-many relation. | |
| 693 | - * | |
| 694 | - * @return bool | |
| 695 | - */ | |
| 696 | - public function hasRelationOneToMany() | |
| 697 | -    { | |
| 698 | - $result = false; | |
| 699 | - | |
| 700 | - $foreignField = $this->getForeignField(); | |
| 701 | -        if (!empty($foreignField)) { | |
| 702 | - // Load TCA service of the foreign field. | |
| 703 | - $foreignTable = $this->getForeignTable(); | |
| 704 | - $result = $this->hasMany() && Tca::table($foreignTable)->field($foreignField)->hasOne(); | |
| 705 | - } | |
| 706 | - return $result; | |
| 707 | - } | |
| 708 | - | |
| 709 | - /** | |
| 710 | - * Returns whether the field has one-to-one relation. | |
| 711 | - * | |
| 712 | - * @return bool | |
| 713 | - */ | |
| 714 | - public function hasRelationOneToOne() | |
| 715 | -    { | |
| 716 | - $result = false; | |
| 717 | - | |
| 718 | - $foreignField = $this->getForeignField(); | |
| 719 | -        if (!empty($foreignField)) { | |
| 720 | - // Load TCA service of foreign field. | |
| 721 | - $foreignTable = $this->getForeignTable(); | |
| 722 | - $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasOne(); | |
| 723 | - } | |
| 724 | - return $result; | |
| 725 | - } | |
| 726 | - | |
| 727 | - /** | |
| 728 | - * Returns whether the field has many to many relation. | |
| 729 | - * | |
| 730 | - * @return bool | |
| 731 | - */ | |
| 732 | - public function hasRelationManyToMany() | |
| 733 | -    { | |
| 734 | - $configuration = $this->getConfiguration(); | |
| 735 | - return $this->hasRelation() && (isset($configuration['MM']) || isset($configuration['foreign_table_field'])); | |
| 736 | - } | |
| 737 | - | |
| 738 | - /** | |
| 739 | - * Returns whether the field has many to many relation using comma separated values (legacy). | |
| 740 | - * | |
| 741 | - * @return bool | |
| 742 | - */ | |
| 743 | - public function hasRelationWithCommaSeparatedValues() | |
| 744 | -    { | |
| 745 | - $configuration = $this->getConfiguration(); | |
| 746 | - return $this->hasRelation() && !isset($configuration['MM']) && !isset($configuration['foreign_field']) && $configuration['maxitems'] > 1; | |
| 747 | - } | |
| 748 | - | |
| 749 | - /** | |
| 750 | - * @return array | |
| 751 | - */ | |
| 752 | - public function getTca() | |
| 753 | -    { | |
| 754 | - return $this->tca['columns']; | |
| 755 | - } | |
| 756 | - | |
| 757 | - /** | |
| 758 | - * @return string | |
| 759 | - */ | |
| 760 | - public function getCompositeField() | |
| 761 | -    { | |
| 762 | - return $this->compositeField; | |
| 763 | - } | |
| 764 | - | |
| 765 | - /** | |
| 766 | - * @param string $compositeField | |
| 767 | - */ | |
| 768 | - public function setCompositeField($compositeField) | |
| 769 | -    { | |
| 770 | - $this->compositeField = $compositeField; | |
| 771 | - } | |
| 772 | - | |
| 773 | - /** | |
| 774 | - * Returns an instance of the Frontend object. | |
| 775 | - * | |
| 776 | - * @return TypoScriptFrontendController | |
| 777 | - */ | |
| 778 | - protected function getFrontendObject() | |
| 779 | -    { | |
| 780 | - return $GLOBALS['TSFE']; | |
| 781 | - } | |
| 21 | + /** | |
| 22 | + * @var string | |
| 23 | + */ | |
| 24 | + protected $fieldName; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * @var string | |
| 28 | + */ | |
| 29 | + protected $compositeField; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * @var string | |
| 33 | + */ | |
| 34 | + protected $tableName; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * @var array | |
| 38 | + */ | |
| 39 | + protected $tca; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * @param string $fieldName | |
| 43 | + * @param array $tca | |
| 44 | + * @param string $tableName | |
| 45 | + * @param string $compositeField | |
| 46 | + * @return \Fab\Vidi\Tca\FieldService | |
| 47 | + */ | |
| 48 | + public function __construct($fieldName, array $tca, $tableName, $compositeField = '') | |
| 49 | +	{ | |
| 50 | + $this->fieldName = $fieldName; | |
| 51 | + $this->tca = $tca; | |
| 52 | + $this->tableName = $tableName; | |
| 53 | + $this->compositeField = $compositeField; | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Tells whether the field is considered as system field, e.g. uid, crdate, tstamp, etc... | |
| 58 | + * | |
| 59 | + * @return bool | |
| 60 | + */ | |
| 61 | + public function isSystem() | |
| 62 | +	{ | |
| 63 | + return in_array($this->fieldName, Tca::getSystemFields()); | |
| 64 | + } | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Tells the opposition of isSystem() | |
| 68 | + * | |
| 69 | + * @return bool | |
| 70 | + */ | |
| 71 | + public function isNotSystem() | |
| 72 | +	{ | |
| 73 | + return !$this->isSystem(); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Returns the configuration for a $field | |
| 78 | + * | |
| 79 | + * @throws \Exception | |
| 80 | + * @return array | |
| 81 | + */ | |
| 82 | + public function getConfiguration() | |
| 83 | +	{ | |
| 84 | + return empty($this->tca['config']) ? [] : $this->tca['config']; | |
| 85 | + } | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * Returns a key of the configuration. | |
| 89 | + * If the key can not to be found, returns null. | |
| 90 | + * | |
| 91 | + * @param string $key | |
| 92 | + * @return mixed | |
| 93 | + */ | |
| 94 | + public function get($key) | |
| 95 | +	{ | |
| 96 | + $configuration = $this->getConfiguration(); | |
| 97 | + return empty($configuration[$key]) ? null : $configuration[$key]; | |
| 98 | + } | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * Returns the foreign field of a given field (opposite relational field). | |
| 102 | + * If no relation exists, returns null. | |
| 103 | + * | |
| 104 | + * @return string|null | |
| 105 | + */ | |
| 106 | + public function getForeignField() | |
| 107 | +	{ | |
| 108 | + $result = null; | |
| 109 | + $configuration = $this->getConfiguration(); | |
| 110 | + | |
| 111 | +		if (!empty($configuration['foreign_field'])) { | |
| 112 | + $result = $configuration['foreign_field']; | |
| 113 | +		} elseif ($this->hasRelationManyToMany()) { | |
| 114 | + $foreignTable = $this->getForeignTable(); | |
| 115 | + $manyToManyTable = $this->getManyToManyTable(); | |
| 116 | + | |
| 117 | + // Load TCA service of foreign field. | |
| 118 | + $tcaForeignTableService = Tca::table($foreignTable); | |
| 119 | + | |
| 120 | + // Look into the MM relations checking for the opposite field | |
| 121 | +			foreach ($tcaForeignTableService->getFields() as $fieldName) { | |
| 122 | +				if ($manyToManyTable == $tcaForeignTableService->field($fieldName)->getManyToManyTable()) { | |
| 123 | + $result = $fieldName; | |
| 124 | + break; | |
| 125 | + } | |
| 126 | + } | |
| 127 | + } | |
| 128 | + return $result; | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Returns the foreign table of a given field (opposite relational table). | |
| 133 | + * If no relation exists, returns null. | |
| 134 | + * | |
| 135 | + * @return string|null | |
| 136 | + */ | |
| 137 | + public function getForeignTable() | |
| 138 | +	{ | |
| 139 | + $result = null; | |
| 140 | + $configuration = $this->getConfiguration(); | |
| 141 | + | |
| 142 | +		if (!empty($configuration['foreign_table'])) { | |
| 143 | + $result = $configuration['foreign_table']; | |
| 144 | +		} elseif ($this->isGroup()) { | |
| 145 | +			$fieldParts = explode('.', $this->compositeField, 2); | |
| 146 | + $result = $fieldParts[1] ?? null; | |
| 147 | + } | |
| 148 | + return $result; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /** | |
| 152 | + * Returns the foreign clause. | |
| 153 | + * If no foreign order exists, returns empty string. | |
| 154 | + * | |
| 155 | + * @return string | |
| 156 | + */ | |
| 157 | + public function getForeignClause() | |
| 158 | +	{ | |
| 159 | + $result = ''; | |
| 160 | + $configuration = $this->getConfiguration(); | |
| 161 | + | |
| 162 | +		if (!empty($configuration['foreign_table_where'])) { | |
| 163 | +			$parts = explode('ORDER BY', $configuration['foreign_table_where']); | |
| 164 | +			if (!empty($parts[0])) { | |
| 165 | + $result = $parts[0]; | |
| 166 | + } | |
| 167 | + } | |
| 168 | + | |
| 169 | + // Substitute some variables | |
| 170 | + return $this->substituteKnownMarkers($result); | |
| 171 | + } | |
| 172 | + | |
| 173 | + /** | |
| 174 | + * Substitute some known markers from the where clause in the Frontend Context. | |
| 175 | + * | |
| 176 | + * @param string $clause | |
| 177 | + * @return string | |
| 178 | + */ | |
| 179 | + protected function substituteKnownMarkers($clause) | |
| 180 | +	{ | |
| 181 | +		if ($clause && $this->isFrontendMode()) { | |
| 182 | + $searches = array( | |
| 183 | + '###CURRENT_PID###', | |
| 184 | + '###REC_FIELD_sys_language_uid###' | |
| 185 | + ); | |
| 186 | + | |
| 187 | + $replaces = array( | |
| 188 | + $this->getFrontendObject()->id, | |
| 189 | +				GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id'), | |
| 190 | + ); | |
| 191 | + | |
| 192 | + $clause = str_replace($searches, $replaces, $clause); | |
| 193 | + } | |
| 194 | + return $clause; | |
| 195 | + } | |
| 196 | + | |
| 197 | + /** | |
| 198 | + * Returns the foreign order of the current field. | |
| 199 | + * If no foreign order exists, returns empty string. | |
| 200 | + * | |
| 201 | + * @return string | |
| 202 | + */ | |
| 203 | + public function getForeignOrder() | |
| 204 | +	{ | |
| 205 | + $result = ''; | |
| 206 | + $configuration = $this->getConfiguration(); | |
| 207 | + | |
| 208 | +		if (!empty($configuration['foreign_table_where'])) { | |
| 209 | +			$parts = explode('ORDER BY', $configuration['foreign_table_where']); | |
| 210 | +			if (!empty($parts[1])) { | |
| 211 | + $result = $parts[1]; | |
| 212 | + } | |
| 213 | + } | |
| 214 | + return $result; | |
| 215 | + } | |
| 216 | + | |
| 217 | + /** | |
| 218 | + * Returns the MM table of a field. | |
| 219 | + * If no relation exists, returns null. | |
| 220 | + * | |
| 221 | + * @return string|null | |
| 222 | + */ | |
| 223 | + public function getManyToManyTable() | |
| 224 | +	{ | |
| 225 | + $configuration = $this->getConfiguration(); | |
| 226 | + return empty($configuration['MM']) ? null : $configuration['MM']; | |
| 227 | + } | |
| 228 | + | |
| 229 | + /** | |
| 230 | + * Returns a possible additional table name used in MM relations. | |
| 231 | + * If no table name exists, returns null. | |
| 232 | + * | |
| 233 | + * @return string|null | |
| 234 | + */ | |
| 235 | + public function getAdditionalTableNameCondition() | |
| 236 | +	{ | |
| 237 | + $result = null; | |
| 238 | + $configuration = $this->getConfiguration(); | |
| 239 | + | |
| 240 | +		if (!empty($configuration['MM_match_fields']['tablenames'])) { | |
| 241 | + $result = $configuration['MM_match_fields']['tablenames']; | |
| 242 | +		} elseif ($this->isGroup()) { | |
| 243 | + // @todo check if $this->fieldName could be simply used as $result | |
| 244 | +			$fieldParts = explode('.', $this->compositeField, 2); | |
| 245 | + $result = $fieldParts[1]; | |
| 246 | + } | |
| 247 | + | |
| 248 | + return $result; | |
| 249 | + } | |
| 250 | + | |
| 251 | + /** | |
| 252 | + * Returns a possible additional conditions for MM tables such as "tablenames", "fieldname", etc... | |
| 253 | + * | |
| 254 | + * @return array | |
| 255 | + */ | |
| 256 | + public function getAdditionalMMCondition() | |
| 257 | +	{ | |
| 258 | + $additionalMMConditions = []; | |
| 259 | + $configuration = $this->getConfiguration(); | |
| 260 | + | |
| 261 | +		if (!empty($configuration['MM_match_fields'])) { | |
| 262 | + $additionalMMConditions = $configuration['MM_match_fields']; | |
| 263 | + } | |
| 264 | + | |
| 265 | + // Add in any case a table name for "group" | |
| 266 | +		if ($this->isGroup()) { | |
| 267 | + // @todo check if $this->fieldName could be simply used as $result | |
| 268 | +			$fieldParts = explode('.', $this->compositeField, 2); | |
| 269 | + $additionalMMConditions = array( | |
| 270 | + 'tablenames' => $fieldParts[1], | |
| 271 | + ); | |
| 272 | + } | |
| 273 | + return $additionalMMConditions; | |
| 274 | + } | |
| 275 | + | |
| 276 | + /** | |
| 277 | + * Returns whether the field name is the opposite in MM relation. | |
| 278 | + * | |
| 279 | + * @return bool | |
| 280 | + */ | |
| 281 | + public function isOppositeRelation() | |
| 282 | +	{ | |
| 283 | + $configuration = $this->getConfiguration(); | |
| 284 | + return isset($configuration['MM_opposite_field']); | |
| 285 | + } | |
| 286 | + | |
| 287 | + /** | |
| 288 | + * Returns the configuration for a $field. | |
| 289 | + * | |
| 290 | + * @throws \Exception | |
| 291 | + * @return string | |
| 292 | + */ | |
| 293 | + public function getType() | |
| 294 | +	{ | |
| 295 | +		if ($this->isSystem()) { | |
| 296 | + $fieldType = FieldType::NUMBER; | |
| 297 | +		} else { | |
| 298 | + $configuration = $this->getConfiguration(); | |
| 299 | + | |
| 300 | +			if (empty($configuration['type'])) { | |
| 301 | +				throw new \Exception(sprintf('No field type found for "%s" in table "%s"', $this->fieldName, $this->tableName), 1385556627); | |
| 302 | + } | |
| 303 | + | |
| 304 | + $fieldType = $configuration['type']; | |
| 305 | + | |
| 306 | +			if ($configuration['type'] === FieldType::SELECT && !empty($configuration['size']) && $configuration['size'] > 1) { | |
| 307 | + $fieldType = FieldType::MULTISELECT; | |
| 308 | + } elseif (!empty($configuration['foreign_table']) | |
| 309 | + && ($configuration['foreign_table'] == 'sys_file_reference' || $configuration['foreign_table'] == 'sys_file') | |
| 310 | +			) { | |
| 311 | + $fieldType = FieldType::FILE; | |
| 312 | +			} elseif (!empty($configuration['eval'])) { | |
| 313 | +				$parts = GeneralUtility::trimExplode(',', $configuration['eval']); | |
| 314 | +				if (in_array('datetime', $parts)) { | |
| 315 | + $fieldType = FieldType::DATETIME; | |
| 316 | +				} elseif (in_array('date', $parts)) { | |
| 317 | + $fieldType = FieldType::DATE; | |
| 318 | +				} elseif (in_array('email', $parts)) { | |
| 319 | + $fieldType = FieldType::EMAIL; | |
| 320 | +				} elseif (in_array('int', $parts) || in_array('double2', $parts)) { | |
| 321 | + $fieldType = FieldType::NUMBER; | |
| 322 | + } | |
| 323 | + } | |
| 324 | + | |
| 325 | + // Do some legacy conversion | |
| 326 | +			if ($fieldType === 'input') { | |
| 327 | + $fieldType = FieldType::TEXT; | |
| 328 | +			} elseif ($fieldType === 'text') { | |
| 329 | + $fieldType = FieldType::TEXTAREA; | |
| 330 | + } | |
| 331 | + } | |
| 332 | + return $fieldType; | |
| 333 | + } | |
| 334 | + | |
| 335 | + /** | |
| 336 | + * Return the default value. | |
| 337 | + * | |
| 338 | + * @return bool | |
| 339 | + */ | |
| 340 | + public function getDefaultValue() | |
| 341 | +	{ | |
| 342 | + $configuration = $this->getConfiguration(); | |
| 343 | + return isset($configuration['default']) ? $configuration['default'] : null; | |
| 344 | + } | |
| 345 | + | |
| 346 | + /** | |
| 347 | + * Get the translation of a label given a column. | |
| 348 | + * | |
| 349 | + * @return string | |
| 350 | + */ | |
| 351 | + public function getLabel() | |
| 352 | +	{ | |
| 353 | + $label = ''; | |
| 354 | +		if ($this->hasLabel()) { | |
| 355 | +			try { | |
| 356 | + $label = LocalizationUtility::translate($this->tca['label'], ''); | |
| 357 | +			} catch (\InvalidArgumentException $e) { | |
| 358 | + } | |
| 359 | +			if (empty($label)) { | |
| 360 | + $label = $this->tca['label']; | |
| 361 | + } | |
| 362 | + } | |
| 363 | + return $label; | |
| 364 | + } | |
| 365 | + | |
| 366 | + /** | |
| 367 | + * Get the translation of a label given a column. | |
| 368 | + * | |
| 369 | + * @param string $itemValue the item value to search for. | |
| 370 | + * @return string | |
| 371 | + */ | |
| 372 | + public function getLabelForItem($itemValue) | |
| 373 | +	{ | |
| 374 | + // Early return whether there is nothing to be translated as label. | |
| 375 | +		if (is_null($itemValue)) { | |
| 376 | + return ''; | |
| 377 | +		} elseif (is_string($itemValue) && $itemValue === '') { | |
| 378 | + return $itemValue; | |
| 379 | + } | |
| 380 | + | |
| 381 | + $configuration = $this->getConfiguration(); | |
| 382 | +		if (!empty($configuration['items']) && is_array($configuration['items'])) { | |
| 383 | +			foreach ($configuration['items'] as $item) { | |
| 384 | +				if ($item[1] == $itemValue) { | |
| 385 | +					try { | |
| 386 | + $label = LocalizationUtility::translate($item[0], ''); | |
| 387 | +					} catch (\InvalidArgumentException $e) { | |
| 388 | + } | |
| 389 | +					if (empty($label)) { | |
| 390 | + $label = $item[0]; | |
| 391 | + } | |
| 392 | + break; | |
| 393 | + } | |
| 394 | + } | |
| 395 | + } | |
| 396 | + | |
| 397 | + // Try fetching a label from a possible itemsProcFunc | |
| 398 | +		if (!isset($label) && is_scalar($itemValue)) { | |
| 399 | + $items = $this->fetchItemsFromUserFunction(); | |
| 400 | +			if (!empty($items[$itemValue])) { | |
| 401 | + $label = $items[$itemValue]; | |
| 402 | + } | |
| 403 | + } | |
| 404 | + | |
| 405 | + // Returns a label if it has been found, otherwise returns the item value as fallback. | |
| 406 | + return isset($label) ? $label : $itemValue; | |
| 407 | + } | |
| 408 | + | |
| 409 | + /** | |
| 410 | + * Retrieve items from User Function. | |
| 411 | + * | |
| 412 | + * @return array | |
| 413 | + */ | |
| 414 | + protected function fetchItemsFromUserFunction() | |
| 415 | +	{ | |
| 416 | + $values = []; | |
| 417 | + | |
| 418 | + $configuration = $this->getConfiguration(); | |
| 419 | +		if (!empty($configuration['itemsProcFunc'])) { | |
| 420 | +			$parts = explode('php:', $configuration['itemsProcFunc']); | |
| 421 | +			if (!empty($parts[1])) { | |
| 422 | +				list($class, $method) = explode('->', $parts[1]); | |
| 423 | + | |
| 424 | + $parameters['items'] = []; | |
| 425 | + $object = GeneralUtility::makeInstance($class); | |
| 426 | + $object->$method($parameters); | |
| 427 | + | |
| 428 | +				foreach ($parameters['items'] as $items) { | |
| 429 | + $values[$items[1]] = $items[0]; | |
| 430 | + } | |
| 431 | + } | |
| 432 | + } | |
| 433 | + return $values; | |
| 434 | + } | |
| 435 | + | |
| 436 | + /** | |
| 437 | + * Get a possible icon given a field name an an item. | |
| 438 | + * | |
| 439 | + * @param string $itemValue the item value to search for. | |
| 440 | + * @return string | |
| 441 | + */ | |
| 442 | + public function getIconForItem($itemValue) | |
| 443 | +	{ | |
| 444 | + $result = ''; | |
| 445 | + $configuration = $this->getConfiguration(); | |
| 446 | +		if (!empty($configuration['items']) && is_array($configuration['items'])) { | |
| 447 | +			foreach ($configuration['items'] as $item) { | |
| 448 | +				if ($item[1] == $itemValue) { | |
| 449 | + $result = empty($item[2]) ? '' : $item[2]; | |
| 450 | + break; | |
| 451 | + } | |
| 452 | + } | |
| 453 | + } | |
| 454 | + return $result; | |
| 455 | + } | |
| 456 | + | |
| 457 | + /** | |
| 458 | + * Returns whether the field has a label. | |
| 459 | + * | |
| 460 | + * @return bool | |
| 461 | + */ | |
| 462 | + public function hasLabel() | |
| 463 | +	{ | |
| 464 | + return empty($this->tca['label']) ? false : true; | |
| 465 | + } | |
| 466 | + | |
| 467 | + /** | |
| 468 | + * Tell whether the current BE User has access to this field. | |
| 469 | + * | |
| 470 | + * @return bool | |
| 471 | + */ | |
| 472 | + public function hasAccess() | |
| 473 | +	{ | |
| 474 | + $hasAccess = true; | |
| 475 | + if ($this->isBackendMode() | |
| 476 | + && Tca::table($this->tableName)->hasAccess() | |
| 477 | + && isset($this->tca['exclude']) | |
| 478 | + && $this->tca['exclude'] | |
| 479 | +		) { | |
| 480 | +			$hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName); | |
| 481 | + } | |
| 482 | + return $hasAccess; | |
| 483 | + } | |
| 484 | + | |
| 485 | + /** | |
| 486 | + * Returns whether the field is numerical. | |
| 487 | + * | |
| 488 | + * @return bool | |
| 489 | + */ | |
| 490 | + public function isNumerical() | |
| 491 | +	{ | |
| 492 | + $result = $this->isSystem(); | |
| 493 | +		if ($result === false) { | |
| 494 | + $configuration = $this->getConfiguration(); | |
| 495 | + $parts = []; | |
| 496 | +			if (!empty($configuration['eval'])) { | |
| 497 | +				$parts = GeneralUtility::trimExplode(',', $configuration['eval']); | |
| 498 | + } | |
| 499 | +			$result = in_array('int', $parts) || in_array('float', $parts); | |
| 500 | + } | |
| 501 | + return $result; | |
| 502 | + } | |
| 503 | + | |
| 504 | + /** | |
| 505 | + * Returns whether the field is of type text area. | |
| 506 | + * | |
| 507 | + * @return bool | |
| 508 | + */ | |
| 509 | + public function isTextArea() | |
| 510 | +	{ | |
| 511 | + return $this->getType() === FieldType::TEXTAREA; | |
| 512 | + } | |
| 513 | + /** | |
| 514 | + * Returns whether the field is of type text area. | |
| 515 | + * | |
| 516 | + * @return bool | |
| 517 | + */ | |
| 518 | + public function isText() | |
| 519 | +	{ | |
| 520 | + return $this->getType() === FieldType::TEXT; | |
| 521 | + } | |
| 522 | + | |
| 523 | + /** | |
| 524 | + * Returns whether the field is displayed as a tree. | |
| 525 | + * | |
| 526 | + * @return bool | |
| 527 | + */ | |
| 528 | + public function isRenderModeTree() | |
| 529 | +	{ | |
| 530 | + $configuration = $this->getConfiguration(); | |
| 531 | + return isset($configuration['renderMode']) && $configuration['renderMode'] == FieldType::TREE; | |
| 532 | + } | |
| 533 | + | |
| 534 | + /** | |
| 535 | + * Returns whether the field is of type select. | |
| 536 | + * | |
| 537 | + * @return bool | |
| 538 | + */ | |
| 539 | + public function isSelect() | |
| 540 | +	{ | |
| 541 | + return $this->getType() === FieldType::SELECT; | |
| 542 | + } | |
| 543 | + | |
| 544 | + /** | |
| 545 | + * Returns whether the field is of type select. | |
| 546 | + * | |
| 547 | + * @return bool | |
| 548 | + */ | |
| 549 | + public function isMultipleSelect() | |
| 550 | +	{ | |
| 551 | + return $this->getType() === FieldType::MULTISELECT; | |
| 552 | + } | |
| 553 | + | |
| 554 | + /** | |
| 555 | + * Returns whether the field is of type select. | |
| 556 | + * | |
| 557 | + * @return bool | |
| 558 | + */ | |
| 559 | + public function isCheckBox() | |
| 560 | +	{ | |
| 561 | + return $this->getType() === FieldType::CHECKBOX; | |
| 562 | + } | |
| 563 | + | |
| 564 | + /** | |
| 565 | + * Returns whether the field is of type db. | |
| 566 | + * | |
| 567 | + * @return bool | |
| 568 | + */ | |
| 569 | + public function isGroup() | |
| 570 | +	{ | |
| 571 | + return $this->getType() === 'group'; | |
| 572 | + } | |
| 573 | + | |
| 574 | + /** | |
| 575 | + * Returns whether the field is language aware. | |
| 576 | + * | |
| 577 | + * @return bool | |
| 578 | + */ | |
| 579 | + public function isLocalized() | |
| 580 | +	{ | |
| 581 | + $isLocalized = false; | |
| 582 | +		if (isset($this->tca['l10n_mode'])) { | |
| 583 | +			if ($this->tca['l10n_mode'] == 'prefixLangTitle' || $this->tca['l10n_mode'] == 'mergeIfNotBlank') { | |
| 584 | + $isLocalized = true; | |
| 585 | + } | |
| 586 | + } | |
| 587 | + return $isLocalized; | |
| 588 | + } | |
| 589 | + | |
| 590 | + /** | |
| 591 | + * Returns whether the field is required. | |
| 592 | + * | |
| 593 | + * @return bool | |
| 594 | + */ | |
| 595 | + public function isRequired() | |
| 596 | +	{ | |
| 597 | + $configuration = $this->getConfiguration(); | |
| 598 | + | |
| 599 | + $isRequired = false; | |
| 600 | +		if (isset($configuration['minitems'])) { | |
| 601 | + // is required of a select? | |
| 602 | + $isRequired = $configuration['minitems'] == 1 ? true : false; | |
| 603 | +		} elseif (isset($configuration['eval'])) { | |
| 604 | +			$parts = GeneralUtility::trimExplode(',', $configuration['eval'], true); | |
| 605 | +			$isRequired = in_array('required', $parts); | |
| 606 | + } | |
| 607 | + return $isRequired; | |
| 608 | + } | |
| 609 | + | |
| 610 | + /** | |
| 611 | + * Returns an array containing the configuration of a column. | |
| 612 | + * | |
| 613 | + * @return array | |
| 614 | + */ | |
| 615 | + public function getField() | |
| 616 | +	{ | |
| 617 | + return $this->tca; | |
| 618 | + } | |
| 619 | + | |
| 620 | + /** | |
| 621 | + * Returns the relation type | |
| 622 | + * | |
| 623 | + * @return string | |
| 624 | + */ | |
| 625 | + public function relationDataType() | |
| 626 | +	{ | |
| 627 | + $configuration = $this->getConfiguration(); | |
| 628 | + return empty($configuration['foreign_table']) ? '' : $configuration['foreign_table']; | |
| 629 | + } | |
| 630 | + | |
| 631 | + /** | |
| 632 | + * Returns whether the field has relation (one to many, many to many) | |
| 633 | + * | |
| 634 | + * @return bool | |
| 635 | + */ | |
| 636 | + public function hasRelation() | |
| 637 | +	{ | |
| 638 | + return null !== $this->getForeignTable(); | |
| 639 | + } | |
| 640 | + | |
| 641 | + /** | |
| 642 | + * Returns whether the field has no relation (one to many, many to many) | |
| 643 | + * | |
| 644 | + * @return bool | |
| 645 | + */ | |
| 646 | + public function hasNoRelation() | |
| 647 | +	{ | |
| 648 | + return !$this->hasRelation(); | |
| 649 | + } | |
| 650 | + | |
| 651 | + /** | |
| 652 | + * Returns whether the field has a "many" objects connected including "many-to-many" or "one-to-many". | |
| 653 | + * | |
| 654 | + * @return bool | |
| 655 | + */ | |
| 656 | + public function hasMany() | |
| 657 | +	{ | |
| 658 | + $configuration = $this->getConfiguration(); | |
| 659 | + return $this->hasRelation() && ((isset($configuration['maxitems']) && $configuration['maxitems'] > 1) || isset($configuration['foreign_table_field'])); | |
| 660 | + } | |
| 661 | + | |
| 662 | + /** | |
| 663 | + * Returns whether the field has relation "one" object connected including of "one-to-one" or "many-to-one". | |
| 664 | + * | |
| 665 | + * @return bool | |
| 666 | + */ | |
| 667 | + public function hasOne() | |
| 668 | +	{ | |
| 669 | + $configuration = $this->getConfiguration(); | |
| 670 | + return !isset($configuration['MM']) && $this->hasRelation() && ($configuration['maxitems'] == 1 || !isset($configuration['maxitems'])); | |
| 671 | + } | |
| 672 | + | |
| 673 | + /** | |
| 674 | + * Returns whether the field has many-to-one relation. | |
| 675 | + * | |
| 676 | + * @return bool | |
| 677 | + */ | |
| 678 | + public function hasRelationManyToOne() | |
| 679 | +	{ | |
| 680 | + $result = false; | |
| 681 | + | |
| 682 | + $foreignField = $this->getForeignField(); | |
| 683 | +		if (!empty($foreignField)) { | |
| 684 | + // Load TCA service of the foreign field. | |
| 685 | + $foreignTable = $this->getForeignTable(); | |
| 686 | + $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasMany(); | |
| 687 | + } | |
| 688 | + return $result; | |
| 689 | + } | |
| 690 | + | |
| 691 | + /** | |
| 692 | + * Returns whether the field has one-to-many relation. | |
| 693 | + * | |
| 694 | + * @return bool | |
| 695 | + */ | |
| 696 | + public function hasRelationOneToMany() | |
| 697 | +	{ | |
| 698 | + $result = false; | |
| 699 | + | |
| 700 | + $foreignField = $this->getForeignField(); | |
| 701 | +		if (!empty($foreignField)) { | |
| 702 | + // Load TCA service of the foreign field. | |
| 703 | + $foreignTable = $this->getForeignTable(); | |
| 704 | + $result = $this->hasMany() && Tca::table($foreignTable)->field($foreignField)->hasOne(); | |
| 705 | + } | |
| 706 | + return $result; | |
| 707 | + } | |
| 708 | + | |
| 709 | + /** | |
| 710 | + * Returns whether the field has one-to-one relation. | |
| 711 | + * | |
| 712 | + * @return bool | |
| 713 | + */ | |
| 714 | + public function hasRelationOneToOne() | |
| 715 | +	{ | |
| 716 | + $result = false; | |
| 717 | + | |
| 718 | + $foreignField = $this->getForeignField(); | |
| 719 | +		if (!empty($foreignField)) { | |
| 720 | + // Load TCA service of foreign field. | |
| 721 | + $foreignTable = $this->getForeignTable(); | |
| 722 | + $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasOne(); | |
| 723 | + } | |
| 724 | + return $result; | |
| 725 | + } | |
| 726 | + | |
| 727 | + /** | |
| 728 | + * Returns whether the field has many to many relation. | |
| 729 | + * | |
| 730 | + * @return bool | |
| 731 | + */ | |
| 732 | + public function hasRelationManyToMany() | |
| 733 | +	{ | |
| 734 | + $configuration = $this->getConfiguration(); | |
| 735 | + return $this->hasRelation() && (isset($configuration['MM']) || isset($configuration['foreign_table_field'])); | |
| 736 | + } | |
| 737 | + | |
| 738 | + /** | |
| 739 | + * Returns whether the field has many to many relation using comma separated values (legacy). | |
| 740 | + * | |
| 741 | + * @return bool | |
| 742 | + */ | |
| 743 | + public function hasRelationWithCommaSeparatedValues() | |
| 744 | +	{ | |
| 745 | + $configuration = $this->getConfiguration(); | |
| 746 | + return $this->hasRelation() && !isset($configuration['MM']) && !isset($configuration['foreign_field']) && $configuration['maxitems'] > 1; | |
| 747 | + } | |
| 748 | + | |
| 749 | + /** | |
| 750 | + * @return array | |
| 751 | + */ | |
| 752 | + public function getTca() | |
| 753 | +	{ | |
| 754 | + return $this->tca['columns']; | |
| 755 | + } | |
| 756 | + | |
| 757 | + /** | |
| 758 | + * @return string | |
| 759 | + */ | |
| 760 | + public function getCompositeField() | |
| 761 | +	{ | |
| 762 | + return $this->compositeField; | |
| 763 | + } | |
| 764 | + | |
| 765 | + /** | |
| 766 | + * @param string $compositeField | |
| 767 | + */ | |
| 768 | + public function setCompositeField($compositeField) | |
| 769 | +	{ | |
| 770 | + $this->compositeField = $compositeField; | |
| 771 | + } | |
| 772 | + | |
| 773 | + /** | |
| 774 | + * Returns an instance of the Frontend object. | |
| 775 | + * | |
| 776 | + * @return TypoScriptFrontendController | |
| 777 | + */ | |
| 778 | + protected function getFrontendObject() | |
| 779 | +	{ | |
| 780 | + return $GLOBALS['TSFE']; | |
| 781 | + } | |
| 782 | 782 | } | 
| @@ -240,7 +240,7 @@ | ||
| 240 | 240 | public function getDefaultOrderSql() | 
| 241 | 241 |      { | 
| 242 | 242 | // "sortby" typically has "sorting" as value. | 
| 243 | -        $order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby'); | |
| 243 | +        $order = $this->get('sortby') ? $this->get('sortby').' ASC' : $this->get('default_sortby'); | |
| 244 | 244 | return $order; | 
| 245 | 245 | } | 
| 246 | 246 | |
| @@ -19,443 +19,443 @@ | ||
| 19 | 19 | */ | 
| 20 | 20 | class TableService extends AbstractTca | 
| 21 | 21 |  { | 
| 22 | - /** | |
| 23 | - * @var array | |
| 24 | - */ | |
| 25 | - protected $tca; | |
| 26 | - | |
| 27 | - /** | |
| 28 | - * @var array | |
| 29 | - */ | |
| 30 | - protected $columnTca; | |
| 31 | - | |
| 32 | - /** | |
| 33 | - * @var string | |
| 34 | - */ | |
| 35 | - protected $tableName; | |
| 36 | - | |
| 37 | - /** | |
| 38 | - * @var array | |
| 39 | - */ | |
| 40 | - protected $instances; | |
| 41 | - | |
| 42 | - /** | |
| 43 | - * @throws InvalidKeyInArrayException | |
| 44 | - * @param string $tableName | |
| 45 | - * @return \Fab\Vidi\Tca\TableService | |
| 46 | - */ | |
| 47 | - public function __construct($tableName) | |
| 48 | -    { | |
| 49 | - $this->tableName = $tableName; | |
| 50 | -        if (empty($GLOBALS['TCA'][$this->tableName])) { | |
| 51 | -            throw new InvalidKeyInArrayException(sprintf('No TCA existence for table "%s"', $this->tableName), 1356945106); | |
| 52 | - } | |
| 53 | - $this->tca = $GLOBALS['TCA'][$this->tableName]['ctrl']; | |
| 54 | - $this->columnTca = $GLOBALS['TCA'][$this->tableName]['columns']; | |
| 55 | - } | |
| 56 | - | |
| 57 | - /** | |
| 58 | - * Tell whether the table has a label field. | |
| 59 | - * | |
| 60 | - * @throws InvalidKeyInArrayException | |
| 61 | - * @return string | |
| 62 | - */ | |
| 63 | - public function hasLabelField() | |
| 64 | -    { | |
| 65 | -        return $this->has('label'); | |
| 66 | - } | |
| 67 | - | |
| 68 | - /** | |
| 69 | - * Get the label name of table name. | |
| 70 | - * | |
| 71 | - * @throws InvalidKeyInArrayException | |
| 72 | - * @return string | |
| 73 | - */ | |
| 74 | - public function getLabelField() | |
| 75 | -    { | |
| 76 | -        $labelField = $this->get('label'); | |
| 77 | -        if (empty($labelField)) { | |
| 78 | -            throw new InvalidKeyInArrayException(sprintf('No label configured for table "%s"', $this->tableName), 1385586726); | |
| 79 | - } | |
| 80 | - return $labelField; | |
| 81 | - } | |
| 82 | - | |
| 83 | - /** | |
| 84 | - * Returns the translated label of the table name. | |
| 85 | - * | |
| 86 | - * @return string | |
| 87 | - */ | |
| 88 | - public function getLabel() | |
| 89 | -    { | |
| 90 | - $label = ''; | |
| 91 | -        try { | |
| 92 | - $label = LocalizationUtility::translate($this->getLabelField(), ''); | |
| 93 | -        } catch (\InvalidArgumentException $e) { | |
| 94 | - } | |
| 95 | -        if (empty($label)) { | |
| 96 | - $label = $this->getLabelField(); | |
| 97 | - } | |
| 98 | - return $label; | |
| 99 | - } | |
| 100 | - | |
| 101 | - /** | |
| 102 | - * Returns the title of the table. | |
| 103 | - * | |
| 104 | - * @return string | |
| 105 | - */ | |
| 106 | - public function getTitle() | |
| 107 | -    { | |
| 108 | - $title = ''; | |
| 109 | -        try { | |
| 110 | -            $title = LocalizationUtility::translate((string)$this->get('title'), ''); | |
| 111 | -        } catch (\InvalidArgumentException $e) { | |
| 112 | - } | |
| 113 | -        if (empty($title)) { | |
| 114 | -            $title = $this->get('title'); | |
| 115 | - } | |
| 116 | - return $title; | |
| 117 | - } | |
| 118 | - | |
| 119 | - /** | |
| 120 | - * Return the "disabled" field. | |
| 121 | - * | |
| 122 | - * @throws InvalidKeyInArrayException | |
| 123 | - * @return string|null | |
| 124 | - */ | |
| 125 | - public function getHiddenField() | |
| 126 | -    { | |
| 127 | - $hiddenField = null; | |
| 128 | -        $enableColumns = $this->get('enablecolumns'); | |
| 129 | -        if (is_array($enableColumns) && !empty($enableColumns['disabled'])) { | |
| 130 | - $hiddenField = $enableColumns['disabled']; | |
| 131 | - } | |
| 132 | - return $hiddenField; | |
| 133 | - } | |
| 134 | - | |
| 135 | - /** | |
| 136 | - * Return the "starttime" field. | |
| 137 | - * | |
| 138 | - * @throws InvalidKeyInArrayException | |
| 139 | - * @return string|null | |
| 140 | - */ | |
| 141 | - public function getStartTimeField() | |
| 142 | -    { | |
| 143 | - $startTimeField = null; | |
| 144 | -        $enableColumns = $this->get('enablecolumns'); | |
| 145 | -        if (is_array($enableColumns) && !empty($enableColumns['starttime'])) { | |
| 146 | - $startTimeField = $enableColumns['starttime']; | |
| 147 | - } | |
| 148 | - return $startTimeField; | |
| 149 | - } | |
| 150 | - | |
| 151 | - /** | |
| 152 | - * Return the "endtime" field. | |
| 153 | - * | |
| 154 | - * @throws InvalidKeyInArrayException | |
| 155 | - * @return string|null | |
| 156 | - */ | |
| 157 | - public function getEndTimeField() | |
| 158 | -    { | |
| 159 | - $endTimeField = null; | |
| 160 | -        $enableColumns = $this->get('enablecolumns'); | |
| 161 | -        if (is_array($enableColumns) && !empty($enableColumns['endtime'])) { | |
| 162 | - $endTimeField = $enableColumns['endtime']; | |
| 163 | - } | |
| 164 | - return $endTimeField; | |
| 165 | - } | |
| 166 | - | |
| 167 | - /** | |
| 168 | - * Tells whether the table is hidden. | |
| 169 | - * | |
| 170 | - * @return bool | |
| 171 | - */ | |
| 172 | - public function isHidden() | |
| 173 | -    { | |
| 174 | - return isset($this->tca['hideTable']) ? $this->tca['hideTable'] : false; | |
| 175 | - } | |
| 176 | - | |
| 177 | - /** | |
| 178 | - * Tells whether the table is not hidden. | |
| 179 | - * | |
| 180 | - * @return bool | |
| 181 | - */ | |
| 182 | - public function isNotHidden() | |
| 183 | -    { | |
| 184 | - return !$this->isHidden(); | |
| 185 | - } | |
| 186 | - | |
| 187 | - /** | |
| 188 | - * Get the "deleted" field for the table. | |
| 189 | - * | |
| 190 | - * @return string|null | |
| 191 | - */ | |
| 192 | - public function getDeletedField() | |
| 193 | -    { | |
| 194 | -        return $this->get('delete'); | |
| 195 | - } | |
| 196 | - | |
| 197 | - /** | |
| 198 | - * Get the modification time stamp field. | |
| 199 | - * | |
| 200 | - * @return string|null | |
| 201 | - */ | |
| 202 | - public function getTimeModificationField() | |
| 203 | -    { | |
| 204 | -        return $this->get('tstamp'); | |
| 205 | - } | |
| 206 | - | |
| 207 | - /** | |
| 208 | - * Get the creation time stamp field. | |
| 209 | - * | |
| 210 | - * @return string|null | |
| 211 | - */ | |
| 212 | - public function getTimeCreationField() | |
| 213 | -    { | |
| 214 | -        return $this->get('crdate'); | |
| 215 | - } | |
| 216 | - | |
| 217 | - /** | |
| 218 | - * Get the language field for the table. | |
| 219 | - * | |
| 220 | - * @return string|null | |
| 221 | - */ | |
| 222 | - public function getLanguageField() | |
| 223 | -    { | |
| 224 | -        return $this->get('languageField'); | |
| 225 | - } | |
| 226 | - | |
| 227 | - /** | |
| 228 | - * Get the field which points to the parent. | |
| 229 | - * | |
| 230 | - * @return string|null | |
| 231 | - */ | |
| 232 | - public function getLanguageParentField() | |
| 233 | -    { | |
| 234 | -        return $this->get('transOrigPointerField'); | |
| 235 | - } | |
| 236 | - | |
| 237 | - /** | |
| 238 | - * Returns the default order in the form of a SQL segment. | |
| 239 | - * | |
| 240 | - * @return string|null | |
| 241 | - */ | |
| 242 | - public function getDefaultOrderSql() | |
| 243 | -    { | |
| 244 | - // "sortby" typically has "sorting" as value. | |
| 245 | -        $order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby'); | |
| 246 | - return $order; | |
| 247 | - } | |
| 248 | - | |
| 249 | - /** | |
| 250 | - * Returns the parsed default orderings. | |
| 251 | -     * Returns array looks like array('title' => 'ASC'); | |
| 252 | - * | |
| 253 | - * @return array | |
| 254 | - */ | |
| 255 | - public function getDefaultOrderings() | |
| 256 | -    { | |
| 257 | - // first clean up the sql segment | |
| 258 | -        $defaultOrder = str_replace('ORDER BY', '', $this->getDefaultOrderSql()); | |
| 259 | -        $defaultOrderParts = GeneralUtility::trimExplode(',', $defaultOrder, true); | |
| 260 | - | |
| 261 | - $orderings = []; | |
| 262 | -        foreach ($defaultOrderParts as $defaultOrderPart) { | |
| 263 | -            $parts = GeneralUtility::trimExplode(' ', $defaultOrderPart); | |
| 264 | -            if (empty($parts[1])) { | |
| 265 | - $parts[1] = QueryInterface::ORDER_DESCENDING; | |
| 266 | - } | |
| 267 | - $orderings[$parts[0]] = $parts[1]; | |
| 268 | - } | |
| 269 | - | |
| 270 | - return $orderings; | |
| 271 | - } | |
| 272 | - | |
| 273 | - /** | |
| 274 | - * Returns the searchable fields. | |
| 275 | - * | |
| 276 | - * @return string|null | |
| 277 | - */ | |
| 278 | - public function getSearchFields() | |
| 279 | -    { | |
| 280 | -        return $this->get('searchFields'); | |
| 281 | - } | |
| 282 | - | |
| 283 | - /** | |
| 284 | - * Returns an array containing the field names. | |
| 285 | - * | |
| 286 | - * @return array | |
| 287 | - */ | |
| 288 | - public function getFields() | |
| 289 | -    { | |
| 290 | - return array_keys($this->columnTca); | |
| 291 | - } | |
| 292 | - | |
| 293 | - /** | |
| 294 | - * Returns an array containing the fields and their configuration. | |
| 295 | - * | |
| 296 | - * @return array | |
| 297 | - */ | |
| 298 | - public function getFieldsAndConfiguration() | |
| 299 | -    { | |
| 300 | - return $this->columnTca; | |
| 301 | - } | |
| 302 | - | |
| 303 | - /** | |
| 304 | - * Tell whether we have a field "sorting". | |
| 305 | - * | |
| 306 | - * @return bool | |
| 307 | - */ | |
| 308 | - public function hasSortableField() | |
| 309 | -    { | |
| 310 | -        return $this->has('sortby'); | |
| 311 | - } | |
| 312 | - | |
| 313 | - /** | |
| 314 | - * Tell whether the field exists or not. | |
| 315 | - * | |
| 316 | - * @param string $fieldName | |
| 317 | - * @return bool | |
| 318 | - */ | |
| 319 | - public function hasField($fieldName) | |
| 320 | -    { | |
| 321 | -        if ($this->isComposite($fieldName)) { | |
| 322 | -            $parts = explode('.', $fieldName); | |
| 323 | - list($strippedFieldPath, $possibleTableName) = $parts; | |
| 324 | - $hasField = isset($this->columnTca[$strippedFieldPath], $GLOBALS['TCA'][$possibleTableName]); | |
| 325 | - | |
| 326 | - // Continue checking that the $strippedFieldName is of type "group" | |
| 327 | -            if (isset($GLOBALS['TCA'][$this->tableName]['columns'][$strippedFieldPath]) && count($parts) > 2) { | |
| 328 | - $hasField = Tca::table($this->tableName)->field($strippedFieldPath)->isGroup(); // Group | |
| 329 | -            } elseif (isset($this->columnTca[$strippedFieldPath]['config']['readOnly']) && (bool)$this->columnTca[$strippedFieldPath]['config']['readOnly']) { | |
| 330 | - $hasField = false; // handle case metadata.fe_groups where "fe_groups" is a tableName. | |
| 331 | - } | |
| 332 | -        } else { | |
| 333 | - $hasField = isset($this->columnTca[$fieldName]) || in_array($fieldName, Tca::getSystemFields(), true); | |
| 334 | - } | |
| 335 | - return $hasField; | |
| 336 | - } | |
| 337 | - | |
| 338 | - /** | |
| 339 | - * Tell whether the field name contains a path, e.g. metadata.title | |
| 340 | - * | |
| 341 | - * @param string $fieldName | |
| 342 | - * @return boolean | |
| 343 | - */ | |
| 344 | - public function isComposite($fieldName) | |
| 345 | -    { | |
| 346 | - return strpos($fieldName, '.') > 0; | |
| 347 | - } | |
| 348 | - | |
| 349 | - /** | |
| 350 | - * Tells whether the $key exists. | |
| 351 | - * | |
| 352 | - * @param string $key | |
| 353 | - * @return string | |
| 354 | - */ | |
| 355 | - public function has($key) | |
| 356 | -    { | |
| 357 | - return isset($this->tca[$key]); | |
| 358 | - } | |
| 359 | - | |
| 360 | - /** | |
| 361 | - * Tells whether the table name has "workspace" support. | |
| 362 | - * | |
| 363 | - * @return string | |
| 364 | - */ | |
| 365 | - public function hasWorkspaceSupport() | |
| 366 | -    { | |
| 367 | - return isset($this->tca['versioningWS']); | |
| 368 | - } | |
| 369 | - | |
| 370 | - /** | |
| 371 | - * Tells whether the table name has "language" support. | |
| 372 | - * | |
| 373 | - * @return string | |
| 374 | - */ | |
| 375 | - public function hasLanguageSupport() | |
| 376 | -    { | |
| 377 | - return isset($this->tca['languageField']); | |
| 378 | - } | |
| 379 | - | |
| 380 | - /** | |
| 381 | - * Return configuration value given a key. | |
| 382 | - * | |
| 383 | - * @param string $key | |
| 384 | - * @return string|null | |
| 385 | - */ | |
| 386 | - public function get($key) | |
| 387 | -    { | |
| 388 | - return $this->has($key) ? $this->tca[$key] : null; | |
| 389 | - } | |
| 390 | - | |
| 391 | - /** | |
| 392 | - * @return array | |
| 393 | - */ | |
| 394 | - public function getTca() | |
| 395 | -    { | |
| 396 | - return $this->tca; | |
| 397 | - } | |
| 398 | - | |
| 399 | - /** | |
| 400 | - * Tell whether the current BE User has access to this field. | |
| 401 | - * | |
| 402 | - * @return bool | |
| 403 | - */ | |
| 404 | - public function hasAccess() | |
| 405 | -    { | |
| 406 | - $hasAccess = true; | |
| 407 | -        if ($this->isBackendMode()) { | |
| 408 | -            $hasAccess = $this->getBackendUser()->check('tables_modify', $this->tableName); | |
| 409 | - } | |
| 410 | - return $hasAccess; | |
| 411 | - } | |
| 412 | - | |
| 413 | - /** | |
| 414 | - * @param string $fieldName | |
| 415 | - * @throws \Exception | |
| 416 | - * @return FieldService | |
| 417 | - */ | |
| 418 | - public function field($fieldName) | |
| 419 | -    { | |
| 420 | - // In case field contains items.tx_table for field type "group" | |
| 421 | - $compositeField = ''; | |
| 422 | -        if (strpos($fieldName, '.') !== false) { | |
| 423 | - $compositeField = $fieldName; | |
| 424 | -            $fieldParts = explode('.', $compositeField, 2); | |
| 425 | - $fieldName = $fieldParts[0]; | |
| 426 | - | |
| 427 | - // Special when field has been instantiated without the field name and path. | |
| 428 | -            if (!empty($this->instances[$fieldName])) { | |
| 429 | - /** @var FieldService $field */ | |
| 430 | - $field = $this->instances[$fieldName]; | |
| 431 | - $field->setCompositeField($compositeField); | |
| 432 | - } | |
| 433 | - } | |
| 434 | - | |
| 435 | - // True for system fields such as uid, pid that don't necessarily have a TCA. | |
| 436 | -        if (empty($this->columnTca[$fieldName]) && in_array($fieldName, Tca::getSystemFields())) { | |
| 437 | - $this->columnTca[$fieldName] = []; | |
| 438 | -        } elseif (empty($this->columnTca[$fieldName])) { | |
| 439 | - $message = sprintf( | |
| 440 | - 'Does the field really exist? No TCA entry found for field "%s" for table "%s"', | |
| 441 | - $fieldName, | |
| 442 | - $this->tableName | |
| 443 | - ); | |
| 444 | - throw new \Exception($message, 1385554481); | |
| 445 | - } | |
| 446 | - | |
| 447 | - | |
| 448 | -        if (empty($this->instances[$fieldName])) { | |
| 449 | - $instance = GeneralUtility::makeInstance( | |
| 450 | - 'Fab\Vidi\Tca\FieldService', | |
| 451 | - $fieldName, | |
| 452 | - $this->columnTca[$fieldName], | |
| 453 | - $this->tableName, | |
| 454 | - $compositeField | |
| 455 | - ); | |
| 456 | - | |
| 457 | - $this->instances[$fieldName] = $instance; | |
| 458 | - } | |
| 459 | - return $this->instances[$fieldName]; | |
| 460 | - } | |
| 22 | + /** | |
| 23 | + * @var array | |
| 24 | + */ | |
| 25 | + protected $tca; | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * @var array | |
| 29 | + */ | |
| 30 | + protected $columnTca; | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * @var string | |
| 34 | + */ | |
| 35 | + protected $tableName; | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * @var array | |
| 39 | + */ | |
| 40 | + protected $instances; | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * @throws InvalidKeyInArrayException | |
| 44 | + * @param string $tableName | |
| 45 | + * @return \Fab\Vidi\Tca\TableService | |
| 46 | + */ | |
| 47 | + public function __construct($tableName) | |
| 48 | +	{ | |
| 49 | + $this->tableName = $tableName; | |
| 50 | +		if (empty($GLOBALS['TCA'][$this->tableName])) { | |
| 51 | +			throw new InvalidKeyInArrayException(sprintf('No TCA existence for table "%s"', $this->tableName), 1356945106); | |
| 52 | + } | |
| 53 | + $this->tca = $GLOBALS['TCA'][$this->tableName]['ctrl']; | |
| 54 | + $this->columnTca = $GLOBALS['TCA'][$this->tableName]['columns']; | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * Tell whether the table has a label field. | |
| 59 | + * | |
| 60 | + * @throws InvalidKeyInArrayException | |
| 61 | + * @return string | |
| 62 | + */ | |
| 63 | + public function hasLabelField() | |
| 64 | +	{ | |
| 65 | +		return $this->has('label'); | |
| 66 | + } | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * Get the label name of table name. | |
| 70 | + * | |
| 71 | + * @throws InvalidKeyInArrayException | |
| 72 | + * @return string | |
| 73 | + */ | |
| 74 | + public function getLabelField() | |
| 75 | +	{ | |
| 76 | +		$labelField = $this->get('label'); | |
| 77 | +		if (empty($labelField)) { | |
| 78 | +			throw new InvalidKeyInArrayException(sprintf('No label configured for table "%s"', $this->tableName), 1385586726); | |
| 79 | + } | |
| 80 | + return $labelField; | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Returns the translated label of the table name. | |
| 85 | + * | |
| 86 | + * @return string | |
| 87 | + */ | |
| 88 | + public function getLabel() | |
| 89 | +	{ | |
| 90 | + $label = ''; | |
| 91 | +		try { | |
| 92 | + $label = LocalizationUtility::translate($this->getLabelField(), ''); | |
| 93 | +		} catch (\InvalidArgumentException $e) { | |
| 94 | + } | |
| 95 | +		if (empty($label)) { | |
| 96 | + $label = $this->getLabelField(); | |
| 97 | + } | |
| 98 | + return $label; | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * Returns the title of the table. | |
| 103 | + * | |
| 104 | + * @return string | |
| 105 | + */ | |
| 106 | + public function getTitle() | |
| 107 | +	{ | |
| 108 | + $title = ''; | |
| 109 | +		try { | |
| 110 | +			$title = LocalizationUtility::translate((string)$this->get('title'), ''); | |
| 111 | +		} catch (\InvalidArgumentException $e) { | |
| 112 | + } | |
| 113 | +		if (empty($title)) { | |
| 114 | +			$title = $this->get('title'); | |
| 115 | + } | |
| 116 | + return $title; | |
| 117 | + } | |
| 118 | + | |
| 119 | + /** | |
| 120 | + * Return the "disabled" field. | |
| 121 | + * | |
| 122 | + * @throws InvalidKeyInArrayException | |
| 123 | + * @return string|null | |
| 124 | + */ | |
| 125 | + public function getHiddenField() | |
| 126 | +	{ | |
| 127 | + $hiddenField = null; | |
| 128 | +		$enableColumns = $this->get('enablecolumns'); | |
| 129 | +		if (is_array($enableColumns) && !empty($enableColumns['disabled'])) { | |
| 130 | + $hiddenField = $enableColumns['disabled']; | |
| 131 | + } | |
| 132 | + return $hiddenField; | |
| 133 | + } | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * Return the "starttime" field. | |
| 137 | + * | |
| 138 | + * @throws InvalidKeyInArrayException | |
| 139 | + * @return string|null | |
| 140 | + */ | |
| 141 | + public function getStartTimeField() | |
| 142 | +	{ | |
| 143 | + $startTimeField = null; | |
| 144 | +		$enableColumns = $this->get('enablecolumns'); | |
| 145 | +		if (is_array($enableColumns) && !empty($enableColumns['starttime'])) { | |
| 146 | + $startTimeField = $enableColumns['starttime']; | |
| 147 | + } | |
| 148 | + return $startTimeField; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /** | |
| 152 | + * Return the "endtime" field. | |
| 153 | + * | |
| 154 | + * @throws InvalidKeyInArrayException | |
| 155 | + * @return string|null | |
| 156 | + */ | |
| 157 | + public function getEndTimeField() | |
| 158 | +	{ | |
| 159 | + $endTimeField = null; | |
| 160 | +		$enableColumns = $this->get('enablecolumns'); | |
| 161 | +		if (is_array($enableColumns) && !empty($enableColumns['endtime'])) { | |
| 162 | + $endTimeField = $enableColumns['endtime']; | |
| 163 | + } | |
| 164 | + return $endTimeField; | |
| 165 | + } | |
| 166 | + | |
| 167 | + /** | |
| 168 | + * Tells whether the table is hidden. | |
| 169 | + * | |
| 170 | + * @return bool | |
| 171 | + */ | |
| 172 | + public function isHidden() | |
| 173 | +	{ | |
| 174 | + return isset($this->tca['hideTable']) ? $this->tca['hideTable'] : false; | |
| 175 | + } | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * Tells whether the table is not hidden. | |
| 179 | + * | |
| 180 | + * @return bool | |
| 181 | + */ | |
| 182 | + public function isNotHidden() | |
| 183 | +	{ | |
| 184 | + return !$this->isHidden(); | |
| 185 | + } | |
| 186 | + | |
| 187 | + /** | |
| 188 | + * Get the "deleted" field for the table. | |
| 189 | + * | |
| 190 | + * @return string|null | |
| 191 | + */ | |
| 192 | + public function getDeletedField() | |
| 193 | +	{ | |
| 194 | +		return $this->get('delete'); | |
| 195 | + } | |
| 196 | + | |
| 197 | + /** | |
| 198 | + * Get the modification time stamp field. | |
| 199 | + * | |
| 200 | + * @return string|null | |
| 201 | + */ | |
| 202 | + public function getTimeModificationField() | |
| 203 | +	{ | |
| 204 | +		return $this->get('tstamp'); | |
| 205 | + } | |
| 206 | + | |
| 207 | + /** | |
| 208 | + * Get the creation time stamp field. | |
| 209 | + * | |
| 210 | + * @return string|null | |
| 211 | + */ | |
| 212 | + public function getTimeCreationField() | |
| 213 | +	{ | |
| 214 | +		return $this->get('crdate'); | |
| 215 | + } | |
| 216 | + | |
| 217 | + /** | |
| 218 | + * Get the language field for the table. | |
| 219 | + * | |
| 220 | + * @return string|null | |
| 221 | + */ | |
| 222 | + public function getLanguageField() | |
| 223 | +	{ | |
| 224 | +		return $this->get('languageField'); | |
| 225 | + } | |
| 226 | + | |
| 227 | + /** | |
| 228 | + * Get the field which points to the parent. | |
| 229 | + * | |
| 230 | + * @return string|null | |
| 231 | + */ | |
| 232 | + public function getLanguageParentField() | |
| 233 | +	{ | |
| 234 | +		return $this->get('transOrigPointerField'); | |
| 235 | + } | |
| 236 | + | |
| 237 | + /** | |
| 238 | + * Returns the default order in the form of a SQL segment. | |
| 239 | + * | |
| 240 | + * @return string|null | |
| 241 | + */ | |
| 242 | + public function getDefaultOrderSql() | |
| 243 | +	{ | |
| 244 | + // "sortby" typically has "sorting" as value. | |
| 245 | +		$order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby'); | |
| 246 | + return $order; | |
| 247 | + } | |
| 248 | + | |
| 249 | + /** | |
| 250 | + * Returns the parsed default orderings. | |
| 251 | +	 * Returns array looks like array('title' => 'ASC'); | |
| 252 | + * | |
| 253 | + * @return array | |
| 254 | + */ | |
| 255 | + public function getDefaultOrderings() | |
| 256 | +	{ | |
| 257 | + // first clean up the sql segment | |
| 258 | +		$defaultOrder = str_replace('ORDER BY', '', $this->getDefaultOrderSql()); | |
| 259 | +		$defaultOrderParts = GeneralUtility::trimExplode(',', $defaultOrder, true); | |
| 260 | + | |
| 261 | + $orderings = []; | |
| 262 | +		foreach ($defaultOrderParts as $defaultOrderPart) { | |
| 263 | +			$parts = GeneralUtility::trimExplode(' ', $defaultOrderPart); | |
| 264 | +			if (empty($parts[1])) { | |
| 265 | + $parts[1] = QueryInterface::ORDER_DESCENDING; | |
| 266 | + } | |
| 267 | + $orderings[$parts[0]] = $parts[1]; | |
| 268 | + } | |
| 269 | + | |
| 270 | + return $orderings; | |
| 271 | + } | |
| 272 | + | |
| 273 | + /** | |
| 274 | + * Returns the searchable fields. | |
| 275 | + * | |
| 276 | + * @return string|null | |
| 277 | + */ | |
| 278 | + public function getSearchFields() | |
| 279 | +	{ | |
| 280 | +		return $this->get('searchFields'); | |
| 281 | + } | |
| 282 | + | |
| 283 | + /** | |
| 284 | + * Returns an array containing the field names. | |
| 285 | + * | |
| 286 | + * @return array | |
| 287 | + */ | |
| 288 | + public function getFields() | |
| 289 | +	{ | |
| 290 | + return array_keys($this->columnTca); | |
| 291 | + } | |
| 292 | + | |
| 293 | + /** | |
| 294 | + * Returns an array containing the fields and their configuration. | |
| 295 | + * | |
| 296 | + * @return array | |
| 297 | + */ | |
| 298 | + public function getFieldsAndConfiguration() | |
| 299 | +	{ | |
| 300 | + return $this->columnTca; | |
| 301 | + } | |
| 302 | + | |
| 303 | + /** | |
| 304 | + * Tell whether we have a field "sorting". | |
| 305 | + * | |
| 306 | + * @return bool | |
| 307 | + */ | |
| 308 | + public function hasSortableField() | |
| 309 | +	{ | |
| 310 | +		return $this->has('sortby'); | |
| 311 | + } | |
| 312 | + | |
| 313 | + /** | |
| 314 | + * Tell whether the field exists or not. | |
| 315 | + * | |
| 316 | + * @param string $fieldName | |
| 317 | + * @return bool | |
| 318 | + */ | |
| 319 | + public function hasField($fieldName) | |
| 320 | +	{ | |
| 321 | +		if ($this->isComposite($fieldName)) { | |
| 322 | +			$parts = explode('.', $fieldName); | |
| 323 | + list($strippedFieldPath, $possibleTableName) = $parts; | |
| 324 | + $hasField = isset($this->columnTca[$strippedFieldPath], $GLOBALS['TCA'][$possibleTableName]); | |
| 325 | + | |
| 326 | + // Continue checking that the $strippedFieldName is of type "group" | |
| 327 | +			if (isset($GLOBALS['TCA'][$this->tableName]['columns'][$strippedFieldPath]) && count($parts) > 2) { | |
| 328 | + $hasField = Tca::table($this->tableName)->field($strippedFieldPath)->isGroup(); // Group | |
| 329 | +			} elseif (isset($this->columnTca[$strippedFieldPath]['config']['readOnly']) && (bool)$this->columnTca[$strippedFieldPath]['config']['readOnly']) { | |
| 330 | + $hasField = false; // handle case metadata.fe_groups where "fe_groups" is a tableName. | |
| 331 | + } | |
| 332 | +		} else { | |
| 333 | + $hasField = isset($this->columnTca[$fieldName]) || in_array($fieldName, Tca::getSystemFields(), true); | |
| 334 | + } | |
| 335 | + return $hasField; | |
| 336 | + } | |
| 337 | + | |
| 338 | + /** | |
| 339 | + * Tell whether the field name contains a path, e.g. metadata.title | |
| 340 | + * | |
| 341 | + * @param string $fieldName | |
| 342 | + * @return boolean | |
| 343 | + */ | |
| 344 | + public function isComposite($fieldName) | |
| 345 | +	{ | |
| 346 | + return strpos($fieldName, '.') > 0; | |
| 347 | + } | |
| 348 | + | |
| 349 | + /** | |
| 350 | + * Tells whether the $key exists. | |
| 351 | + * | |
| 352 | + * @param string $key | |
| 353 | + * @return string | |
| 354 | + */ | |
| 355 | + public function has($key) | |
| 356 | +	{ | |
| 357 | + return isset($this->tca[$key]); | |
| 358 | + } | |
| 359 | + | |
| 360 | + /** | |
| 361 | + * Tells whether the table name has "workspace" support. | |
| 362 | + * | |
| 363 | + * @return string | |
| 364 | + */ | |
| 365 | + public function hasWorkspaceSupport() | |
| 366 | +	{ | |
| 367 | + return isset($this->tca['versioningWS']); | |
| 368 | + } | |
| 369 | + | |
| 370 | + /** | |
| 371 | + * Tells whether the table name has "language" support. | |
| 372 | + * | |
| 373 | + * @return string | |
| 374 | + */ | |
| 375 | + public function hasLanguageSupport() | |
| 376 | +	{ | |
| 377 | + return isset($this->tca['languageField']); | |
| 378 | + } | |
| 379 | + | |
| 380 | + /** | |
| 381 | + * Return configuration value given a key. | |
| 382 | + * | |
| 383 | + * @param string $key | |
| 384 | + * @return string|null | |
| 385 | + */ | |
| 386 | + public function get($key) | |
| 387 | +	{ | |
| 388 | + return $this->has($key) ? $this->tca[$key] : null; | |
| 389 | + } | |
| 390 | + | |
| 391 | + /** | |
| 392 | + * @return array | |
| 393 | + */ | |
| 394 | + public function getTca() | |
| 395 | +	{ | |
| 396 | + return $this->tca; | |
| 397 | + } | |
| 398 | + | |
| 399 | + /** | |
| 400 | + * Tell whether the current BE User has access to this field. | |
| 401 | + * | |
| 402 | + * @return bool | |
| 403 | + */ | |
| 404 | + public function hasAccess() | |
| 405 | +	{ | |
| 406 | + $hasAccess = true; | |
| 407 | +		if ($this->isBackendMode()) { | |
| 408 | +			$hasAccess = $this->getBackendUser()->check('tables_modify', $this->tableName); | |
| 409 | + } | |
| 410 | + return $hasAccess; | |
| 411 | + } | |
| 412 | + | |
| 413 | + /** | |
| 414 | + * @param string $fieldName | |
| 415 | + * @throws \Exception | |
| 416 | + * @return FieldService | |
| 417 | + */ | |
| 418 | + public function field($fieldName) | |
| 419 | +	{ | |
| 420 | + // In case field contains items.tx_table for field type "group" | |
| 421 | + $compositeField = ''; | |
| 422 | +		if (strpos($fieldName, '.') !== false) { | |
| 423 | + $compositeField = $fieldName; | |
| 424 | +			$fieldParts = explode('.', $compositeField, 2); | |
| 425 | + $fieldName = $fieldParts[0]; | |
| 426 | + | |
| 427 | + // Special when field has been instantiated without the field name and path. | |
| 428 | +			if (!empty($this->instances[$fieldName])) { | |
| 429 | + /** @var FieldService $field */ | |
| 430 | + $field = $this->instances[$fieldName]; | |
| 431 | + $field->setCompositeField($compositeField); | |
| 432 | + } | |
| 433 | + } | |
| 434 | + | |
| 435 | + // True for system fields such as uid, pid that don't necessarily have a TCA. | |
| 436 | +		if (empty($this->columnTca[$fieldName]) && in_array($fieldName, Tca::getSystemFields())) { | |
| 437 | + $this->columnTca[$fieldName] = []; | |
| 438 | +		} elseif (empty($this->columnTca[$fieldName])) { | |
| 439 | + $message = sprintf( | |
| 440 | + 'Does the field really exist? No TCA entry found for field "%s" for table "%s"', | |
| 441 | + $fieldName, | |
| 442 | + $this->tableName | |
| 443 | + ); | |
| 444 | + throw new \Exception($message, 1385554481); | |
| 445 | + } | |
| 446 | + | |
| 447 | + | |
| 448 | +		if (empty($this->instances[$fieldName])) { | |
| 449 | + $instance = GeneralUtility::makeInstance( | |
| 450 | + 'Fab\Vidi\Tca\FieldService', | |
| 451 | + $fieldName, | |
| 452 | + $this->columnTca[$fieldName], | |
| 453 | + $this->tableName, | |
| 454 | + $compositeField | |
| 455 | + ); | |
| 456 | + | |
| 457 | + $this->instances[$fieldName] = $instance; | |
| 458 | + } | |
| 459 | + return $this->instances[$fieldName]; | |
| 460 | + } | |
| 461 | 461 | } | 
| @@ -34,7 +34,7 @@ | ||
| 34 | 34 |          $configuration = $this->templateVariableContainer->get('configuration'); | 
| 35 | 35 | |
| 36 | 36 |          if (isset($configuration['dataType'])) { | 
| 37 | - $fieldName = $configuration['dataType'] . '.' . $fieldName; | |
| 37 | + $fieldName = $configuration['dataType'].'.'.$fieldName; | |
| 38 | 38 | } | 
| 39 | 39 | |
| 40 | 40 | return $fieldName; | 
| @@ -16,20 +16,20 @@ | ||
| 16 | 16 | */ | 
| 17 | 17 | class FieldNameViewHelper extends AbstractViewHelper | 
| 18 | 18 |  { | 
| 19 | - /** | |
| 20 | - * Return the final field name in the context of the Grid. | |
| 21 | - * | |
| 22 | - * @return string | |
| 23 | - */ | |
| 24 | - public function render() | |
| 25 | -    { | |
| 26 | -        $fieldName = $this->templateVariableContainer->get('columnName'); | |
| 27 | -        $configuration = $this->templateVariableContainer->get('configuration'); | |
| 19 | + /** | |
| 20 | + * Return the final field name in the context of the Grid. | |
| 21 | + * | |
| 22 | + * @return string | |
| 23 | + */ | |
| 24 | + public function render() | |
| 25 | +	{ | |
| 26 | +		$fieldName = $this->templateVariableContainer->get('columnName'); | |
| 27 | +		$configuration = $this->templateVariableContainer->get('configuration'); | |
| 28 | 28 | |
| 29 | -        if (isset($configuration['dataType'])) { | |
| 30 | - $fieldName = $configuration['dataType'] . '.' . $fieldName; | |
| 31 | - } | |
| 29 | +		if (isset($configuration['dataType'])) { | |
| 30 | + $fieldName = $configuration['dataType'] . '.' . $fieldName; | |
| 31 | + } | |
| 32 | 32 | |
| 33 | - return $fieldName; | |
| 34 | - } | |
| 33 | + return $fieldName; | |
| 34 | + } | |
| 35 | 35 | } | 
| @@ -57,7 +57,7 @@ | ||
| 57 | 57 |      { | 
| 58 | 58 | $serializedMatches = serialize($matches); | 
| 59 | 59 | $serializedOrderings = serialize($orderings); | 
| 60 | - return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset); | |
| 60 | + return md5($dataType.$serializedMatches.$serializedOrderings.$limit.$offset); | |
| 61 | 61 | } | 
| 62 | 62 | |
| 63 | 63 | /** | 
| @@ -27,201 +27,201 @@ | ||
| 27 | 27 | */ | 
| 28 | 28 | abstract class AbstractContentViewHelper extends AbstractViewHelper | 
| 29 | 29 |  { | 
| 30 | - /** | |
| 31 | - * @return void | |
| 32 | - * @throws Exception | |
| 33 | - */ | |
| 34 | - public function initializeArguments() | |
| 35 | -    { | |
| 36 | -        $this->registerArgument('type', 'string', 'Corresponds to the type of data to be fetched. It will basically be a table name e.g. fe_users.', false, ''); | |
| 37 | -        $this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, array()); | |
| 38 | -        $this->registerArgument('selection', 'int', 'A possible selection defined in the BE and stored in the database.', false, 0); | |
| 39 | -        $this->registerArgument('ignoreEnableFields', 'bool', 'Whether to ignore enable fields or not (AKA hidden, deleted, starttime, ...).', false, false); | |
| 40 | -        $this->registerArgument('aliases', 'array', 'Attribute "matches" does not support certain character such as "." in field name. Use this to create aliases.', false, array()); | |
| 41 | - } | |
| 42 | - | |
| 43 | - /** | |
| 44 | - * Generate a signature to be used for storing the result set. | |
| 45 | - * | |
| 46 | - * @param string $dataType | |
| 47 | - * @param array $matches | |
| 48 | - * @param array $orderings | |
| 49 | - * @param $limit | |
| 50 | - * @param $offset | |
| 51 | - * @return string | |
| 52 | - */ | |
| 53 | - protected function getQuerySignature($dataType, array $matches, array $orderings, $limit, $offset) | |
| 54 | -    { | |
| 55 | - $serializedMatches = serialize($matches); | |
| 56 | - $serializedOrderings = serialize($orderings); | |
| 57 | - return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset); | |
| 58 | - } | |
| 59 | - | |
| 60 | - /** | |
| 61 | - * Returns a matcher object. | |
| 62 | - * | |
| 63 | - * @param string $dataType | |
| 64 | - * @param array $matches | |
| 65 | - * @return Matcher | |
| 66 | - * @throws NotExistingClassException | |
| 67 | - * @throws \InvalidArgumentException | |
| 68 | - */ | |
| 69 | - protected function getMatcher($dataType, $matches = array()) | |
| 70 | -    { | |
| 71 | - /** @var $matcher Matcher */ | |
| 72 | - $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType); | |
| 73 | - | |
| 74 | -        // @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}} | |
| 75 | -        foreach ($matches as $fieldNameAndPath => $value) { | |
| 76 | - // CSV values should be considered as "in" operator in Query, otherwise "equals". | |
| 77 | -            $explodedValues = GeneralUtility::trimExplode(',', $value, true); | |
| 78 | - | |
| 79 | - // The matching value contains a "1,2" as example | |
| 80 | -            if (count($explodedValues) > 1) { | |
| 81 | - $resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType); | |
| 82 | - $resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType); | |
| 83 | - | |
| 84 | - // "equals" if in presence of a relation. | |
| 85 | - // "in" if not a relation. | |
| 86 | -                if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) { | |
| 87 | -                    foreach ($explodedValues as $explodedValue) { | |
| 88 | - $matcher->equals($fieldNameAndPath, $explodedValue); | |
| 89 | - } | |
| 90 | -                } else { | |
| 91 | - $matcher->in($fieldNameAndPath, $explodedValues); | |
| 92 | - } | |
| 93 | -            } else { | |
| 94 | - $matcher->equals($fieldNameAndPath, $explodedValues[0]); | |
| 95 | - } | |
| 96 | - } | |
| 97 | - | |
| 98 | - // Trigger signal for post processing Matcher Object. | |
| 99 | - $this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher); | |
| 100 | - | |
| 101 | - return $matcher; | |
| 102 | - } | |
| 103 | - | |
| 104 | - /** | |
| 105 | - * Replace possible aliases. | |
| 106 | - * | |
| 107 | - * @param array $values | |
| 108 | - * @return array | |
| 109 | - */ | |
| 110 | - protected function replacesAliases(array $values) | |
| 111 | -    { | |
| 112 | - $aliases = $this->arguments['aliases']; | |
| 113 | - | |
| 114 | -        foreach ($aliases as $aliasName => $aliasValue) { | |
| 115 | -            if (isset($values[$aliasName])) { | |
| 116 | - $values[$aliasValue] = $values[$aliasName]; | |
| 117 | - unset($values[$aliasName]); // remove the alias. | |
| 118 | - } | |
| 119 | - } | |
| 120 | - | |
| 121 | - return $values; | |
| 122 | - } | |
| 123 | - | |
| 124 | - /** | |
| 125 | - * Returns an order object. | |
| 126 | - * | |
| 127 | - * @param string $dataType | |
| 128 | - * @param array $order | |
| 129 | - * @return Order | |
| 130 | - */ | |
| 131 | - public function getOrder($dataType, array $order = array()) | |
| 132 | -    { | |
| 133 | - // Default orderings in case order is empty. | |
| 134 | -        if (empty($order)) { | |
| 135 | - $order = Tca::table($dataType)->getDefaultOrderings(); | |
| 136 | - } | |
| 137 | - | |
| 138 | - $order = GeneralUtility::makeInstance(Order::class, $order); | |
| 139 | - | |
| 140 | - // Trigger signal for post processing Order Object. | |
| 141 | - $this->emitPostProcessOrderObjectSignal($dataType, $order); | |
| 142 | - | |
| 143 | - return $order; | |
| 144 | - } | |
| 145 | - | |
| 146 | - /** | |
| 147 | - * @return ResultSetStorage | |
| 148 | - */ | |
| 149 | - public function getResultSetStorage() | |
| 150 | -    { | |
| 151 | - return GeneralUtility::makeInstance(ResultSetStorage::class); | |
| 152 | - } | |
| 153 | - | |
| 154 | - /** | |
| 155 | - * Signal that is called for post-processing a "order" object. | |
| 156 | - * | |
| 157 | - * @param string $dataType | |
| 158 | - * @param Order $order | |
| 159 | - */ | |
| 160 | - protected function emitPostProcessOrderObjectSignal($dataType, Order $order) | |
| 161 | -    { | |
| 162 | -        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType)); | |
| 163 | - } | |
| 164 | - | |
| 165 | - /** | |
| 166 | - * Signal that is called for post-processing a "matcher" object. | |
| 167 | - * | |
| 168 | - * @param string $dataType | |
| 169 | - * @param Matcher $matcher | |
| 170 | - */ | |
| 171 | - protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher) | |
| 172 | -    { | |
| 173 | -        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType)); | |
| 174 | - } | |
| 175 | - | |
| 176 | - /** | |
| 177 | - * Signal that is called for post-processing a "limit". | |
| 178 | - * | |
| 179 | - * @param string $dataType | |
| 180 | - * @param int $limit | |
| 181 | - */ | |
| 182 | - protected function emitPostProcessLimitSignal($dataType, $limit) | |
| 183 | -    { | |
| 184 | -        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType)); | |
| 185 | - } | |
| 186 | - | |
| 187 | - /** | |
| 188 | - * Signal that is called for post-processing a "offset". | |
| 189 | - * | |
| 190 | - * @param string $dataType | |
| 191 | - * @param int $offset | |
| 192 | - */ | |
| 193 | - protected function emitPostProcessOffsetSignal($dataType, $offset) | |
| 194 | -    { | |
| 195 | -        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType)); | |
| 196 | - } | |
| 197 | - | |
| 198 | - /** | |
| 199 | - * Get the SignalSlot dispatcher | |
| 200 | - * | |
| 201 | - * @return Dispatcher | |
| 202 | - */ | |
| 203 | - protected function getSignalSlotDispatcher() | |
| 204 | -    { | |
| 205 | - return GeneralUtility::makeInstance(Dispatcher::class); | |
| 206 | - } | |
| 207 | - | |
| 208 | - /** | |
| 209 | - * @param $ignoreEnableFields | |
| 210 | - * @return QuerySettingsInterface | |
| 211 | - */ | |
| 212 | - protected function getDefaultQuerySettings($ignoreEnableFields) | |
| 213 | -    { | |
| 214 | - /** @var Typo3QuerySettings $defaultQuerySettings */ | |
| 215 | - $defaultQuerySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class); | |
| 216 | - $defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields); | |
| 217 | - return $defaultQuerySettings; | |
| 218 | - } | |
| 219 | - | |
| 220 | - /** | |
| 221 | - * @return FieldPathResolver | |
| 222 | - */ | |
| 223 | - protected function getFieldPathResolver() | |
| 224 | -    { | |
| 225 | - return GeneralUtility::makeInstance(FieldPathResolver::class); | |
| 226 | - } | |
| 30 | + /** | |
| 31 | + * @return void | |
| 32 | + * @throws Exception | |
| 33 | + */ | |
| 34 | + public function initializeArguments() | |
| 35 | +	{ | |
| 36 | +		$this->registerArgument('type', 'string', 'Corresponds to the type of data to be fetched. It will basically be a table name e.g. fe_users.', false, ''); | |
| 37 | +		$this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, array()); | |
| 38 | +		$this->registerArgument('selection', 'int', 'A possible selection defined in the BE and stored in the database.', false, 0); | |
| 39 | +		$this->registerArgument('ignoreEnableFields', 'bool', 'Whether to ignore enable fields or not (AKA hidden, deleted, starttime, ...).', false, false); | |
| 40 | +		$this->registerArgument('aliases', 'array', 'Attribute "matches" does not support certain character such as "." in field name. Use this to create aliases.', false, array()); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * Generate a signature to be used for storing the result set. | |
| 45 | + * | |
| 46 | + * @param string $dataType | |
| 47 | + * @param array $matches | |
| 48 | + * @param array $orderings | |
| 49 | + * @param $limit | |
| 50 | + * @param $offset | |
| 51 | + * @return string | |
| 52 | + */ | |
| 53 | + protected function getQuerySignature($dataType, array $matches, array $orderings, $limit, $offset) | |
| 54 | +	{ | |
| 55 | + $serializedMatches = serialize($matches); | |
| 56 | + $serializedOrderings = serialize($orderings); | |
| 57 | + return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset); | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Returns a matcher object. | |
| 62 | + * | |
| 63 | + * @param string $dataType | |
| 64 | + * @param array $matches | |
| 65 | + * @return Matcher | |
| 66 | + * @throws NotExistingClassException | |
| 67 | + * @throws \InvalidArgumentException | |
| 68 | + */ | |
| 69 | + protected function getMatcher($dataType, $matches = array()) | |
| 70 | +	{ | |
| 71 | + /** @var $matcher Matcher */ | |
| 72 | + $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType); | |
| 73 | + | |
| 74 | +		// @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}} | |
| 75 | +		foreach ($matches as $fieldNameAndPath => $value) { | |
| 76 | + // CSV values should be considered as "in" operator in Query, otherwise "equals". | |
| 77 | +			$explodedValues = GeneralUtility::trimExplode(',', $value, true); | |
| 78 | + | |
| 79 | + // The matching value contains a "1,2" as example | |
| 80 | +			if (count($explodedValues) > 1) { | |
| 81 | + $resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType); | |
| 82 | + $resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType); | |
| 83 | + | |
| 84 | + // "equals" if in presence of a relation. | |
| 85 | + // "in" if not a relation. | |
| 86 | +				if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) { | |
| 87 | +					foreach ($explodedValues as $explodedValue) { | |
| 88 | + $matcher->equals($fieldNameAndPath, $explodedValue); | |
| 89 | + } | |
| 90 | +				} else { | |
| 91 | + $matcher->in($fieldNameAndPath, $explodedValues); | |
| 92 | + } | |
| 93 | +			} else { | |
| 94 | + $matcher->equals($fieldNameAndPath, $explodedValues[0]); | |
| 95 | + } | |
| 96 | + } | |
| 97 | + | |
| 98 | + // Trigger signal for post processing Matcher Object. | |
| 99 | + $this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher); | |
| 100 | + | |
| 101 | + return $matcher; | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * Replace possible aliases. | |
| 106 | + * | |
| 107 | + * @param array $values | |
| 108 | + * @return array | |
| 109 | + */ | |
| 110 | + protected function replacesAliases(array $values) | |
| 111 | +	{ | |
| 112 | + $aliases = $this->arguments['aliases']; | |
| 113 | + | |
| 114 | +		foreach ($aliases as $aliasName => $aliasValue) { | |
| 115 | +			if (isset($values[$aliasName])) { | |
| 116 | + $values[$aliasValue] = $values[$aliasName]; | |
| 117 | + unset($values[$aliasName]); // remove the alias. | |
| 118 | + } | |
| 119 | + } | |
| 120 | + | |
| 121 | + return $values; | |
| 122 | + } | |
| 123 | + | |
| 124 | + /** | |
| 125 | + * Returns an order object. | |
| 126 | + * | |
| 127 | + * @param string $dataType | |
| 128 | + * @param array $order | |
| 129 | + * @return Order | |
| 130 | + */ | |
| 131 | + public function getOrder($dataType, array $order = array()) | |
| 132 | +	{ | |
| 133 | + // Default orderings in case order is empty. | |
| 134 | +		if (empty($order)) { | |
| 135 | + $order = Tca::table($dataType)->getDefaultOrderings(); | |
| 136 | + } | |
| 137 | + | |
| 138 | + $order = GeneralUtility::makeInstance(Order::class, $order); | |
| 139 | + | |
| 140 | + // Trigger signal for post processing Order Object. | |
| 141 | + $this->emitPostProcessOrderObjectSignal($dataType, $order); | |
| 142 | + | |
| 143 | + return $order; | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * @return ResultSetStorage | |
| 148 | + */ | |
| 149 | + public function getResultSetStorage() | |
| 150 | +	{ | |
| 151 | + return GeneralUtility::makeInstance(ResultSetStorage::class); | |
| 152 | + } | |
| 153 | + | |
| 154 | + /** | |
| 155 | + * Signal that is called for post-processing a "order" object. | |
| 156 | + * | |
| 157 | + * @param string $dataType | |
| 158 | + * @param Order $order | |
| 159 | + */ | |
| 160 | + protected function emitPostProcessOrderObjectSignal($dataType, Order $order) | |
| 161 | +	{ | |
| 162 | +		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType)); | |
| 163 | + } | |
| 164 | + | |
| 165 | + /** | |
| 166 | + * Signal that is called for post-processing a "matcher" object. | |
| 167 | + * | |
| 168 | + * @param string $dataType | |
| 169 | + * @param Matcher $matcher | |
| 170 | + */ | |
| 171 | + protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher) | |
| 172 | +	{ | |
| 173 | +		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType)); | |
| 174 | + } | |
| 175 | + | |
| 176 | + /** | |
| 177 | + * Signal that is called for post-processing a "limit". | |
| 178 | + * | |
| 179 | + * @param string $dataType | |
| 180 | + * @param int $limit | |
| 181 | + */ | |
| 182 | + protected function emitPostProcessLimitSignal($dataType, $limit) | |
| 183 | +	{ | |
| 184 | +		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType)); | |
| 185 | + } | |
| 186 | + | |
| 187 | + /** | |
| 188 | + * Signal that is called for post-processing a "offset". | |
| 189 | + * | |
| 190 | + * @param string $dataType | |
| 191 | + * @param int $offset | |
| 192 | + */ | |
| 193 | + protected function emitPostProcessOffsetSignal($dataType, $offset) | |
| 194 | +	{ | |
| 195 | +		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType)); | |
| 196 | + } | |
| 197 | + | |
| 198 | + /** | |
| 199 | + * Get the SignalSlot dispatcher | |
| 200 | + * | |
| 201 | + * @return Dispatcher | |
| 202 | + */ | |
| 203 | + protected function getSignalSlotDispatcher() | |
| 204 | +	{ | |
| 205 | + return GeneralUtility::makeInstance(Dispatcher::class); | |
| 206 | + } | |
| 207 | + | |
| 208 | + /** | |
| 209 | + * @param $ignoreEnableFields | |
| 210 | + * @return QuerySettingsInterface | |
| 211 | + */ | |
| 212 | + protected function getDefaultQuerySettings($ignoreEnableFields) | |
| 213 | +	{ | |
| 214 | + /** @var Typo3QuerySettings $defaultQuerySettings */ | |
| 215 | + $defaultQuerySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class); | |
| 216 | + $defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields); | |
| 217 | + return $defaultQuerySettings; | |
| 218 | + } | |
| 219 | + | |
| 220 | + /** | |
| 221 | + * @return FieldPathResolver | |
| 222 | + */ | |
| 223 | + protected function getFieldPathResolver() | |
| 224 | +	{ | |
| 225 | + return GeneralUtility::makeInstance(FieldPathResolver::class); | |
| 226 | + } | |
| 227 | 227 | } | 
| @@ -81,7 +81,7 @@ | ||
| 81 | 81 | */ | 
| 82 | 82 | protected function getDataKey() | 
| 83 | 83 |      { | 
| 84 | - return 'vidi_clipboard_' . $this->getModuleLoader()->getDataType(); | |
| 84 | + return 'vidi_clipboard_'.$this->getModuleLoader()->getDataType(); | |
| 85 | 85 | } | 
| 86 | 86 | |
| 87 | 87 | /** | 
| @@ -19,83 +19,83 @@ | ||
| 19 | 19 | */ | 
| 20 | 20 | class ClipboardService implements SingletonInterface | 
| 21 | 21 |  { | 
| 22 | - /** | |
| 23 | - * Get the Matcher object of the clipboard. | |
| 24 | - * | |
| 25 | - * @return Matcher | |
| 26 | - */ | |
| 27 | - public function getMatcher() | |
| 28 | -    { | |
| 29 | - $matcher = $this->getBackendUser()->getModuleData($this->getDataKey()); | |
| 30 | -        if (!$matcher) { | |
| 31 | - /** @var $matcher Matcher */ | |
| 32 | - $matcher = GeneralUtility::makeInstance(Matcher::class); | |
| 33 | - } | |
| 34 | - return $matcher; | |
| 35 | - } | |
| 22 | + /** | |
| 23 | + * Get the Matcher object of the clipboard. | |
| 24 | + * | |
| 25 | + * @return Matcher | |
| 26 | + */ | |
| 27 | + public function getMatcher() | |
| 28 | +	{ | |
| 29 | + $matcher = $this->getBackendUser()->getModuleData($this->getDataKey()); | |
| 30 | +		if (!$matcher) { | |
| 31 | + /** @var $matcher Matcher */ | |
| 32 | + $matcher = GeneralUtility::makeInstance(Matcher::class); | |
| 33 | + } | |
| 34 | + return $matcher; | |
| 35 | + } | |
| 36 | 36 | |
| 37 | - /** | |
| 38 | - * Tell whether the clipboard has items or not. | |
| 39 | - * | |
| 40 | - * @return bool | |
| 41 | - */ | |
| 42 | - public function hasItems() | |
| 43 | -    { | |
| 44 | - $matcher = $this->getMatcher(); | |
| 37 | + /** | |
| 38 | + * Tell whether the clipboard has items or not. | |
| 39 | + * | |
| 40 | + * @return bool | |
| 41 | + */ | |
| 42 | + public function hasItems() | |
| 43 | +	{ | |
| 44 | + $matcher = $this->getMatcher(); | |
| 45 | 45 | |
| 46 | - $inCriteria = $matcher->getIn(); | |
| 47 | - $likeCriteria = $matcher->getLike(); | |
| 48 | - $searchTerm = $matcher->getSearchTerm(); | |
| 46 | + $inCriteria = $matcher->getIn(); | |
| 47 | + $likeCriteria = $matcher->getLike(); | |
| 48 | + $searchTerm = $matcher->getSearchTerm(); | |
| 49 | 49 | |
| 50 | - $hasItems = !empty($inCriteria) || !empty($likeCriteria) || !empty($searchTerm); | |
| 51 | - return $hasItems; | |
| 52 | - } | |
| 50 | + $hasItems = !empty($inCriteria) || !empty($likeCriteria) || !empty($searchTerm); | |
| 51 | + return $hasItems; | |
| 52 | + } | |
| 53 | 53 | |
| 54 | - /** | |
| 55 | - * Save data into the clipboard. | |
| 56 | - * | |
| 57 | - * @param Matcher $matches | |
| 58 | - */ | |
| 59 | - public function save(Matcher $matches) | |
| 60 | -    { | |
| 61 | - $this->getBackendUser()->pushModuleData($this->getDataKey(), $matches); | |
| 62 | - } | |
| 54 | + /** | |
| 55 | + * Save data into the clipboard. | |
| 56 | + * | |
| 57 | + * @param Matcher $matches | |
| 58 | + */ | |
| 59 | + public function save(Matcher $matches) | |
| 60 | +	{ | |
| 61 | + $this->getBackendUser()->pushModuleData($this->getDataKey(), $matches); | |
| 62 | + } | |
| 63 | 63 | |
| 64 | - /** | |
| 65 | - * Completely empty the clipboard for a data type. | |
| 66 | - * | |
| 67 | - * @return void | |
| 68 | - */ | |
| 69 | - public function flush() | |
| 70 | -    { | |
| 71 | - $this->getBackendUser()->pushModuleData($this->getDataKey(), null); | |
| 72 | - } | |
| 64 | + /** | |
| 65 | + * Completely empty the clipboard for a data type. | |
| 66 | + * | |
| 67 | + * @return void | |
| 68 | + */ | |
| 69 | + public function flush() | |
| 70 | +	{ | |
| 71 | + $this->getBackendUser()->pushModuleData($this->getDataKey(), null); | |
| 72 | + } | |
| 73 | 73 | |
| 74 | - /** | |
| 75 | - * @return string | |
| 76 | - */ | |
| 77 | - protected function getDataKey() | |
| 78 | -    { | |
| 79 | - return 'vidi_clipboard_' . $this->getModuleLoader()->getDataType(); | |
| 80 | - } | |
| 74 | + /** | |
| 75 | + * @return string | |
| 76 | + */ | |
| 77 | + protected function getDataKey() | |
| 78 | +	{ | |
| 79 | + return 'vidi_clipboard_' . $this->getModuleLoader()->getDataType(); | |
| 80 | + } | |
| 81 | 81 | |
| 82 | - /** | |
| 83 | - * Get the Vidi Module Loader. | |
| 84 | - * | |
| 85 | - * @return ModuleLoader|object | |
| 86 | - */ | |
| 87 | - protected function getModuleLoader() | |
| 88 | -    { | |
| 89 | - return GeneralUtility::makeInstance(ModuleLoader::class); | |
| 90 | - } | |
| 82 | + /** | |
| 83 | + * Get the Vidi Module Loader. | |
| 84 | + * | |
| 85 | + * @return ModuleLoader|object | |
| 86 | + */ | |
| 87 | + protected function getModuleLoader() | |
| 88 | +	{ | |
| 89 | + return GeneralUtility::makeInstance(ModuleLoader::class); | |
| 90 | + } | |
| 91 | 91 | |
| 92 | - /** | |
| 93 | - * Returns an instance of the current Backend User. | |
| 94 | - * | |
| 95 | - * @return BackendUserAuthentication | |
| 96 | - */ | |
| 97 | - protected function getBackendUser() | |
| 98 | -    { | |
| 99 | - return $GLOBALS['BE_USER']; | |
| 100 | - } | |
| 92 | + /** | |
| 93 | + * Returns an instance of the current Backend User. | |
| 94 | + * | |
| 95 | + * @return BackendUserAuthentication | |
| 96 | + */ | |
| 97 | + protected function getBackendUser() | |
| 98 | +	{ | |
| 99 | + return $GLOBALS['BE_USER']; | |
| 100 | + } | |
| 101 | 101 | } | 
| @@ -15,27 +15,27 @@ | ||
| 15 | 15 | */ | 
| 16 | 16 | class ConstraintContainer | 
| 17 | 17 |  { | 
| 18 | - /** | |
| 19 | - * @var ConstraintInterface | |
| 20 | - */ | |
| 21 | - protected $constraint; | |
| 18 | + /** | |
| 19 | + * @var ConstraintInterface | |
| 20 | + */ | |
| 21 | + protected $constraint; | |
| 22 | 22 | |
| 23 | - /** | |
| 24 | - * @return ConstraintInterface | |
| 25 | - */ | |
| 26 | - public function getConstraint() | |
| 27 | -    { | |
| 28 | - return $this->constraint; | |
| 29 | - } | |
| 23 | + /** | |
| 24 | + * @return ConstraintInterface | |
| 25 | + */ | |
| 26 | + public function getConstraint() | |
| 27 | +	{ | |
| 28 | + return $this->constraint; | |
| 29 | + } | |
| 30 | 30 | |
| 31 | - /** | |
| 32 | - * @param ConstraintInterface $constraint | |
| 33 | - * @return $this | |
| 34 | - */ | |
| 35 | - public function setConstraint($constraint) | |
| 36 | -    { | |
| 37 | - $this->constraint = $constraint; | |
| 38 | - return $this; | |
| 39 | - } | |
| 31 | + /** | |
| 32 | + * @param ConstraintInterface $constraint | |
| 33 | + * @return $this | |
| 34 | + */ | |
| 35 | + public function setConstraint($constraint) | |
| 36 | +	{ | |
| 37 | + $this->constraint = $constraint; | |
| 38 | + return $this; | |
| 39 | + } | |
| 40 | 40 | |
| 41 | 41 | } |