Completed
Push — master ( d535d3...8c6cf6 )
by Felix
16:53
created

Tx_FeatureFlag_System_Typo3_TCA   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 7
dl 0
loc 298
rs 8.2769
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
B renderSelectForFlag() 0 23 4
A renderInfo() 0 5 1
B renderSelectForBehavior() 0 31 6
A processDatamap_preProcessFieldArray() 0 14 3
B processCmdmap_postProcess() 0 17 6
B postOverlayPriorityLookup() 0 19 5
B updateMapping() 0 26 4
A isMappingAvailableForTableAndUid() 0 12 3
A getFeatureFlagByUid() 0 10 2
A getMappingRepository() 0 4 1
A getFeatureFlagRepository() 0 4 1
A getObjectManager() 0 8 2
A getPersistenceManager() 0 8 2
A getLanguageService() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Tx_FeatureFlag_System_Typo3_TCA often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Tx_FeatureFlag_System_Typo3_TCA, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/***************************************************************
4
 *  Copyright notice
5
 *
6
 *  (c) 2016 AOE GmbH <[email protected]>
7
 *
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
/**
28
 * @package FeatureFlag
29
 * @subpackage System_Typo3
30
 */
31
class Tx_FeatureFlag_System_Typo3_TCA
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
32
{
33
    /**
34
     * @var string
35
     */
36
    const FIELD_BEHAVIOR = 'tx_featureflag_behavior';
37
38
    /**
39
     * @var string
40
     */
41
    const FIELD_FLAG = 'tx_featureflag_flag';
42
43
    /**
44
     * @var Tx_FeatureFlag_Domain_Repository_FeatureFlag
45
     */
46
    protected $featureFlagRepository;
47
48
    /**
49
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
50
     */
51
    protected $objectManager;
52
53
    /**
54
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
55
     */
56
    protected $persistenceManager;
57
58
    /**
59
     * @var \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
60
     */
61
    protected static $hashedMappings;
62
63
64
    /**
65
     * @param array $PA
66
     * @return string
67
     */
68
    public function renderSelectForFlag(array $PA)
69
    {
70
        $activeMapping = $this->getMappingRepository()->findOneByForeignTableNameAndUid($PA['row']['uid'], $PA['table']);
71
72
        $html = '';
73
        $html .= '<select class="select" id="' . $PA['itemFormElID'] . '" name="' . $PA['itemFormElName'] . '">';
74
        $html .= '<option value="0"></option>';
75
        foreach ($this->getFeatureFlagRepository()->findAll() as $featureFlag) {
76
            /** @var Tx_FeatureFlag_Domain_Model_FeatureFlag $featureFlag */
77
            $selected = '';
78
            if ($activeMapping instanceof Tx_FeatureFlag_Domain_Model_Mapping &&
79
                $activeMapping->getFeatureFlag()->getUid() === $featureFlag->getUid()
80
            ) {
81
                $selected = ' selected="selected"';
82
            }
83
            $value = $featureFlag->getUid();
84
            $label = $featureFlag->getDescription();
85
            $html .= '<option value="' . $value . '"' . $selected . '>' . $label . '</option>';
86
        }
87
        $html .= '</select>';
88
89
        return $html;
90
    }
91
92
    /**
93
     * @param array $PA
94
     * @return string
95
     */
96
    public function renderInfo(array $PA)
0 ignored issues
show
Unused Code introduced by
The parameter $PA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
97
    {
98
        $langField = 'LLL:EXT:feature_flag/Resources/Private/Language/locallang_db.xml:tx_featureflag_info.text';
99
        return $this->getLanguageService()->sL($langField);
100
    }
101
102
    /**
103
     * @param array $PA
104
     * @return string
105
     */
106
    public function renderSelectForBehavior(array $PA)
107
    {
108
        // check, which behavior is selected
109
        $isBehaviorHideSelected = false;
110
        $isBehaviorShowSelected = false;
111
        $activeMapping = $this->getMappingRepository()->findOneByForeignTableNameAndUid($PA['row']['uid'], $PA['table']);
112
        if ($activeMapping instanceof Tx_FeatureFlag_Domain_Model_Mapping) {
113
            if ($activeMapping->getBehavior() === Tx_FeatureFlag_Service::BEHAVIOR_HIDE) {
114
                $isBehaviorHideSelected = true;
115
            } elseif ($activeMapping->getBehavior() === Tx_FeatureFlag_Service::BEHAVIOR_SHOW) {
116
                $isBehaviorShowSelected = true;
117
            }
118
        }
119
120
        // build select-box
121
        $html = '';
122
        $html .= '<select class="select" id="' . $PA['itemFormElID'] . '" name="' . $PA['itemFormElName'] . '">';
123
        $html .= '<option value="' . Tx_FeatureFlag_Service::BEHAVIOR_HIDE . '"' . ($isBehaviorHideSelected ? ' selected="selected"' : '') .
124
            '>';
125
        $langField = 'LLL:EXT:feature_flag/Resources/Private/Language/locallang_db.xml:tx_featureflag_behavior.hide';
126
        $html .= $this->getLanguageService()->sL($langField);
127
        $html .= '</option>';
128
        $html .= '<option value="' . Tx_FeatureFlag_Service::BEHAVIOR_SHOW . '"' . ($isBehaviorShowSelected ? ' selected="selected"' : '') .
129
            '>';
130
        $langField = 'LLL:EXT:feature_flag/Resources/Private/Language/locallang_db.xml:tx_featureflag_behavior.show';
131
        $html .= $this->getLanguageService()->sL($langField);
132
        $html .= '</option>';
133
        $html .= '</select>';
134
135
        return $html;
136
    }
137
138
    /**
139
     * Hook for updates in Typo3 backend
140
     * @param array $incomingFieldArray
141
     * @param string $table
142
     * @param integer $id
143
     * @param \TYPO3\CMS\Core\DataHandling\DataHandler $tceMain
144
     * @codingStandardsIgnoreStart
145
     */
146
    public function processDatamap_preProcessFieldArray(
147
        &$incomingFieldArray,
148
        $table,
149
        $id,
150
        \TYPO3\CMS\Core\DataHandling\DataHandler &$tceMain
151
    ) {
152
        // @codingStandardsIgnoreEnd
153
        if (array_key_exists(self::FIELD_BEHAVIOR, $incomingFieldArray) && array_key_exists(self::FIELD_FLAG, $incomingFieldArray)) {
154
            $pid = $tceMain->getPID($table, $id);
155
            $this->updateMapping($table, $id, $incomingFieldArray[self::FIELD_FLAG], $pid, $incomingFieldArray[self::FIELD_BEHAVIOR]);
0 ignored issues
show
Security Bug introduced by
It seems like $pid defined by $tceMain->getPID($table, $id) on line 154 can also be of type false; however, Tx_FeatureFlag_System_Typo3_TCA::updateMapping() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
156
            unset($incomingFieldArray[self::FIELD_BEHAVIOR]);
157
            unset($incomingFieldArray[self::FIELD_FLAG]);
158
        }
159
    }
160
161
    /**
162
     * Hook for deletes in Typo3 Backend. It also delete all overwrite protection
163
     * @param string $command
164
     * @param string $table
165
     * @param integer $id
166
     * @codingStandardsIgnoreStart
167
     */
168
    public function processCmdmap_postProcess($command, $table, $id)
169
    {
170
        // @codingStandardsIgnoreEnd
171
        if ($command !== 'delete') {
172
            return;
173
        }
174
        $mappings = $this->getMappingRepository()->findAllByForeignTableNameAndUid($id, $table);
175
        if (false === is_array($mappings) && false === ($mappings instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface)) {
176
            return;
177
        }
178
        foreach ($mappings as $mapping) {
179
            if ($mapping instanceof Tx_FeatureFlag_Domain_Model_Mapping) {
180
                $this->getMappingRepository()->remove($mapping);
181
            }
182
        }
183
        $this->getPersistenceManager()->persistAll();
184
    }
185
186
    /**
187
     * @param string $table
188
     * @param array $row
189
     * @param string $status
190
     * @param string $iconName
191
     * @return string
192
     */
193
    public function postOverlayPriorityLookup($table, $row, &$status, $iconName)
0 ignored issues
show
Unused Code introduced by
The parameter $status is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
    {
195
        if ($this->isMappingAvailableForTableAndUid($row['uid'], $table)) {
196
            $mapping = $this->getMappingRepository()->findOneByForeignTableNameAndUid($row['uid'], $table);
197
            if ($mapping instanceof Tx_FeatureFlag_Domain_Model_Mapping) {
198
                if ($row['hidden'] === '1') {
199
                    return 'record-has-feature-flag-which-is-hidden';
200
                }
201
                if ($iconName !== '') {
202
                    // if record is e.g. hidden or protected by FE-group, than show that (e.g. 'hidden' or 'fe_group'-)overlay as default
203
                    return $iconName;
204
                }
205
                return 'record-has-feature-flag-which-is-visible';
206
            }
207
        }
208
209
        // return given icon-name as fall-back
210
        return $iconName;
211
    }
212
213
    /**
214
     * @param string $table
215
     * @param int $id
216
     * @param int $featureFlag
217
     * @param int $pid
218
     * @param string $behavior
219
     */
220
    protected function updateMapping($table, $id, $featureFlag, $pid, $behavior)
221
    {
222
        $mapping = $this->getMappingRepository()->findOneByForeignTableNameAndUid($id, $table);
223
        if ($mapping instanceof Tx_FeatureFlag_Domain_Model_Mapping) {
224
            if ('0' === $featureFlag) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of '0' (string) and $featureFlag (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
225
                $this->getMappingRepository()->remove($mapping);
226
            } else {
227
                $mapping->setFeatureFlag($this->getFeatureFlagByUid($featureFlag));
228
                $mapping->setBehavior($behavior);
229
            }
230
            $mapping->setTstamp(time());
231
            $this->getMappingRepository()->update($mapping);
232
        } elseif ('0' !== $featureFlag) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of '0' (string) and $featureFlag (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
233
            /** @var Tx_FeatureFlag_Domain_Model_Mapping $mapping */
234
            $mapping = $this->getObjectManager()->get('Tx_FeatureFlag_Domain_Model_Mapping');
235
            $mapping->setPid($pid);
236
            $mapping->setFeatureFlag($this->getFeatureFlagByUid($featureFlag));
237
            $mapping->setForeignTableName($table);
238
            $mapping->setForeignTableUid($id);
239
            $mapping->setCrdate(time());
240
            $mapping->setTstamp(time());
241
            $mapping->setBehavior($behavior);
242
            $this->getMappingRepository()->add($mapping);
243
        }
244
        $this->getPersistenceManager()->persistAll();
245
    }
246
247
    /**
248
     * @param int $foreignTableUid
249
     * @param string $foreignTableName
250
     * @return bool
251
     */
252
    protected function isMappingAvailableForTableAndUid($foreignTableUid, $foreignTableName)
253
    {
254
        if (null === self::$hashedMappings) {
255
            self::$hashedMappings = $this->getMappingRepository()->getHashedMappings();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getMappingReposit...()->getHashedMappings() of type array is incompatible with the declared type object<TYPO3\CMS\Extbase...e\QueryResultInterface> of property $hashedMappings.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
256
        }
257
        $identifier = sha1($foreignTableUid . '_' . $foreignTableName);
258
        if (array_key_exists($identifier, self::$hashedMappings)) {
259
            return true;
260
        }
261
262
        return false;
263
    }
264
265
    /**
266
     * @param int $uid
267
     * @return Tx_FeatureFlag_Domain_Model_FeatureFlag
268
     * @throws Tx_FeatureFlag_Service_Exception_FeatureNotFound
269
     */
270
    protected function getFeatureFlagByUid($uid)
271
    {
272
        /** @var Tx_FeatureFlag_Domain_Model_FeatureFlag $featureFlag */
273
        $featureFlag = $this->getFeatureFlagRepository()->findByUid($uid);
274
        if (false === ($featureFlag instanceof Tx_FeatureFlag_Domain_Model_FeatureFlag)) {
275
            throw new Tx_FeatureFlag_Service_Exception_FeatureNotFound('Feature Flag not found by uid: "' . $uid . '"', 1384340431);
276
        }
277
278
        return $featureFlag;
279
    }
280
281
    /**
282
     * @return Tx_FeatureFlag_Domain_Repository_Mapping
283
     */
284
    protected function getMappingRepository()
285
    {
286
        return $this->getObjectManager()->get('Tx_FeatureFlag_Domain_Repository_Mapping');
287
    }
288
289
    /**
290
     * @return Tx_FeatureFlag_Domain_Repository_FeatureFlag
291
     */
292
    protected function getFeatureFlagRepository()
293
    {
294
        return $this->getObjectManager()->get('Tx_FeatureFlag_Domain_Repository_FeatureFlag');
295
    }
296
297
    /**
298
     * @return \TYPO3\CMS\Extbase\Object\ObjectManager
299
     */
300
    protected function getObjectManager()
301
    {
302
        if (false === ($this->objectManager instanceof \TYPO3\CMS\Extbase\Object\ObjectManager)) {
303
            $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
304
        }
305
306
        return $this->objectManager;
307
    }
308
309
    /**
310
     * @return \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
311
     */
312
    protected function getPersistenceManager()
313
    {
314
        if (false === $this->persistenceManager instanceof \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager) {
315
            $this->persistenceManager = $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
316
        }
317
318
        return $this->persistenceManager;
319
    }
320
321
    /**
322
     * @return TYPO3\CMS\Lang\LanguageService
323
     */
324
    protected function getLanguageService()
325
    {
326
        return $GLOBALS['LANG'];
327
    }
328
}
329