Total Complexity | 47 |
Total Lines | 288 |
Duplicated Lines | 0 % |
Changes | 3 | ||
Bugs | 2 | Features | 0 |
Complex classes like BlocksModuleInstaller 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.
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 BlocksModuleInstaller, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
37 | class BlocksModuleInstaller extends AbstractExtensionInstaller |
||
38 | { |
||
39 | /** |
||
40 | * @var array |
||
41 | */ |
||
42 | private $entities = [ |
||
43 | BlockEntity::class, |
||
44 | BlockPositionEntity::class, |
||
45 | BlockPlacementEntity::class |
||
46 | ]; |
||
47 | |||
48 | /** |
||
49 | * @var ZikulaHttpKernelInterface |
||
50 | */ |
||
51 | private $kernel; |
||
52 | |||
53 | public function __construct( |
||
64 | } |
||
65 | |||
66 | public function install(): bool |
||
79 | } |
||
80 | |||
81 | public function upgrade(string $oldVersion): bool |
||
82 | { |
||
83 | $blockRepository = $this->entityManager->getRepository(BlockEntity::class); |
||
84 | // Upgrade dependent on old version number |
||
85 | switch ($oldVersion) { |
||
86 | case '3.8.1': |
||
87 | case '3.8.2': |
||
88 | case '3.9.0': |
||
89 | $sql = 'SELECT * FROM blocks'; |
||
90 | $blocks = $this->entityManager->getConnection()->fetchAll($sql); |
||
|
|||
91 | foreach ($blocks as $block) { |
||
92 | $content = $block['content']; |
||
93 | if ($this->isSerialized($content)) { |
||
94 | $content = unserialize($content); |
||
95 | foreach ($content as $k => $item) { |
||
96 | if (is_string($item)) { |
||
97 | if (false !== mb_strpos($item, 'blocks_block_extmenu_topnav.tpl')) { |
||
98 | $content[$k] = str_replace('blocks_block_extmenu_topnav.tpl', 'Block/Extmenu/topnav.tpl', $item); |
||
99 | } elseif (false !== mb_strpos($item, 'blocks_block_extmenu.tpl')) { |
||
100 | $content[$k] = str_replace('blocks_block_extmenu.tpl', 'Block/Extmenu/extmenu.tpl', $item); |
||
101 | } elseif (false !== mb_strpos($item, 'menutree/blocks_block_menutree_')) { |
||
102 | $content[$k] = str_replace('menutree/blocks_block_menutree_', 'Block/Menutree/', $item); |
||
103 | } |
||
104 | } |
||
105 | } |
||
106 | $this->entityManager->getConnection()->executeUpdate('UPDATE blocks SET content=? WHERE bid=?', [serialize($content), $block['bid']]); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | // check if request is available (#2073) |
||
111 | $templateWarning = $this->trans('Warning: Block template locations modified, you may need to fix your template overrides if you have any.'); |
||
112 | $request = $this->requestStack->getMasterRequest(); |
||
113 | if ( |
||
114 | is_object($request) |
||
115 | && method_exists($request, 'getSession') |
||
116 | && is_object($request->getSession()) |
||
117 | ) { |
||
118 | $this->addFlash('warning', $templateWarning); |
||
119 | } |
||
120 | case '3.9.1': |
||
121 | // make all content fields of blocks serialized. |
||
122 | $sql = 'SELECT * FROM blocks'; |
||
123 | $blocks = $this->entityManager->getConnection()->fetchAll($sql); |
||
124 | $oldContent = []; |
||
125 | foreach ($blocks as $block) { |
||
126 | $block['content'] = !empty($block['content']) ? $block['content'] : ''; |
||
127 | $oldContent[$block['bid']] = $this->isSerialized($block['content']) ? unserialize($block['content']) : ['content' => $block['content']]; |
||
128 | } |
||
129 | $this->schemaTool->update($this->entities); |
||
130 | $this->entityManager->getConnection()->executeQuery("UPDATE blocks SET properties='a:0:{}'"); |
||
131 | |||
132 | $blocks = $blockRepository->findAll(); |
||
133 | $installerHelper = new InstallerHelper(); |
||
134 | /** @var ZikulaHttpKernelInterface $kernel */ |
||
135 | /** @var BlockEntity $block */ |
||
136 | foreach ($blocks as $block) { |
||
137 | $block->setProperties($oldContent[$block->getBid()]); |
||
138 | $block->setFilters($installerHelper->upgradeFilterArray($block->getFilters())); |
||
139 | $block->setBlocktype(preg_match('/Block$/', $block->getBkey()) ? mb_substr($block->getBkey(), 0, -5) : $block->getBkey()); |
||
140 | $block->setBkey($installerHelper->upgradeBkeyToFqClassname($this->kernel, $block)); |
||
141 | } |
||
142 | $this->entityManager->flush(); |
||
143 | |||
144 | $collapseable = $this->getVar('collapseable'); |
||
145 | $this->setVar('collapseable', (bool)$collapseable); |
||
146 | |||
147 | case '3.9.2': |
||
148 | // convert Text and Html block types so properties is proper array |
||
149 | $blocks = $blockRepository->findBy(['blocktype' => ['Html', 'Text']]); |
||
150 | foreach ($blocks as $block) { |
||
151 | $properties = $block->getProperties(); |
||
152 | if (!is_array($properties)) { |
||
153 | $block->setProperties(['content' => $properties]); |
||
154 | } |
||
155 | } |
||
156 | $this->entityManager->flush(); |
||
157 | case '3.9.3': |
||
158 | $this->schemaTool->drop([ |
||
159 | 'Zikula\BlocksModule\Entity\UserBlockEntity' |
||
160 | ]); |
||
161 | case '3.9.4': |
||
162 | // convert integer values to boolean for search block settings |
||
163 | $searchBlocks = $blockRepository->findBy(['blocktype' => 'Search']); |
||
164 | foreach ($searchBlocks as $searchBlock) { |
||
165 | $properties = $searchBlock->getProperties(); |
||
166 | $properties['displaySearchBtn'] = (bool)$properties['displaySearchBtn']; |
||
167 | if (isset($properties['active'])) { |
||
168 | foreach ($properties['active'] as $module => $active) { |
||
169 | $properties['active'][$module] = (bool)$active; |
||
170 | } |
||
171 | } |
||
172 | $searchBlock->setProperties($properties); |
||
173 | } |
||
174 | $this->entityManager->flush(); |
||
175 | case '3.9.5': |
||
176 | $loginBlocks = $blockRepository->findBy(['blocktype' => 'Login']); |
||
177 | foreach ($loginBlocks as $loginBlock) { |
||
178 | $filters = $loginBlock->getFilters(); |
||
179 | $filters[] = [ |
||
180 | 'attribute' => '_route', |
||
181 | 'queryParameter' => null, |
||
182 | 'comparator' => '!=', |
||
183 | 'value' => 'zikulausersmodule_access_login' |
||
184 | ]; |
||
185 | $loginBlock->setFilters($filters); |
||
186 | } |
||
187 | $this->entityManager->flush(); |
||
188 | case '3.9.6': |
||
189 | $statement = $this->entityManager->getConnection()->executeQuery("SELECT * FROM blocks WHERE blocktype = 'Lang'"); |
||
190 | $blocks = $statement->fetchAll(\PDO::FETCH_ASSOC); |
||
191 | if (count($blocks) > 0) { |
||
192 | $this->entityManager->getConnection()->executeQuery("UPDATE blocks set bkey=?, blocktype=?, properties=? WHERE blocktype = 'Lang'", [ |
||
193 | 'ZikulaSettingsModule:Zikula\SettingsModule\Block\LocaleBlock', |
||
194 | 'Locale', |
||
195 | 'a:0:{}' |
||
196 | ]); |
||
197 | $this->addFlash('success', 'All instances of LangBlock have been converted to LocaleBlock.'); |
||
198 | } |
||
199 | $this->entityManager->getConnection()->executeQuery("UPDATE group_perms SET component = REPLACE(component, 'Languageblock', 'LocaleBlock') WHERE component LIKE 'Languageblock%'"); |
||
200 | case '3.9.7': |
||
201 | case '3.9.8': |
||
202 | $statement = $this->entityManager->getConnection()->executeQuery("SELECT * FROM blocks"); |
||
203 | $blocks = $statement->fetchAll(\PDO::FETCH_ASSOC); |
||
204 | foreach ($blocks as $block) { |
||
205 | $bKey = $block['bkey']; |
||
206 | if (mb_strpos($bKey, ':')) { |
||
207 | [/*$moduleName*/, $bKey] = explode(':', $bKey); |
||
208 | } |
||
209 | $this->entityManager->getConnection()->executeUpdate('UPDATE blocks SET bKey=? WHERE bid=?', [trim($bKey, '\\'), $block['bid']]); |
||
210 | } |
||
211 | case '3.9.9': |
||
212 | // future upgrade routines |
||
213 | } |
||
214 | |||
215 | // Update successful |
||
216 | return true; |
||
217 | } |
||
218 | |||
219 | public function uninstall(): bool |
||
220 | { |
||
221 | // Deletion not allowed |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Add default block data for new installations. |
||
227 | * This is called after a complete installation since the blocks |
||
228 | * need to be populated with module id's which are only available |
||
229 | * once the installation has been completed. |
||
230 | */ |
||
231 | public function createDefaultData(): void |
||
232 | { |
||
233 | // create the default block positions - left, right and center for the traditional 3 column layout |
||
234 | $positions = [ |
||
235 | 'left' => $this->trans('Left blocks'), |
||
236 | 'right' => $this->trans('Right blocks'), |
||
237 | 'center' => $this->trans('Center blocks'), |
||
238 | 'search' => $this->trans('Search block'), |
||
239 | 'header' => $this->trans('Header block'), |
||
240 | 'footer' => $this->trans('Footer block'), |
||
241 | 'topnav' => $this->trans('Top navigation block'), |
||
242 | 'bottomnav' => $this->trans('Bottom navigation block') |
||
243 | ]; |
||
244 | foreach ($positions as $name => $description) { |
||
245 | $positions[$name] = new BlockPositionEntity(); |
||
246 | $positions[$name]->setName($name); |
||
247 | $positions[$name]->setDescription($description); |
||
248 | $this->entityManager->persist($positions[$name]); |
||
249 | } |
||
250 | $this->entityManager->flush(); |
||
251 | |||
252 | $hellomessage = $this->trans('<p><a href="https://ziku.la">Zikula</a> is an Open Source Content Application Framework built on top of Symfony.</p><p>With Zikula you get:</p><ul><li><strong>Power:</strong> You get the all the features of <a href="https://symfony.com">Symfony</a> PLUS: </li><li><strong>User Management:</strong> Built in User and Group management with Rights/Roles control</li><li><strong>Front end control:</strong> You can customise all aspects of the site\'s appearance through themes, with support for <a href="http://jquery.com">jQuery</a>, <a href="http://getbootstrap.com">Bootstrap</a> and many other modern technologies</li><li><strong>Internationalization (i18n):</strong> You can mark content as being suitable for either a single language or for all languages, and can control all aspects of localisation of your site</li><li><strong>Extensibility:</strong> you get a standard application-programming interface (API) that lets you easily extend your site\'s functionality through modules</li><li><strong>More:</strong> Admin UI, global categories, site-wide search, content blocks, menu creation, and more!</li><li><strong>Support:</strong> you can get help and support from the Zikula community of webmasters and developers at <a href="https://ziku.la">ziku.la</a>, <a href="https://github.com/zikula/core">Github</a> and <a href="https://zikula.slack.com/">Slack</a>.</li></ul><p>Enjoy using Zikula!</p><p><strong>The Zikula team</strong></p><p><em>Note: Zikula is Free Open Source Software (FOSS) licensed under the GNU General Public License.</em></p>'); |
||
253 | |||
254 | $blocks = []; |
||
255 | $extensionRepo = $this->entityManager->getRepository(ExtensionEntity::class); |
||
256 | $blocksModuleEntity = $extensionRepo->findOneBy(['name' => 'ZikulaBlocksModule']); |
||
257 | $searchModuleEntity = $extensionRepo->findOneBy(['name' => 'ZikulaSearchModule']); |
||
258 | $usersModuleEntity = $extensionRepo->findOneBy(['name' => 'ZikulaUsersModule']); |
||
259 | $blocks[] = [ |
||
260 | 'bkey' => SearchBlock::class, |
||
261 | 'blocktype' => 'Search', |
||
262 | 'language' => '', |
||
263 | 'module' => $searchModuleEntity, |
||
264 | 'title' => $this->trans('Search box'), |
||
265 | 'description' => $this->trans('Search block'), |
||
266 | 'properties' => [ |
||
267 | 'displaySearchBtn' => true, |
||
268 | 'active' => ['ZikulaUsersModule' => 1] |
||
269 | ], |
||
270 | 'position' => $positions['left'] |
||
271 | ]; |
||
272 | $blocks[] = [ |
||
273 | 'bkey' => HtmlBlock::class, |
||
274 | 'blocktype' => 'Html', |
||
275 | 'language' => '', |
||
276 | 'module' => $blocksModuleEntity, |
||
277 | 'title' => $this->trans('This site is powered by Zikula!'), |
||
278 | 'description' => $this->trans('HTML block'), |
||
279 | 'properties' => ['content' => $hellomessage], |
||
280 | 'position' => $positions['center'] |
||
281 | ]; |
||
282 | $blocks[] = [ |
||
283 | 'bkey' => LoginBlock::class, |
||
284 | 'blocktype' => 'Login', |
||
285 | 'language' => '', |
||
286 | 'module' => $usersModuleEntity, |
||
287 | 'title' => $this->trans('User log-in'), |
||
288 | 'description' => $this->trans('Login block'), |
||
289 | 'position' => $positions['topnav'], |
||
290 | 'order' => 1, |
||
291 | 'filters' => [[ |
||
292 | 'attribute' => '_route', |
||
293 | 'queryParameter' => null, |
||
294 | 'comparator' => '!=', |
||
295 | 'value' => 'zikulausersmodule_access_login' |
||
296 | ]] |
||
297 | ]; |
||
298 | |||
299 | foreach ($blocks as $block) { |
||
300 | $blockEntity = new BlockEntity(); |
||
301 | $position = $block['position']; |
||
302 | $sortOrder = !empty($block['order']) ? $block['order'] : 0; |
||
303 | unset($block['position'], $block['order']); |
||
304 | $blockEntity->merge($block); |
||
305 | $this->entityManager->persist($blockEntity); |
||
306 | $placement = new BlockPlacementEntity(); |
||
307 | $placement->setBlock($blockEntity); |
||
308 | $placement->setPosition($position); |
||
309 | $placement->setSortorder($sortOrder); |
||
310 | $this->entityManager->persist($placement); |
||
311 | } |
||
312 | $this->entityManager->flush(); |
||
313 | } |
||
314 | |||
315 | private function isSerialized($string): bool |
||
325 | } |
||
326 | } |
||
327 |