DEFAULT_VOCABULARY_CONTAINER = 'SimpleVocabulary' DEFAULT_VOCABULARY_ITEM = 'SimpleVocabularyTerm' VDEX_EXPORT_NEWL = '\n' VDEX_EXPORT_INDENT = '\t' # encoding of files in flat-file csv import IMPORT_ENCODING = 'latin-1' SORT_METHOD_FOLDER_ORDER = "getObjPositionInParent" SORT_METHOD_LEXICO_VALUES = "lexicographic_values" SORT_METHOD_LEXICO_KEYS = "lexicographic_keys" VOCABULARY_SORT_ORDERS = DisplayList(( ('getObjPositionInParent', _('Vocabulary Folder Order'), 'sort_method_folder_order'), ('lexicographic_values', _('Lexicographic sort by values'), 'sort_method_lexi_value'), ('lexicographic_keys', _('Lexicographic sort by keys'), 'sort_method_lexi_keys'), )) # LinguaPlone addon? import pkg_resources try: pkg_resources.get_distribution("Products.LinguaPlone") except DistributionNotFound: HAS_LINGUA_PLONE = False else: HAS_LINGUA_PLONE = True
from Products.CMFCore.utils import getToolByName from Products.CMFPlone.utils import base_hasattr from Products.Archetypes.utils import OrderedDict try: from Products.Archetypes.lib.vocabulary import DisplayList except ImportError: from Products.Archetypes.utils import DisplayList from Products.ATVocabularyManager.types.simple import SimpleVocabulary from Products.ATVocabularyManager.config import PROJECTNAME from Products.ATVocabularyManager import messageFactory as _ schema = SimpleVocabulary.schema + Schema(( BooleanField('ShowLeavesOnly', widget = BooleanWidget( label = _("label_show_leaves_only", default=u"Show leaves only"), description = _("help_show_leaves_only", default=u"Check to show only leaves in this vocabulary."), ), ), )) class TreeVocabulary(SimpleVocabulary): security = ClassSecurityInfo() schema = schema meta_type = 'TreeVocabulary' def getDisplayList(self, instance, display_parents='tree'):
class SimpleVocabularyTerm(BaseContent): security = ClassSecurityInfo() portal_type = meta_type = 'SimpleVocabularyTerm' archetype_name = 'Simple Vocabulary Term' _at_rename_after_creation = True implements(ISimpleVocabularyTerm) schema = BaseSchema + Schema(( StringField( 'id', required=0, ## Still actually required, but ## the widget will supply the missing value ## on non-submits mode="rw", accessor="getId", mutator="setId", default='', size=50, widget=StringWidget( label=_("label_key", default="Key"), description=_( "help_vocab_name", default= "Should not contain spaces, underscores or mixed case."), ), ), StringField( 'title', required=1, searchable=0, default='', accessor='Title', widget=StringWidget(label=_("label_value", default="Value"), ), ))) aliases = { '(Default)': 'base_view', 'view': 'base_view', 'edit': 'base_edit', } # Methods # methods from Interface IVocabularTerm def getTermKey(self): """ """ if not HAS_LINGUA_PLONE or self.isCanonical(): return self.getId() else: return self.getCanonical().getId() def getTermValue(self, lang=None): """ """ if not lang is None: # if we ask for a specific language, we try to # provide it trans = self.getTranslation(lang) # if not found, we return the title of the current term return trans and trans.Title() or self.Title() return self.Title() def getTermKeyPath(self): # terms of flat vocabularies can savely return their key return [ self.getTermKey(), ] def getVocabularyKey(self): ''' returns the key of the field ''' deprecated( "please use the IVocabularyTerm compatible method 'getTermKey'") return self.getTermKey() def getVocabularyValue(self, **kwargs): ''' returns the value of the field. The value is a processed value ''' deprecated( "please use the IVocabularyTerm compatible method 'getTermValue'") return self.getTermValue() def processForm(self, data=1, metadata=0, REQUEST=None, values=None): request = REQUEST or self.REQUEST values = request.form if 'title' in values: orig_title = self.Title() BaseContent.processForm(self, data, metadata, REQUEST, values) if 'title' in values: new_title = values['title'] vocab = find_toplevel_vocab(self) event.notify(TermRenamedEvent(orig_title, new_title, self, vocab)) def update(self, *args, **kwargs): if 'title' in kwargs: orig_title = self.Title() BaseContent.update(self, *args, **kwargs) if 'title' in kwargs: new_title = kwargs['title'] vocab = find_toplevel_vocab(self) event.notify(TermRenamedEvent(orig_title, new_title, self, vocab)) edit = update # uncomment lines below when you need factory_type_information = { 'allowed_content_types': (), 'allow_discussion': 0, 'immediate_view': 'simplevocabulary_view', 'global_allow': 0, 'filter_content_types': 1, } actions = ()
from Products.CMFCore.utils import getToolByName from Products.CMFPlone.utils import base_hasattr from Products.Archetypes.utils import OrderedDict from Products.Archetypes.utils import DisplayList from Products.ATVocabularyManager.interfaces import ITreeVocabulary from Products.ATVocabularyManager.types.simple import SimpleVocabulary from Products.ATVocabularyManager.config import PROJECTNAME from Products.ATVocabularyManager import messageFactory as _ from zope.interface import implements schema = SimpleVocabulary.schema + Schema(( BooleanField('ShowLeavesOnly', widget = BooleanWidget( label = _("label_show_leaves_only", default=u"Show leaves only"), description = _("help_show_leaves_only", default=u"Check to show only leaves in this vocabulary."), ), ), )) class TreeVocabulary(SimpleVocabulary): """ A tree vocabulary """ security = ClassSecurityInfo() schema = schema meta_type = 'TreeVocabulary' implements(ITreeVocabulary)
class SimpleVocabulary(OrderedBaseFolder): implements(ISimpleVocabulary) security = ClassSecurityInfo() meta_type = 'SimpleVocabulary' schema = BaseFolderSchema.copy() + Schema(( StringField('id', required = 1, ## Still actually required, but ## the widget will supply the missing value ## on non-submits mode = "rw", accessor = "getId", mutator = "setId", default = '', widget = StringWidget( label=_("label_vocab_name", default="Vocabulary Name"), description=_("help_vocab_name", default="Should not contain spaces, underscores or mixed case."), size=50, ), ), TextField('description', default = '', required = 0, searchable = 0, accessor = "Description", storage = MetadataStorage(), widget = TextAreaWidget(label=PMF("label_description", default="Description"), description=PMF("help_description", default="Enter a brief description"), rows = 5, ), ), StringField("sortMethod", default = SORT_METHOD_LEXICO_VALUES, required = 0, # smooth upgrades from 1.0.0-beta2 searchable = 0, widget = SelectionWidget( label = _("label_sort_method", default="Sort method"), description = _("help_sort_method", default="Sort method used for displaying vocabulary terms"), ), vocabulary = VOCABULARY_SORT_ORDERS, ), )) def isLinguaPloneInstalled(self): """ checks if LinguaPlone is installed """ return ILinguaPloneProductLayer in registered_layers() \ or self.portal_quickinstaller.isProductInstalled('LinguaPlone') # Methods from Interface IVocabulary def getDisplayList(self, instance): """Returns a object of class DisplayList as defined in Products.Archetypes.utils. The instance of the content class is given as parameter. The list is sorted accordingly to the sortMethod chosen. """ dl = DisplayList() vdict = self.getVocabularyDict(instance) for key in self.getSortedKeys(instance): dl.add(key, vdict[key]) return dl def getVocabularyLines(self, instance=None): """Returns a List of Key-Value tuples. The list is sorted accordingly to the sortMethod chosen. """ termlist = [] vdict = self.getVocabularyDict(instance) for key in self.getSortedKeys(): termlist.append((key, vdict[key])) return termlist def getVocabularyDict(self, instance=None): """Returns a vocabulary dictionary as defined in the interface """ if self.isLinguaPloneInstalled(): # if lp is installed # obtain language and return translated dict try: # we use the language of instance for this dictionary lang = instance.getLanguage() except AttributeError: # we retrieve the current language langtool = getToolByName(self, 'portal_languages') lang = langtool.getPreferredLanguage() return self._getTranslatedVocabularyDict(lang) else: # just return all terms vdict = OrderedDict() for obj in self.contentValues(): vdict[obj.getTermKey()] = obj.getTermValue() return vdict def _getTranslatedVocabularyDict(self, lang): vdict = OrderedDict() for obj in self.contentValues(): vdict[obj.getTermKey()] = obj.getTermValue(lang) return vdict def isFlat(self): """ returns true for a flat vocabulary """ return 1 def showLeafsOnly(self): """ indicates if only leafs should be shown """ return 1 # some supporting methods def getSortedKeys(self, instance=None): """ returns a list of keys sorted accordingly to the selected sort method (may be unsorted if method = no sort) """ sortMethod = self.getSortMethod() context = self if self.isLinguaPloneInstalled(): from Products.LinguaPlone.interfaces import ITranslatable langtool = getToolByName(self, 'portal_languages') if instance and ITranslatable.providedBy(instance): lang = instance.getLanguage() or langtool.getPreferredLanguage() else: lang = langtool.getPreferredLanguage() context = context.getTranslation(lang) or self keys = [term.getVocabularyKey() for term in context.contentValues()] if not hasattr(self, 'sortMethod'): # smooth upgrade from previous releases return keys if sortMethod == SORT_METHOD_LEXICO_KEYS: keys.sort() return keys if sortMethod == SORT_METHOD_LEXICO_VALUES: # returns keys sorted by lexicogarphic order of VALUES terms = context.contentValues() terms.sort(lambda x, y: cmp(x.getTermValue(), y.getTermValue())) return [term.getVocabularyKey() for term in terms] if sortMethod == SORT_METHOD_FOLDER_ORDER: try: contentListing = getMultiAdapter( (context, context.REQUEST), name='folderListing')() except ComponentLookupError: # still Plone 3 compatible contentListing = context.getFolderContents() return [term.getObject().getTermKey() for term in contentListing] # fallback return keys security.declareProtected(AddPortalContent, 'addTerm') def addTerm(self, key, value, language=None, termtype=DEFAULT_VOCABULARY_ITEM, silentignore=False, **kwargs): """ add a new key/value pair to the container termtype is the portal_type of the term language is for future use with LinguaPlone with silentignore duplicate keys are silently skipped returns True if addition worked """ if key in self.getVocabularyDict(): if silentignore: return False raise KeyError('key %s already exist in vocabulary %s ' % ( key, self.title_or_id())) allowed = [fti.content_meta_type for fti in self.allowedContentTypes()] if not termtype in allowed: if termtype == DEFAULT_VOCABULARY_ITEM and len(allowed) == 1: termtype = allowed[0].meta_type else: raise ValueError('type %s is not allowed as vocabularyterm in this context' % termtype) self.invokeFactory(termtype, key) self[key].setTitle(value) return True security.declareProtected(AddPortalContent, 'importCSV') def importCSV(self, csvdata, termtype=DEFAULT_VOCABULARY_ITEM, titlerow=False, silentignore=False): """ imports given csv data as the given vocabularytype csv is a string or a file-like object in the style: "Data 1.1", "Data 1.2" "Data 2.1", "Data 2.2" "Data 3.1", "Data 3.2" vocabularytype is the terms portal-type, like SimpleVocabularyTerm which is also the default. It uses column 1 as key=id and column 2 as value=title. If titlerow is True the first line will be skipped. """ qi = getToolByName(self, 'portal_quickinstaller') lp = qi.isProductInstalled('LinguaPlone') if type(csvdata) == type(''): csvdata = StringIO(csvdata) csvreader = csv.reader(csvdata) languages = [] for row in csvreader: if titlerow: # If LinguaPlone is installed, it's assumed the title row is # used to define language columns if lp: for n in range(1, len(row)): languages.append(row[n]) titlerow = False else: value = str(row[1], IMPORT_ENCODING) key = row[0] or make_uuid(value) self.addTerm(key, value, termtype=termtype, silentignore=silentignore) if len(languages) > 0: self[key].setLanguage(languages[0]) if len(row) > 2: for col in range(2, len(row)): self[key].addTranslation(languages[col-1], title=row[col])
class TreeVocabularyTerm(TreeVocabulary, SimpleVocabularyTerm): """ Term inside of a TreeVocabulary or as an subterm """ security = ClassSecurityInfo() meta_type = 'TreeVocabularyTerm' implements(ITreeVocabularyTerm) schema = BaseSchema + Schema( ( StringField( 'id', required=0, ## Still actually required, but ## the widget will supply the missing value ## on non-submits mode="rw", accessor="getId", mutator="setId", default='', size=50, widget=IdWidget( label=_("label_key", default=u"Key"), description=_( "help_vocab_name", default= "Should not contain spaces, underscores or mixed case." ), ), ), StringField( 'title', required=1, searchable=0, default='', accessor='Title', widget=StringWidget(label=_("label_value", default=u"Value"), ), )), ) # Methods # methods from Interface IVocabularyTerm def getTermKey(self): """ """ if not HAS_LINGUA_PLONE or self.isCanonical(): return self.UID() else: return self.getCanonical().UID() def getTermValue(self, lang=None): """ """ if (not HAS_LINGUA_PLONE) or (lang is None): return self.Title() else: trans = self.getTranslation(lang) return trans and trans.Title() or self.Title() def getTermKeyPath(self): path = [ self.getTermKey(), ] actTerm = self while actTerm.aq_parent.portal_type != 'TreeVocabulary' \ and hasattr(actTerm.aq_parent, 'getTermKey'): path.append(actTerm.aq_parent.getTermKey()) actTerm = actTerm.aq_parent path.reverse() return path def getVocabularyKey(self): ''' returns the key of the field ''' deprecated( "please use the IVocabularyTerm compatible method 'getTermKey'") return self.getTermKey() def getVocabularyValue(self, lang=None, **kwargs): ''' returns the value of the field. The value is a processed value ''' deprecated( "please use the IVocabularyTerm compatible method 'getTermValue'") return self.getTermValue(lang=lang, **kwargs) # these should be inherited from SimpleVocabularyTerm processForm = SimpleVocabularyTerm.processForm edit = SimpleVocabularyTerm.edit update = SimpleVocabularyTerm.update
DEFAULT_VOCABULARY_CONTAINER = 'SimpleVocabulary' DEFAULT_VOCABULARY_ITEM = 'SimpleVocabularyTerm' VDEX_EXPORT_NEWL = '\n' VDEX_EXPORT_INDENT = '\t' # encoding of files in flat-file csv import IMPORT_ENCODING = 'latin-1' SORT_METHOD_FOLDER_ORDER = "getObjPositionInParent" SORT_METHOD_LEXICO_VALUES = "lexicographic_values" SORT_METHOD_LEXICO_KEYS = "lexicographic_keys" VOCABULARY_SORT_ORDERS = DisplayList(( ('getObjPositionInParent', _('Vocabulary Folder Order'), 'sort_method_folder_order'), ('lexicographic_values', _('Lexicographic sort by values'), 'sort_method_lexi_value'), ('lexicographic_keys', _('Lexicographic sort by keys'), 'sort_method_lexi_keys'), )) # LinguaPlone addon? import pkg_resources try: pkg_resources.get_distribution("Products.LinguaPlone") except DistributionNotFound: HAS_LINGUA_PLONE = False else: HAS_LINGUA_PLONE = True
DEFAULT_VOCABULARY_CONTAINER = 'SimpleVocabulary' DEFAULT_VOCABULARY_ITEM = 'SimpleVocabularyTerm' VDEX_EXPORT_NEWL = '\n' VDEX_EXPORT_INDENT = '\t' # encoding of files in flat-file csv import IMPORT_ENCODING = 'latin-1' SORT_METHOD_FOLDER_ORDER = "getObjPositionInParent" SORT_METHOD_LEXICO_VALUES = "lexicographic_values" SORT_METHOD_LEXICO_KEYS = "lexicographic_keys" VOCABULARY_SORT_ORDERS = DisplayList(( ('getObjPositionInParent', _('Vocabulary Folder Order'), 'sort_method_folder_order'), ('lexicographic_values', _('Lexicographic sort by values'), 'sort_method_lexi_value'), ('lexicographic_keys', _('Lexicographic sort by keys'), 'sort_method_lexi_keys'), )) # LinguaPlone addon? try: import Products.LinguaPlone except ImportError: HAS_LINGUA_PLONE = False else: HAS_LINGUA_PLONE = True GLOBALS = globals()