Guest User

Untitled

a guest
Dec 14th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.72 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. from plone import api
  3. from plone.app.textfield.interfaces import TransformError
  4. from plone.app.textfield.value import RichTextValue
  5. from plone.app.theming.utils import applyTheme
  6. from plone.portlets.interfaces import IPortletAssignmentMapping
  7. from plone.portlets.interfaces import IPortletManager
  8. from Products.CMFPlone.interfaces import IPloneSiteRoot
  9. from Products.PluginIndexes.common import safe_callable
  10. from plone.app.layout.navigation.interfaces import INavigationRoot
  11. from OFS.CopySupport import CopyError
  12. from zope.component import getMultiAdapter
  13. from zope.component import getUtility
  14. from zope.globalrequest import getRequest
  15. from zExceptions import BadRequest
  16.  
  17. import logging
  18. import transaction
  19.  
  20. log = logging.getLogger(__name__)
  21.  
  22.  
  23. def cleanup_addons(setup):
  24. """1000 -> 1001
  25. Step is to be run in Plone 4.3.x
  26. """
  27. patch_indexing_at_blobs()
  28. patch_indexing_dx_blobs()
  29.  
  30. # init
  31. portal = api.portal.get()
  32. catalog = api.portal.get_tool('portal_catalog')
  33. qi = api.portal.get_tool('portal_quickinstaller')
  34. css = api.portal.get_tool('portal_css')
  35. controlpanel = api.portal.get_tool('portal_controlpanel')
  36. portal_properties = api.portal.get_tool('portal_properties')
  37. portal_skins = api.portal.get_tool('portal_skins')
  38.  
  39. to_delete = [
  40. '/nm/microsite/sip/astrid/carousel',
  41. '/nm/nuetzliches/carousel',
  42. ]
  43. for path in to_delete:
  44. try:
  45. obj = api.content.get(path=path)
  46. if obj is not None:
  47. api.content.delete(obj, check_linkintegrity=False)
  48. except:
  49. continue
  50. log.info('Deleted %s' % path)
  51.  
  52. # remove overrides
  53. custom = portal_skins['custom']
  54. for name in custom.keys():
  55. custom.manage_delObjects([name])
  56.  
  57. log.info('removing portal_view_customizations')
  58. view_customizations = api.portal.get_tool('portal_view_customizations')
  59. for name in view_customizations.keys():
  60. view_customizations.manage_delObjects([name])
  61.  
  62. # Remove collective.easyslider
  63. if qi.isProductInstalled('collective.easyslider'):
  64. from collective.easyslider.interfaces import IViewEasySlider
  65. for brain in api.content.find(
  66. object_provides=IViewEasySlider.__identifier__):
  67. obj = brain.getObject()
  68. # noLongerProvides(obj, IViewEasySlider)
  69. if obj.getLayout() == 'sliderview':
  70. obj.manage_delProperties(['layout'])
  71. log.info('removed easyslider from {}'.format(brain.getURL()))
  72. controlpanel.unregisterConfiglet('easyslieder')
  73. qi.uninstallProducts(['collective.easyslider'])
  74. try:
  75. portal_properties.manage_delObjects(['easyslideshow_properties'])
  76. except BadRequest:
  77. pass
  78.  
  79. # remove cciaa.modulistica
  80. log.info('removing cciaa.modulistica')
  81. if qi.isProductInstalled('cciaa.modulistica'):
  82. catalog._removeIndex('getRawRelatedItems')
  83. css.manage_removeStylesheet('++resource++cciaa.modulistica.stylesheets/cciaa.modulistica.css') # noqa: E501
  84. from cciaa.modulistica.interfaces import CCIAAModAbleContent
  85. for brain in api.content.find(
  86. object_provides=CCIAAModAbleContent.__identifier__):
  87. obj = brain.getObject()
  88. # noLongerProvides(obj, IViewEasySlider)
  89. if obj.getLayout() == 'cciaa_modulistica_view':
  90. obj.manage_delProperties(['layout'])
  91. log.info('removed cciaa.modulistica from {}'.format(brain.getURL())) # noqa: E501
  92. qi.uninstallProducts(['cciaa.modulistica'])
  93.  
  94. # Solgema.fullcalendar
  95. log.info('removing Solgema.fullcalendar')
  96. if qi.isProductInstalled('Solgema.fullcalendar'):
  97. qi.uninstallProducts(['Solgema.fullcalendar'])
  98.  
  99. # collective.imagetags
  100. log.info('removing collective.imagetags')
  101. if qi.isProductInstalled('collective.imagetags'):
  102. controlpanel.unregisterConfiglet('imagetags')
  103. # do not uninstall utilities since that will nuke the registry
  104. cascade = [
  105. 'types', 'skins', 'actions', 'portalobjects', 'workflows', 'slots',
  106. 'registrypredicates', 'adapters']
  107. qi.uninstallProducts(['collective.imagetags'], cascade=cascade)
  108.  
  109. # wpd.mmxi.countdown
  110. # delete portlet instance
  111. log.info('removing wpd.mmxi.countdown')
  112. content = api.content.get(path='/nm/netstal-intranet')
  113. if content:
  114. manager = getUtility(
  115. IPortletManager, name='plone.leftcolumn', context=content)
  116. mapping = getMultiAdapter(
  117. (content, manager), IPortletAssignmentMapping)
  118. try:
  119. del mapping['wpd-countdown']
  120. except KeyError:
  121. pass
  122.  
  123. if qi.isProductInstalled('wpd.mmxi.countdown'):
  124. qi.uninstallProducts(['wpd.mmxi.countdown'])
  125. try:
  126. setup.manage_deleteImportSteps(['wpd.mmxi.countdown-upgrades'])
  127. except KeyError:
  128. pass
  129.  
  130. # Products.Carousel
  131. log.info('removing Products.Carousel')
  132. if qi.isProductInstalled('Products.Carousel'):
  133. qi.uninstallProducts(['Products.Carousel'])
  134.  
  135. # Products.PlonePopoll
  136. log.info('removing Products.PlonePopoll')
  137. if qi.isProductInstalled('PlonePopoll'):
  138. qi.uninstallProducts(['PlonePopoll'])
  139.  
  140. # eea.facetednavigation
  141. log.info('removing eea.facetednavigation')
  142. if qi.isProductInstalled('eea.facetednavigation'):
  143. qi.uninstallProducts(['eea.facetednavigation'])
  144.  
  145. # eea.relations
  146. log.info('removing eea.relations')
  147. if qi.isProductInstalled('eea.relations'):
  148. qi.uninstallProducts(['eea.relations'])
  149.  
  150. # Products.ECLecture
  151. log.info('removing Products.ECLecture')
  152. if qi.isProductInstalled('ECLecture'):
  153. qi.uninstallProducts(['ECLecture'])
  154.  
  155. # Products.ImageEditor
  156. log.info('removing Products.ImageEditor')
  157. if qi.isProductInstalled('ImageEditor'):
  158. qi.uninstallProducts(['ImageEditor'])
  159.  
  160. # collective.plonetruegallery
  161. log.info('removing collective.plonetruegallery')
  162. if qi.isProductInstalled('collective.plonetruegallery'):
  163. qi.uninstallProducts(['collective.plonetruegallery'])
  164. try:
  165. setup.manage_deleteImportSteps(['collective.plonetruegallery.install'])
  166. except KeyError:
  167. pass
  168.  
  169. # zettwerk.ui
  170. log.info('removing zettwerk.ui')
  171. if qi.isProductInstalled('zettwerk.ui'):
  172. qi.uninstallProducts(['zettwerk.ui'])
  173. try:
  174. setup.manage_deleteImportSteps(['zettwerk.ui.disable_sunburst_patch'])
  175. except KeyError:
  176. pass
  177.  
  178. # Solgema.fullcalendar
  179. log.info('removing Solgema.fullcalendar')
  180. if qi.isProductInstalled('Solgema.fullcalendar'):
  181. qi.uninstallProducts(['Solgema.fullcalendar'])
  182.  
  183. # Solgema.ContextualContentMenu
  184. log.info('removing Solgema.ContextualContentMenu')
  185. if qi.isProductInstalled('Solgema.ContextualContentMenu'):
  186. qi.uninstallProducts(['Solgema.ContextualContentMenu'])
  187.  
  188. # Products.ImageEditor
  189. log.info('removing Products.ImageEditor')
  190. if qi.isProductInstalled('Products.ImageEditor'):
  191. qi.uninstallProducts(['Products.ImageEditor'])
  192. try:
  193. portal_properties.manage_delObjects(['imageeditor'])
  194. except BadRequest:
  195. pass
  196.  
  197. # collective.easyslideshow
  198. log.info('removing collective.easyslideshow')
  199. if qi.isProductInstalled('collective.easyslideshow'):
  200. qi.uninstallProducts(['collective.easyslideshow'])
  201. try:
  202. portal_properties.manage_delObjects(['easyslideshow_properties'])
  203. except BadRequest:
  204. pass
  205. _unregisterUtility(portal)
  206.  
  207. # collective.quickupload
  208. log.info('removing collective.quickupload')
  209. if qi.isProductInstalled('collective.quickupload'):
  210. qi.uninstallProducts(['collective.quickupload'])
  211. try:
  212. portal_properties.manage_delObjects(['quickupload_properties'])
  213. except BadRequest:
  214. pass
  215.  
  216. # collective.prettyphoto
  217. log.info('removing collective.prettyphoto')
  218. if qi.isProductInstalled('collective.prettyphoto'):
  219. qi.uninstallProducts(['collective.prettyphoto'])
  220. try:
  221. portal_properties.manage_delObjects(['prettyphoto_properties'])
  222. except BadRequest:
  223. pass
  224.  
  225. # collective.plonefinder
  226. log.info('removing collective.plonefinder')
  227. if qi.isProductInstalled('collective.plonefinder'):
  228. qi.uninstallProducts(['collective.plonefinder'])
  229.  
  230. # Products.PloneFormGen
  231. log.info('removing Products.PloneFormGen')
  232. if qi.isProductInstalled('PloneFormGen'):
  233. qi.uninstallProducts(['PloneFormGen'])
  234. try:
  235. portal_properties.manage_delObjects(['ploneformgen_properties'])
  236. except BadRequest:
  237. pass
  238.  
  239. # DataGridField
  240. log.info('removing DataGridField')
  241. if qi.isProductInstalled('DataGridField'):
  242. qi.uninstallProducts(['DataGridField'])
  243.  
  244. # collective.js.fullcalendar
  245. log.info('removing collective.js.fullcalendar')
  246. if qi.isProductInstalled('collective.js.fullcalendar'):
  247. qi.uninstallProducts(['collective.js.fullcalendar'])
  248.  
  249. # Products.PloneFlashUpload (not installed)
  250. log.info('removing Products.PloneFlashUpload')
  251. if qi.isProductInstalled('Products.PloneFlashUpload'):
  252. qi.uninstallProducts(['Products.PloneFlashUpload'])
  253.  
  254. # netstal.contenttype.person
  255. log.info('removing netstal.contenttype.person')
  256. if qi.isProductInstalled('netstal.contenttype.person'):
  257. qi.uninstallProducts(['netstal.contenttype.person'])
  258.  
  259. # p4a.subtyper
  260. log.info('removing p4a.subtyper')
  261. if qi.isProductInstalled('p4a.subtyper'):
  262. qi.uninstallProducts(['p4a.subtyper'])
  263.  
  264. # collective.externaleditor
  265. log.info('removing collective.externaleditor')
  266. if qi.isProductInstalled('collective.externaleditor'):
  267. qi.uninstallProducts(['collective.externaleditor'])
  268.  
  269. # collective.ckeditor
  270. log.info('removing collective.ckeditor')
  271. if qi.isProductInstalled('collective.ckeditor'):
  272. qi.uninstallProducts(['collective.ckeditor'])
  273. try:
  274. portal_properties.manage_delObjects(['ckeditor_properties'])
  275. except BadRequest:
  276. pass
  277.  
  278. # redturtle.smartlink
  279. log.info('removing redturtle.smartlink')
  280. if qi.isProductInstalled('redturtle.smartlink'):
  281. # run migration
  282. setup.runAllImportStepsFromProfile(
  283. 'profile-redturtle.smartlink:smartLinkToATLink', purge_old=False)
  284. qi.uninstallProducts(['redturtle.smartlink'])
  285.  
  286. # collective.js.jqueryui
  287. log.info('removing collective.js.jqueryui')
  288. if qi.isProductInstalled('collective.js.jqueryui'):
  289. qi.uninstallProducts(['collective.js.jqueryui'])
  290. try:
  291. portal_properties.manage_delObjects(['jqueryui_properties'])
  292. except BadRequest:
  293. pass
  294.  
  295. # finally run uninstall-profile
  296. log.info('run step to_1001')
  297. setup.runAllImportStepsFromProfile(
  298. 'profile-netstal.policy:to_1001', purge_old=False)
  299.  
  300. # other
  301. log.info('remove configlets')
  302. controlpanel.unregisterConfiglet('UsersGroups2')
  303. controlpanel.unregisterConfiglet('clickmap')
  304. # controlpanel.unregisterConfiglet('WindowZTool')
  305. controlpanel.unregisterConfiglet('EasySlideshowConfiguration')
  306. # controlpanel.unregisterConfiglet('portal_atct')
  307. controlpanel.unregisterConfiglet('PloneFormGen')
  308. controlpanel.unregisterConfiglet('SmartlinkConfig')
  309. controlpanel.unregisterConfiglet('QuickUpload')
  310. controlpanel.unregisterConfiglet('CKEditor')
  311.  
  312. broken_import_steps = [
  313. u'ECLecture-GS-dependencies',
  314. u'ECLecture-QI-dependencies',
  315. u'ECLecture-Update-RoleMappings',
  316. u'ECLecture-postInstall',
  317. u'Products.ImageEditor.install',
  318. u'Products.ImageEditor.uninstall',
  319. u'ckeditor-uninstall',
  320. u'collective.easyslider.install',
  321. u'collective.easyslider.uninstall',
  322. u'collective.prettyphoto.reset-layers',
  323. u'pleonformgen',
  324. u'solgemacontextualcontentmenu',
  325. u'solgemafullcalendarinstall',
  326. u'solgemafullcalendaruninstall',
  327. ]
  328. broken_export_steps = [u'possible_relations']
  329.  
  330. log.info('remove import-steps')
  331. registry = setup.getImportStepRegistry()
  332. for broken_import_step in broken_import_steps:
  333. if broken_import_step in registry.listSteps():
  334. registry.unregisterStep(broken_import_step)
  335.  
  336. log.info('remove export-steps')
  337. registry = setup.getExportStepRegistry()
  338. for broken_export_step in broken_export_steps:
  339. if broken_export_step in registry.listSteps():
  340. registry.unregisterStep(broken_export_step)
  341. setup._p_changed = True
  342.  
  343. # remove instances
  344. to_remove = [
  345. 'FormFolder',
  346. 'PlonePopoll',
  347. 'ECLecture',
  348. 'Person Folder',
  349. 'Person',
  350. ]
  351. for brain in catalog(portal_type=to_remove, Language='all'):
  352. obj = brain.getObject()
  353. log.info('Deleting {} at {}'.format(
  354. to_remove, obj.absolute_url_path()))
  355. api.content.delete(obj, check_linkintegrity=False)
  356.  
  357. # disable diazo theme
  358. # netstal.theme
  359. log.info('remove netstal.theme')
  360. if qi.isProductInstalled('netstal.theme'):
  361. qi.uninstallProducts(['netstal.theme'])
  362. applyTheme(None)
  363. portal_skins.default_skin = 'Sunburst Theme'
  364. if 'Netstal Theme' in portal_skins.getSkinSelections():
  365. portal_skins.manage_skinLayers(['Netstal Theme'], del_skin=True)
  366.  
  367. for brain in catalog(object_provides='Products.Carousel.interfaces.ICarouselFolder', Language='all'): # noqa: E501
  368. obj = brain.getObject()
  369. log.info('Deleting {} at {}'.format(
  370. obj.portal_type, obj.absolute_url_path()))
  371. api.content.delete(obj, check_linkintegrity=False)
  372.  
  373. for brain in catalog(object_provides='eea.facetednavigation.settings.interfaces.IDisableSmartFacets', Language='all'): # noqa: E501
  374. obj = brain.getObject()
  375. log.info('Deleting {} at {}'.format(
  376. obj.portal_type, obj.absolute_url_path()))
  377. api.content.delete(obj, check_linkintegrity=False)
  378.  
  379. log.info('rebuilding catalog')
  380. catalog.clearFindAndRebuild()
  381.  
  382. # reset viewlet-order
  383. log.info('order viewlets')
  384. setup.runImportStepFromProfile(
  385. 'profile-Products.CMFPlone:plone',
  386. step_id='viewlets',
  387. run_dependencies=False)
  388. unregister_broken_persistent_components(portal)
  389. unpatch_indexing_at_blobs()
  390. unpatch_indexing_dx_blobs()
  391.  
  392.  
  393. def _unregisterUtility(portal):
  394. from p4a.subtyper.interfaces import IPortalTypedFolderishDescriptor
  395. sm = portal.getSiteManager()
  396. util = sm.queryUtility(
  397. IPortalTypedFolderishDescriptor, u'collective.easyslideshow.slideshow')
  398. sm.unregisterUtility(
  399. util,
  400. IPortalTypedFolderishDescriptor,
  401. name=u'collective.easyslideshow.slideshow')
  402. if IPortalTypedFolderishDescriptor in sm.utilities._subscribers[0]:
  403. del sm.utilities._subscribers[0][IPortalTypedFolderishDescriptor]
  404. from collective.lineage.upgrades import removeP4A
  405. removeP4A(portal)
  406. remove_vocabularies(None)
  407.  
  408.  
  409. def cleanup_content_for_pam(setup):
  410. """Set languages and add translations so that we can migrate to pam
  411. """
  412. patch_indexing_at_blobs()
  413. patch_indexing_dx_blobs()
  414.  
  415. portal = api.portal.get()
  416. unregister_broken_persistent_components(portal)
  417.  
  418. # set language of containers without lang to a sane value
  419. for brain in api.content.find(
  420. portal_type=['Folder', 'Section'], Language=''):
  421. obj = brain.getObject()
  422. content = obj.contentValues()
  423. lang = set([i.Language() for i in content])
  424. if lang and len(lang) == 1:
  425. lang = lang.pop()
  426. if not lang:
  427. lang = 'de'
  428. else:
  429. lang = 'de'
  430. obj.setLanguage(lang)
  431. log.info('Set language of %s to %s' % (obj.absolute_url_path(), lang))
  432. obj.reindexObject(idxs=['Language'])
  433. transaction.commit()
  434.  
  435. # add missing translations for parents of english content
  436. brains = [i for i in api.content.find(Language='en')]
  437. done = []
  438. for brain in brains:
  439. try:
  440. if brain.getPath() in done:
  441. continue
  442. obj = brain.getObject()
  443. except KeyError:
  444. continue
  445. if IPloneSiteRoot.providedBy(obj) or INavigationRoot.providedBy(obj):
  446. continue
  447. parent = obj.__parent__
  448. if IPloneSiteRoot.providedBy(parent):
  449. continue
  450.  
  451. if parent.Language() == 'en':
  452. continue
  453.  
  454. if parent.hasTranslation('en'):
  455. translation = parent.getTranslation('en')
  456. if translation.absolute_url_path() != parent.absolute_url_path():
  457. log.info('Parent container has a translation. Moving %s to %s' % (obj.absolute_url_path(), translation.absolute_url_path())) # noqa: E501
  458. api.content.move(source=obj, target=translation, safe_id=True)
  459. continue
  460.  
  461. content = parent.contentValues()
  462. if content and 'de' not in [i.Language() for i in content]:
  463. parent.setLanguage('en')
  464. log.info('Switched container with english-only content to english. Please link translation of %s!' % parent.absolute_url_path()) # noqa: E501
  465. obj.reindexObject(idxs=['Language'])
  466. for child_obj in content:
  467. if child_obj.Language() != 'en':
  468. child_obj.setLanguage('en')
  469. child_obj.reindexObject(idxs=['Language'])
  470. continue
  471.  
  472. if not parent.Language():
  473. log.error('Crap! Container without lang: %s' % parent.absolute_url_path()) # noqa: E501
  474. continue
  475.  
  476. if parent.getId().endswith('-en'):
  477. log.error('Crap! Weird things at: %s' % parent.absolute_url_path())
  478. continue
  479.  
  480. try:
  481. translation = parent.addTranslation('en')
  482. except CopyError:
  483. log.info('Could not create english translation of %s' % parent.absolute_url_path()) # noqa: E501
  484. pass
  485. done.append('/'.join(parent.getPhysicalPath()))
  486. log.info('Add translation of %s: %s' % (
  487. parent.absolute_url_path(), translation))
  488. transaction.commit()
  489.  
  490. brains = [i for i in api.content.find(Language='de')]
  491. done = []
  492. for brain in brains:
  493. try:
  494. if brain.getPath() in done:
  495. continue
  496. obj = brain.getObject()
  497. except KeyError:
  498. continue
  499. if IPloneSiteRoot.providedBy(obj) or INavigationRoot.providedBy(obj):
  500. continue
  501. parent = obj.__parent__
  502. if IPloneSiteRoot.providedBy(parent):
  503. continue
  504. if parent.Language() == 'de':
  505. continue
  506.  
  507. if parent.hasTranslation('de'):
  508. log.error('Crap! Weird things at: %s' % parent.absolute_url_path())
  509. continue
  510.  
  511. if not parent.Language():
  512. parent.setLanguage('de')
  513. log.info('Switched container to german: %s!' % parent.absolute_url_path()) # noqa: E501
  514. obj.reindexObject(idxs=['Language'])
  515. continue
  516.  
  517. content = parent.contentValues()
  518. if 'en' not in [i.Language() for i in content]:
  519. parent.setLanguage('de')
  520. log.info('Switched container to german: %s!' % parent.absolute_url_path()) # noqa: E501
  521. obj.reindexObject(idxs=['Language'])
  522. for child_obj in content:
  523. if child_obj.Language() != 'de':
  524. child_obj.setLanguage('de')
  525. child_obj.reindexObject(idxs=['Language'])
  526. continue
  527.  
  528. if parent.getId().endswith('-en'):
  529. log.error('Crap! Weird things at: %s' % parent.absolute_url_path())
  530.  
  531. # set language of all neutral content to 'de'
  532. transaction.commit()
  533. for brain in api.content.find(Language=''):
  534. obj = brain.getObject()
  535. if not obj.Language():
  536. if not obj.isCanonical() and 'de' in obj.getTranslations():
  537. lang = 'en'
  538. else:
  539. lang = 'de'
  540. obj.setLanguage(lang)
  541. obj.reindexObject(idxs=['Language'])
  542. log.info('Switched %s to %s' % (obj.absolute_url_path(), lang))
  543.  
  544. # log non-default content with different languages than their parents
  545. find_content_with_wrong_language(portal)
  546. unpatch_indexing_at_blobs()
  547. unpatch_indexing_dx_blobs()
  548.  
  549.  
  550. def install_pam(setup):
  551. qi = api.portal.get_tool('portal_quickinstaller')
  552. portal = api.portal.get()
  553.  
  554. if not qi.isProductInstalled('plone.app.multilingual'):
  555. qi.installProduct('plone.app.multilingual')
  556. qi.installProduct('archetypes.multilingual')
  557. from plone.app.multilingual.browser.setup import SetupMultilingualSite
  558. ml_setup_tool = SetupMultilingualSite()
  559. ml_setup_tool.setupSite(portal)
  560. setup_netstal_language_switcher(portal)
  561.  
  562.  
  563. def setup_netstal_language_switcher(portal):
  564. """Setup custom language switcher
  565. """
  566. doneSomething = False
  567. tt = api.portal.get_tool('portal_types')
  568. site = tt['Plone Site']
  569. if 'netstal-language-switcher' not in site.view_methods:
  570. methods = site.view_methods
  571. site.view_methods = methods + ('netstal-language-switcher', )
  572. site.default_view = 'netstal-language-switcher'
  573. portal.setLayout('')
  574. portal.reindexObject()
  575. doneSomething = True
  576. log.info(u'Netstal language switcher set up.')
  577. return doneSomething
  578.  
  579.  
  580. def migrate_to_pam(setup):
  581. patch_indexing_at_blobs()
  582. patch_indexing_dx_blobs()
  583.  
  584. qi = api.portal.get_tool('portal_quickinstaller')
  585. portal_properties = api.portal.get_tool('portal_properties')
  586. portal = api.portal.get()
  587.  
  588. # again set the language of containers without lang to a sane value
  589. # This information gets lost somehow
  590. for brain in api.content.find(
  591. portal_type=['Folder', 'Section'], Language=''):
  592. obj = brain.getObject()
  593. content = obj.contentValues()
  594. lang = set([i.Language() for i in content])
  595. if lang and len(lang) == 1:
  596. lang = lang.pop()
  597. if not lang:
  598. lang = 'de'
  599. else:
  600. lang = 'de'
  601. obj.setLanguage(lang)
  602. log.info('Set language of %s to %s' % (obj.absolute_url_path(), lang))
  603. obj.reindexObject(idxs=['Language'])
  604.  
  605. # run lp migration-steps
  606. from zope.globalrequest import getRequest
  607. request = getRequest()
  608. lp_relocate = api.content.get_view('relocate-content', portal, request)
  609. lp_relocate.blacklist = []
  610. lp_relocate.step1andstep2()
  611. transaction.commit()
  612. lp_relocate.step3()
  613. transaction.commit()
  614. transfer_lp_catalog = api.content.get_view(
  615. 'transfer-lp-catalog', portal, request)
  616. transfer_lp_catalog()
  617. transaction.commit()
  618.  
  619. # remove LinguaPlone
  620. if qi.isProductInstalled('LinguaPlone'):
  621. qi.uninstallProducts(['LinguaPlone'])
  622. try:
  623. portal_properties.manage_delObjects(['linguaplone_properties'])
  624. except BadRequest:
  625. pass
  626. # run our LP-uninstall-profile
  627. setup.runAllImportStepsFromProfile(
  628. 'profile-netstal.policy:to_1005', purge_old=False)
  629. unpatch_indexing_at_blobs()
  630. unpatch_indexing_dx_blobs()
  631.  
  632.  
  633. def remove_vocabularies(setup):
  634. from plone.i18n.locales.interfaces import IContentLanguageAvailability
  635. from plone.i18n.locales.interfaces import IMetadataLanguageAvailability
  636. from p4a.subtyper.interfaces import IPortalTypedFolderishDescriptor
  637. portal = api.portal.get()
  638. sm = portal.getSiteManager()
  639.  
  640. if IContentLanguageAvailability in sm.utilities._subscribers[0]:
  641. del sm.utilities._subscribers[0][IContentLanguageAvailability]
  642. log.info(u'Unregistering subscriber for IContentLanguageAvailability')
  643. if IMetadataLanguageAvailability in sm.utilities._subscribers[0]:
  644. del sm.utilities._subscribers[0][IMetadataLanguageAvailability]
  645. log.info(u'Unregistering subscriber for IMetadataLanguageAvailability')
  646.  
  647. if IMetadataLanguageAvailability in sm.utilities._adapters[0]:
  648. del sm.utilities._adapters[0][IMetadataLanguageAvailability]
  649. log.info(u'Unregistering adapter for IMetadataLanguageAvailability')
  650. if IContentLanguageAvailability in sm.utilities._adapters[0]:
  651. del sm.utilities._adapters[0][IContentLanguageAvailability]
  652. log.info(u'Unregistering adapter for IContentLanguageAvailability')
  653.  
  654. if IPortalTypedFolderishDescriptor in sm.utilities._adapters[0]:
  655. del sm.utilities._adapters[0][IPortalTypedFolderishDescriptor]
  656. log.info(u'Unregistering adapter for IPortalTypedFolderishDescriptor')
  657. sm.utilities._p_changed = True
  658. transaction.commit()
  659.  
  660.  
  661. def unregister_broken_persistent_components(portal):
  662. sm = portal.getSiteManager()
  663.  
  664. for item in sm._utility_registrations.items():
  665. if hasattr(item[1][0], '__Broken_state__'):
  666. # unregisterUtility(component, provided, name)
  667. # See: five.localsitemanager.registry.PersistentComponents.unregisterUtility # noqa: E501
  668. log.info(u"Unregistering component {0}".format(item))
  669. sm.unregisterUtility(item[1][0], item[0][0], item[0][1])
  670.  
  671.  
  672. def find_content_with_wrong_language(content):
  673. """In part stolen from
  674. plone.app.multilingual.browser.migrator.moveContentToProperRLF.findContent
  675. """
  676. # only handle portal content
  677. from plone.dexterity.interfaces import IDexterityContent
  678. from Products.Archetypes.interfaces import IBaseObject
  679. from Acquisition import aq_base
  680. from Acquisition import aq_parent
  681. try:
  682. from Products.LinguaPlone.interfaces import ITranslatable
  683. except ImportError:
  684. from plone.app.multilingual.interfaces import ITranslatable
  685.  
  686. if not IDexterityContent.providedBy(content)\
  687. and not IBaseObject.providedBy(content)\
  688. and not IPloneSiteRoot.providedBy(content):
  689. return
  690. if hasattr(aq_base(content), 'objectIds'):
  691. for id in content.objectIds():
  692. find_content_with_wrong_language(getattr(content, id))
  693. if ITranslatable.providedBy(content):
  694. # The content parent has the same language?
  695. if not IPloneSiteRoot.providedBy(aq_parent(content)) \
  696. and aq_parent(content).Language() != content.Language():
  697. log.info('Obj %s (%s) not same language as parent (%s)' % (
  698. content.absolute_url_path(), content.Language(), aq_parent(content).Language())) # noqa: E501
  699.  
  700.  
  701. def cleanup_after_pam_migration(setup):
  702. """Nothing yet"""
  703. return
  704.  
  705.  
  706. def prepare_p5_upgrade(setup):
  707. broken_import_steps = [
  708. u'collective.z3cform.datetimewidget',
  709. u'languagetool',
  710. u'smartLinkToATLink',
  711. ]
  712. registry = setup.getImportStepRegistry()
  713. for broken_import_step in broken_import_steps:
  714. if broken_import_step in registry.listSteps():
  715. registry.unregisterStep(broken_import_step)
  716.  
  717. # reinstall plone.app.iterate
  718. qi = api.portal.get_tool('portal_quickinstaller')
  719. qi.reinstallProducts(['plone.app.iterate'])
  720. setup.runAllImportStepsFromProfile(
  721. 'profile-plone.app.z3cform:default', purge_old=False)
  722.  
  723.  
  724. def after_p5_upgrade(setup):
  725. qi = api.portal.get_tool('portal_quickinstaller')
  726.  
  727. # reinstall some addons
  728. qi.reinstallProducts(['CMFPlacefulWorkflow'])
  729. qi.reinstallProducts(['webcouturier.dropdownmenu'])
  730. qi.reinstallProducts(['plone.app.ldap'])
  731. qi.reinstallProducts(['Reflecto'])
  732.  
  733. # install pac
  734. qi.installProduct('plone.app.contenttypes')
  735.  
  736. # reinstall pam
  737. qi.reinstallProducts(['plone.app.multilingual'])
  738. qi.reinstallProducts(['archetypes.multilingual'])
  739.  
  740. # install theme
  741. qi.installProducts(['netstal.theme'])
  742.  
  743. # from plone.app.multilingual import setuphandlers
  744. # setuphandlers.enable_translatable_behavior(api.portal.get())
  745.  
  746.  
  747. def migrate_folders(setup):
  748. patch_indexing_at_blobs()
  749. patch_indexing_dx_blobs()
  750.  
  751. portal = api.portal.get()
  752. request = getRequest()
  753.  
  754. pac_migration = api.content.get_view('migrate_from_atct', portal, request)
  755. content_types = ['Folder']
  756.  
  757. pac_migration(
  758. migrate=True,
  759. content_types=content_types,
  760. migrate_schemaextended_content=True,
  761. reindex_catalog=True)
  762.  
  763. unpatch_indexing_at_blobs()
  764. unpatch_indexing_dx_blobs()
  765.  
  766.  
  767. def migrate_to_pac(setup):
  768. patch_indexing_at_blobs()
  769. patch_indexing_dx_blobs()
  770.  
  771. portal = api.portal.get()
  772. request = getRequest()
  773.  
  774. pac_migration = api.content.get_view('migrate_from_atct', portal, request)
  775. content_types = ['News Item', 'Document', 'Image', 'Collection', 'BlobImage', 'Event'] # noqa: E501
  776.  
  777. pac_migration(
  778. migrate=True,
  779. content_types=content_types,
  780. migrate_schemaextended_content=True,
  781. reindex_catalog=True)
  782.  
  783. unpatch_indexing_at_blobs()
  784. unpatch_indexing_dx_blobs()
  785.  
  786.  
  787. def migrate_topics(setup):
  788. patch_indexing_at_blobs()
  789. patch_indexing_dx_blobs()
  790.  
  791. portal = api.portal.get()
  792. request = getRequest()
  793. pac_migration = api.content.get_view('migrate_from_atct', portal, request)
  794. content_types = ['Topic']
  795. pac_migration(
  796. migrate=True,
  797. content_types=content_types,
  798. migrate_schemaextended_content=True,
  799. reindex_catalog=True)
  800.  
  801. unpatch_indexing_at_blobs()
  802. unpatch_indexing_dx_blobs()
  803.  
  804.  
  805. def migrate_files(setup):
  806. patch_indexing_at_blobs()
  807. patch_indexing_dx_blobs()
  808.  
  809. portal = api.portal.get()
  810. request = getRequest()
  811.  
  812. pac_migration = api.content.get_view('migrate_from_atct', portal, request)
  813. content_types = ['BlobFile', 'File']
  814.  
  815. pac_migration(
  816. migrate=True,
  817. content_types=content_types,
  818. migrate_schemaextended_content=True,
  819. reindex_catalog=True)
  820.  
  821. unpatch_indexing_at_blobs()
  822. unpatch_indexing_dx_blobs()
  823.  
  824.  
  825. def migrate_links(setup):
  826. patch_indexing_at_blobs()
  827. patch_indexing_dx_blobs()
  828.  
  829. portal = api.portal.get()
  830. request = getRequest()
  831. pac_migration = api.content.get_view('migrate_from_atct', portal, request)
  832. content_types = ['Link']
  833. pac_migration(
  834. migrate=True,
  835. content_types=content_types,
  836. migrate_schemaextended_content=True,
  837. reindex_catalog=False)
  838.  
  839. unpatch_indexing_at_blobs()
  840. unpatch_indexing_dx_blobs()
  841.  
  842.  
  843. def cleanup_after_pac_migration(setup):
  844. patch_indexing_at_blobs()
  845. patch_indexing_dx_blobs()
  846.  
  847. log.info('Rebuilding catalog...')
  848. portal_catalog = api.portal.get_tool('portal_catalog')
  849. portal_catalog.clearFindAndRebuild()
  850. log.info('Done!')
  851. log.info('Set startpageview')
  852. portal = api.portal.get()
  853. portal['de'].setLayout('startpageview')
  854. portal['en'].setLayout('startpageview')
  855. for brain in api.content.find(portal_type=['Folder', 'Collection']):
  856. obj = brain.getObject()
  857. if obj.getLayout() == 'prettyPhoto_album_view':
  858. obj.setLayout('album_view')
  859. log.info('Removed prettyPhoto from %s' % obj.absolute_url_path())
  860. portal_transforms = api.portal.get_tool('portal_transforms')
  861. portal_transforms.reloadTransforms(['safe_html'])
  862. log.info('Reloaded safe_html transform!')
  863. # reinstall some steps from default profile
  864. setup.runAllImportStepsFromProfile(
  865. 'profile-netstal.policy:default', purge_old=False)
  866.  
  867. unpatch_indexing_at_blobs()
  868. unpatch_indexing_dx_blobs()
  869.  
  870.  
  871. def rebuild_catalog_without_patch(setup):
  872. log.info('Rebuilding catalog...')
  873. portal_catalog = api.portal.get_tool('portal_catalog')
  874. portal_catalog.clearFindAndRebuild()
  875. log.info('Done!')
  876.  
  877.  
  878. # Old scale name to new scale name
  879. IMAGE_SCALE_MAP = {
  880. 'icon': 'icon',
  881. 'large': 'large',
  882. 'listing': 'listing',
  883. 'mini': 'mini',
  884. 'preview': 'preview',
  885. 'thumb': 'thumb',
  886. 'tile': 'tile',
  887. # BBB
  888. 'article': 'preview',
  889. 'artikel': 'preview',
  890. 'carousel': 'preview',
  891. 'company_index': 'thumb',
  892. 'content': 'preview',
  893. 'leadimage': 'tile',
  894. 'portlet-fullpage': 'large',
  895. 'portlet-halfpage': 'large',
  896. 'portlet-links': 'thumb',
  897. 'portlet': 'thumb',
  898. 'staff_crop': 'thumb',
  899. 'staff_index': 'thumb',
  900. }
  901.  
  902.  
  903. def image_scale_fixer(text):
  904. if text:
  905. for old, new in IMAGE_SCALE_MAP.items():
  906. # replace plone.app.imaging old scale names with new ones
  907. text = text.replace(
  908. '@@images/image/{0}'.format(old),
  909. '@@images/image/{0}'.format(new)
  910. )
  911. # replace AT traversing scales
  912. text = text.replace(
  913. '/image_{0}'.format(old),
  914. '/@@images/image/{0}'.format(new)
  915. )
  916. return text
  917.  
  918.  
  919. def fix_at_image_scales(setup):
  920. catalog = api.portal.get_tool('portal_catalog')
  921. query = {}
  922. query['object_provides'] = 'plone.app.contenttypes.behaviors.richtext.IRichText' # noqa
  923. results = catalog(**query)
  924. log.info('There are {0} in total, stating migration...'.format(
  925. len(results)))
  926. for result in results:
  927. try:
  928. obj = result.getObject()
  929. except:
  930. log.warning(
  931. 'Not possible to fetch object from catalog result for '
  932. 'item: {0}.'.format(result.getPath()))
  933. continue
  934.  
  935. text = getattr(obj, 'text', None)
  936. if text:
  937. clean_text = image_scale_fixer(text.raw)
  938. if clean_text != text.raw:
  939. obj.text = RichTextValue(
  940. raw=clean_text,
  941. mimeType=text.mimeType,
  942. outputMimeType=text.outputMimeType,
  943. encoding=text.encoding
  944. )
  945. obj.reindexObject(idxs=('SearchableText', ))
  946. log.info('Text cleanup for {0}'.format(
  947. '/'.join(obj.getPhysicalPath())
  948. ))
  949.  
  950.  
  951. def pass_fn(*args, **kwargs):
  952. """Empty function used for patching."""
  953. pass
  954.  
  955.  
  956. def upgrade_contenttype_section(setup):
  957. displayed_types = api.portal.get_registry_record('plone.displayed_types')
  958. displayed_types += ('Section', )
  959. api.portal.set_registry_record('plone.displayed_types', displayed_types)
  960.  
  961.  
  962. def patch_indexing_at_blobs():
  963. from plone.app.blob.content import ATBlob
  964. from Products.contentmigration.utils import patch
  965. patch(ATBlob, 'getIndexValue', pass_fn)
  966.  
  967.  
  968. def unpatch_indexing_at_blobs():
  969. from Products.contentmigration.utils import undoPatch
  970. from plone.app.blob.content import ATBlob
  971. undoPatch(ATBlob, 'getIndexValue')
  972.  
  973.  
  974. def patch_indexing_dx_blobs():
  975. from Products.contentmigration.utils import patch
  976. from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex
  977. # from plone.app.blob.content import ATBlob
  978. patch(ZCTextIndex, 'index_object', patched_index_object)
  979.  
  980.  
  981. def unpatch_indexing_dx_blobs():
  982. from Products.contentmigration.utils import undoPatch
  983. from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex
  984. undoPatch(ZCTextIndex, 'index_object')
  985.  
  986.  
  987. def patched_index_object(self, documentId, obj, threshold=None):
  988. """Wrapper for index_doc() handling indexing of multiple attributes.
  989.  
  990. Enter the document with the specified documentId in the index
  991. under the terms extracted from the indexed text attributes,
  992. each of which should yield either a string or a list of
  993. strings (Unicode or otherwise) to be passed to index_doc().
  994. """
  995.  
  996. # patch: ignore Files
  997. if getattr(obj, 'portal_type', None) == 'File':
  998. return 0
  999. # TODO we currently ignore subtransaction threshold
  1000.  
  1001. # needed for backward compatibility
  1002. fields = getattr(self, '_indexed_attrs', [self._fieldname])
  1003.  
  1004. all_texts = []
  1005. for attr in fields:
  1006. try:
  1007. text = getattr(obj, attr, None)
  1008. except TransformError as e:
  1009. log.warn('TransformError accessing {0} of {1}: {2}'.format(attr, obj.absolute_url_path(), e)) # noqa: E501
  1010. continue
  1011. if text is None:
  1012. continue
  1013. if safe_callable(text):
  1014. text = text()
  1015. if text is not None:
  1016. if isinstance(text, (list, tuple, set)):
  1017. all_texts.extend(text)
  1018. else:
  1019. all_texts.append(text)
  1020.  
  1021. # Check that we're sending only strings
  1022. all_texts = [t for t in all_texts if isinstance(t, basestring)]
  1023. if all_texts:
  1024. return self.index.index_doc(documentId, all_texts)
  1025. return 0
  1026.  
  1027.  
  1028. def fix_collections(setup):
  1029. setup.runAllImportStepsFromProfile(
  1030. 'profile-netstal.policy:to_1051', purge_old=False)
Add Comment
Please, Sign In to add comment