@@ -408,49 +408,142 @@ class SerializeTopicToJson(SerializeToJson):
408408 """This uses the topic migration from p.a.contenttypes to turn Criteria into a Querystring."""
409409
410410 def __call__ (self , version = None , include_items = False ):
411- topic_metadata = super (SerializeTopicToJson , self ).__call__ (version = version )
411+ # 1. Get the default serialisation for AT content
412+ item = super (SerializeTopicToJson , self ).__call__ (version = version )
412413
413- # migrate criteria
414- formquery = []
414+ # 2. Get querystring-registry
415+ query = []
415416 reg = getUtility (IRegistry )
416417 reader = IQuerystringRegistryReader (reg )
417- self .registry = reader .parseRegistry ()
418-
418+ registry = reader .parseRegistry ()
419+
420+ # Inject new selection-operators that were added in Plone 5
421+ selection = registry ["plone" ]["app" ]["querystring" ]["operation" ]["selection" ]
422+ new_operators = ["all" , "any" , "none" ]
423+ for operator in new_operators :
424+ if operator not in selection :
425+ # just a dummy method to pass validation
426+ selection [operator ] = {"operation" : "collective.exportimport" }
427+
428+ # Inject any operator for some fields
429+ any_operator = "plone.app.querystring.operation.selection.any"
430+ fields_with_any_operator = ['Creator' , 'Subject' , 'portal_type' , 'review_state' ]
431+ for field in fields_with_any_operator :
432+ operations = registry ["plone" ]["app" ]["querystring" ]["field" ][field ]["operations" ]
433+ if any_operator not in operations :
434+ registry ["plone" ]["app" ]["querystring" ]["field" ][field ]["operations" ].append (any_operator )
435+
436+ # Inject all operator for Subject
437+ all_operator = "plone.app.querystring.operation.selection.all"
438+ fields_with_any_operator = ["Subject" ]
439+ for field in fields_with_any_operator :
440+ operations = registry ["plone" ]["app" ]["querystring" ]["field" ][field ]["operations" ]
441+ if all_operator not in operations :
442+ registry ["plone" ]["app" ]["querystring" ]["field" ][field ]["operations" ].append (all_operator )
443+
444+ # 3. Migrate criteria using the converters from p.a.contenttypes
419445 criteria = self .context .listCriteria ()
420446 for criterion in criteria :
421447 type_ = criterion .__class__ .__name__
422448 if type_ == "ATSortCriterion" :
423- # Sort order and direction are now stored in the Collection.
424- self ._collection_sort_reversed = criterion .getReversed ()
425- self ._collection_sort_on = criterion .Field ()
426- logger .debug (
427- "Sort on %r, reverse: %s." ,
428- self ._collection_sort_on ,
429- self ._collection_sort_reversed ,
430- )
449+ # Migrate sorting
450+ item ["sort_reversed" ] = criterion .getReversed ()
451+ item ["sort_on" ] = criterion .Field ()
431452 continue
432453
433454 converter = CONVERTERS .get (type_ )
434455 if converter is None :
435- msg = "Unsupported criterion {0}" .format (type_ )
456+ msg = u "Unsupported criterion {0}" .format (type_ )
436457 logger .error (msg )
437458 raise ValueError (msg )
459+ before = len (query )
438460 try :
439- converter (formquery , criterion , self .registry )
440- except Exception as e :
441- logger .info (e )
442-
443- topic_metadata ["query" ] = json_compatible (formquery )
444-
445- # migrate batch size
461+ converter (query , criterion , registry )
462+ except Exception :
463+ logger .info (u"Error converting criterion %s" , criterion .__dict__ , exc_info = True )
464+ pass
465+
466+ # Try to manually convert when no criterion was added
467+ # this happens with invalid criteria (e.g. path without a path)
468+ if len (query ) == before :
469+ fixed = self .fix_criteria (criterion )
470+ if fixed :
471+ query .append (fixed )
472+ else :
473+ logger .info (u"Check maybe broken collection %s" , self .context .absolute_url ())
474+
475+ # 4. So some manual fixes in the migrated query
476+ indexes_to_fix = [
477+ u"portal_type" ,
478+ u"review_state" ,
479+ u"Creator" ,
480+ u"Subject" ,
481+ ]
482+ operator_mapping = {
483+ # old -> new
484+ u"plone.app.querystring.operation.selection.is" :
485+ u"plone.app.querystring.operation.selection.any" ,
486+ u"plone.app.querystring.operation.string.is" :
487+ u"plone.app.querystring.operation.selection.any" ,
488+ }
489+ fixed_query = []
490+ for crit in query :
491+ if crit ["o" ].endswith ("relativePath" ) and crit ["v" ] == ".." :
492+ # relativePath no longer accepts ..
493+ crit ["v" ] = "..::1"
494+ if crit ["i" ] in indexes_to_fix :
495+ for old_operator , new_operator in operator_mapping .items ():
496+ if crit ["o" ] == old_operator :
497+ crit ["o" ] = new_operator
498+ if crit ["o" ] == u"plone.app.querystring.operation.string.currentUser" :
499+ crit ["v" ] = ""
500+ fixed_query .append (crit )
501+ query = fixed_query
502+
503+ # 5. Migrate batch size
446504 if self .context .itemCount :
447- topic_metadata ["b_size" ] = self .context .itemCount
505+ item ["item_count" ] = self .context .itemCount
506+
507+ # 6. Migrate customView
508+ if item .pop ("customView" , False ):
509+ item ["layout" ] = "tabular_view"
510+
511+ item ["query" ] = json_compatible (query )
512+ return item
513+
514+ def fix_criteria (self , criterion ):
515+ """Try to fix some invalid criteria"""
516+ FIXES = {
517+ # real operators
518+ "or" : "plone.app.querystring.operation.selection.any" ,
519+ # fake operators
520+ "contains" : "plone.app.querystring.operation.string.contains" ,
521+ "any" : "plone.app.querystring.operation.selection.any" ,
522+ }
448523
449- if hasattr (self , "_collection_sort_on" ):
450- topic_metadata ["sort_on" ] = self ._collection_sort_on
451- topic_metadata ["sort_reversed" ] = self ._collection_sort_reversed
524+ type_ = criterion .__class__ .__name__
525+ field = criterion .field
526+ value = getattr (criterion , "value" , None )
527+ operator = getattr (criterion , "operator" , None )
528+
529+ if type_ == "ATSimpleStringCriterion" :
530+ operator = "contains"
531+ if type_ == "ATSelectionCriterion" :
532+ operator = "any"
533+ if type_ == "ATListCriterion" :
534+ operator = "any"
535+ if type_ in ["ATPathCriterion" , "ATDateCriteria" ] and not value :
536+ return
537+ if field == "commentators" :
538+ # no index
539+ return
452540
453- return topic_metadata
541+ query = {
542+ "i" : field ,
543+ "o" : FIXES .get (operator , operator ),
544+ "v" : value ,
545+ }
546+ return query
454547
455548
456549def get_dx_blob_path (obj ):
0 commit comments