Example #1
0
class PloneSoftwareCenter(ATCTMixin, BaseBTreeFolder):
    """A simple folderish archetype for the Software Center."""

    implements(ISoftwareCenterContent)

    content_icon = 'product_icon.gif'

    archetype_name = 'Software Center'
    metatype = 'PloneSoftwareCenter'
    immediate_view = default_view = 'plonesoftwarecenter_view'
    suppl_views = ()

    global_allow = 1
    filter_content_types = 1
    allowed_content_types = ('PSCProject',)
    schema = PloneSoftwareCenterSchema
    _at_rename_after_creation = True

    security = ClassSecurityInfo()
    
    typeDescription = "A container for software projects"

    if NEEDS_UPDATE: # pre Plone3/GS-based install
        actions = updateActions(ATCTMixin,
                                ({
        'id'          : 'local_roles',
        'name'        : 'Sharing',
        'action'      : 'string:${object_url}/sharing',
        'permissions' : (permissions.ManageProperties,),
        },
                                 {
        'id'          : 'view',
        'name'        : 'View',
        'action'      : 'string:${folder_url}/',
        'permissions' : (permissions.View,),
        },
                                 )
                                )
    
    def canSelectDefaultPage(self):
        return False

    # Validator

    security.declarePrivate('validate_availableCategories')
    def validate_availableCategories(self, value):
        """Ensure that when setting available categories, we don't accidentally
        set the same category id as an existing project.
        """
        catalog = getToolByName(self, 'portal_catalog')
        projects = catalog.searchResults(
                            portal_type = 'PSCProject',
                            path = '/'.join(self.getPhysicalPath()))
        
        categoryIds = [v.split('|')[0].strip() for v in value]
        projectIds = [p.getId for p in projects]

        empty = []
        invalid = []
        for cat in categoryIds:
            if not cat:
                empty.append(cat)
            elif cat in projectIds or categoryIds.count(cat) > 1:
                invalid.append(cat)
    
        if empty:
            return "Please enter categories as Short Name | Long name | Description."
        if invalid:
            return "The following short category names are in use, either " \
                   "by another category, or by a project in the software " \
                   "center: %s." % (','.join(invalid))
        else:
            return None

    # Vocabulary methods
    security.declareProtected(permissions.View, 
                              'getAvailableTopicsFromClassifiers')
    def getAvailableTopicsFromClassifiers(self):
        """Get categories in DisplayList form, extracted from
        all classifiers that starts with 'Topic'"""
        field = self.getField('availableClassifiers')
        classifiers = field.getAsGrid(field)
        vocab = {}
        for id, title, trove_id in classifiers:
            if trove_id.startswith('Topic'):
                vocab[id] = (title, trove_id)
        return vocab

    security.declareProtected(permissions.View, 
                              'getAvailableCategoriesAsDisplayList')
    def getAvailableCategoriesAsDisplayList(self):
        """Get categories in DisplayList form."""
        return self.getField('availableCategories').getAsDisplayList(self)

    security.declareProtected(permissions.View, 'getAvailableClassifiersAsDisplayList')
    def getAvailableClassifiersAsDisplayList(self):
        return self.getField('availableClassifiers').getAsDisplayList(self)


    security.declareProtected(permissions.View, 'getAvailableLicensesAsDisplayList')
    def getAvailableLicensesAsDisplayList(self):
        """Get licenses in DisplayList form."""
        return self.getField('availableLicenses').getAsDisplayList(self)

    security.declareProtected(permissions.View, 'getAvailableVersionsAsDisplayList')
    def getAvailableVersionsAsDisplayList(self):
        """Get versions in DisplayList form."""
        return DisplayList([(item, item) for item in self.getAvailableVersions()])
    
    security.declareProtected(permissions.View, 'getAvailableVersionsAsDisplayList')
    def getAvailableSelfCertificationCriteriaAsDisplayList(self):
        """Get self-certification criteria in DisplayList form."""
        try: 
            return DisplayList([(item, item) for item in self.getAvailableSelfCertificationCriteria()])
        except:
            return DisplayList([('no','criteria')])
    
    # Mutator methods
    security.declareProtected(permissions.ModifyPortalContent, 'setProjectEvaluators')
    def setProjectEvaluators(self, value, **kw):
        orig = self.getProjectEvaluators()
        self.getField('projectEvaluators').set(self, value, **kw)
        
        usersToDemote = [id for id in orig if id not in value]
        usersToPromote = [id for id in value if id not in orig]
        
        for id in usersToDemote:
            roles = list(self.get_local_roles_for_userid(id))
            while 'PSCEvaluator' in roles:
                roles.remove('PSCEvaluator')
            if not roles:
                self.manage_delLocalRoles([id])
            else:
                self.manage_setLocalRoles(id, roles)
        for id in usersToPromote:
            roles = list(self.get_local_roles_for_userid(id))
            if 'PSCEvaluator' not in roles:
                roles.append('PSCEvaluator')
            self.manage_setLocalRoles(id, roles)

    security.declareProtected(permissions.View, 
                              'getFileStorageStrategyVocab')
    def getFileStorageStrategyVocab(self):
        """returns registered storage strategies"""
        return getFileStorageVocab(self)

    security.declareProtected(permissions.ModifyPortalContent, 'setStorageStrategy')
    def setStorageStrategy(self, value, **kw):
        """triggers an event before changing the field"""
        # the event will raise an error if any
        # project failed to migrate from one storage
        # to another
        old = self.getStorageStrategy()
        if old != value:
            event.notify(StorageStrategyChanging(self, old, value))
        self.getField('storageStrategy').set(self, value, **kw)
Example #2
0
class PSCProject(ATCTMixin, OrderedBaseFolder):
    """Project class that holds the information about the Software Project.
    """

    implements(IProjectContent)

    archetype_name = 'Software Project'
    immediate_view = default_view = 'psc_project_view'
    suppl_views = ()
    content_icon = 'product_icon.png'
    schema = PSCProjectSchema
    _at_rename_after_creation = True

    global_allow = False
    allowed_content_types = (
        'PSCReleaseFolder',
        'PSCImprovementProposalFolder',
        'PSCDocumentationFolder',
    )

    security = ClassSecurityInfo()

    typeDescMsgId = 'description_edit_package'
    typeDescription = ('A Software Project contains details about a '
                       'particular software package. It can keep track '
                       'of meta-data about the project, as well as '
                       'releases and improvement proposals.')
    if NEEDS_UPDATE:
        actions = updateActions(ATCTMixin, (
            {
                'id': 'local_roles',
                'name': 'Sharing',
                'action': 'string:${object_url}/sharing',
                'permissions': (permissions.ManageProperties, ),
            },
            {
                'id': 'view',
                'name': 'View',
                'action': 'string:${folder_url}/',
                'permissions': (permissions.View, ),
            },
        ))

    def canSelectDefaultPage(self):
        return False

    security.declarePrivate('initializeArchetype')

    def initializeArchetype(self, **kwargs):
        """Initialize package.

        Projects are initialized with a release folder.
        """
        OrderedBaseFolder.initializeArchetype(self, **kwargs)

        # if self.haveHelpCenter() and \
        #        not self.objectIds('PSCDocumentationFolder'):
        #    self.invokeFactory('PSCDocumentationFolder',
        #                       config.DOCUMENTATION_ID)

        if not self.objectIds('PSCReleaseFolder'):
            self.invokeFactory('PSCReleaseFolder', config.RELEASES_ID)

        # if not self.objectIds('PSCImprovementProposalFolder'):
        #     self.invokeFactory('PSCImprovementProposalFolder',
        #                        config.IMPROVEMENTS_ID)

        if not self.hasProperty('releaseCount'):
            self.manage_addProperty('releaseCount', 0, 'int')

    def _setAndIndexField(self, field_name, index_name, value):
        self.getField(field_name).set(self, value)
        self.reindexObject(idxs=[index_name])
        catalog = getToolByName(self, 'portal_catalog')
        res = catalog.searchResults(portal_type=[
            'PSCRelease', 'PSCFile', 'PSCFileLink', 'PSCImprovementProposal'
        ],
                                    path='/'.join(self.getPhysicalPath()))
        for r in res:
            o = r.getObject()
            o.reindexObject(idxs=[index_name])

    security.declareProtected(permissions.View, 'getView')

    def getView(self):
        """returns the view object"""
        return getMultiAdapter((self, self.REQUEST), name='project_view')

    security.declareProtected(permissions.ModifyPortalContent,
                              'setClassifiers')

    def setClassifiers(self, value):
        """Overrides classifiers mutator so we can reindex internal content.
        """
        self._setAndIndexField('classifiers', 'getClassifiers', value)

    security.declareProtected(permissions.ModifyPortalContent, 'setCategories')

    def setCategories(self, value):
        """Overrides categories mutator so we can reindex internal content.
        """
        self._setAndIndexField('categories', 'getCategories', value)

    security.declareProtected(permissions.View, 'getCategoryTitles')

    def getCategoryTitles(self):
        """Return selected categories as a list of category long names,
        for the user interface.
        """
        vocab = self.getCategoriesVocab()
        values = [vocab.getValue(c) or c for c in self.getCategories()]
        values.sort()
        return values

    security.declareProtected(permissions.View,
                              'getVocabularyTitlesFromCLassifiers')

    def getVocabularyTitlesFromCLassifiers(self):
        """Return selected categories as a list of category long names,
        for the user interface. Uses the classifiers.
        """
        vocab = self.getClassifiersVocab()
        values = [vocab.getValue(c) or c for c in self.getClassifiers()]
        values.sort()
        return values

    security.declareProtected(permissions.View, 'getClassifiersVocab')

    def getClassifiersVocab(self):
        """Get classifiers vocabulary from parent project area via acquisition.
        """
        return self.getAvailableClassifiersAsDisplayList()

    security.declareProtected(permissions.View, 'getCategoriesVocab')

    def getCategoriesVocab(self):
        """Get categories vocabulary from parent project area via acquisition.
        """
        return self.getAvailableCategoriesAsDisplayList()

    security.declareProtected(permissions.View,
                              'getSelfCertificationCriteriaVocab')

    def getSelfCertificationCriteriaVocab(self):
        """Get self-certification criteria vocabulary from parent project area
        via acquisition.
        """
        return self.getAvailableSelfCertificationCriteriaAsDisplayList()

    security.declareProtected(permissions.View, 'getReleaseFolder')

    def getReleaseFolder(self):
        """Get the release folder.

        We only should have one, so only deal with case of single
        folder. May return None if no roadmap folder exists.
        """
        type_filter = {'portal_type': 'PSCReleaseFolder'}
        folders = self.contentValues(filter=type_filter)
        if folders:
            return folders[0]
        else:
            return None

    security.declareProtected(permissions.View, 'getRoadmapFolder')

    def getRoadmapFolder(self):
        """Get the roadmap folder.

        We only should have one, so only deal with case of single
        folder. May return None if no roadmap folder exists.
        """
        type_filter = {'portal_type': 'PSCImprovementProposalFolder'}
        folders = self.contentValues(filter=type_filter)
        if folders:
            return folders[0]
        else:
            return None

    security.declareProtected(permissions.View, 'getNotAddableTypes')

    def getNotAddableTypes(self):
        """Hide the release container types if it already exists.
        """
        ignored = []
        objectIds = self.objectIds()
        if config.RELEASES_ID in objectIds:
            ignored.append('PSCReleaseFolder')
        if config.IMPROVEMENTS_ID in objectIds:
            ignored.append('PSCImprovementProposalFolder')
        if not self.haveHelpCenter() or \
            config.DOCUMENTATION_ID in objectIds:
            ignored.append('PSCDocumentationFolder')
        if config.TRACKER_ID in objectIds:
            ignored.append('PoiPscTracker')
        return ignored

    security.declareProtected(permissions.View, 'getVersionsVocab')

    def getVersionsVocab(self):
        """To ensure PloneHelpCenter integration works, return the versions
        defined, by looking at the versions found in the releases.
        """
        catalog = getToolByName(self, 'portal_catalog')
        releases = catalog.searchResults(portal_type='PSCRelease',
                                         path='/'.join(self.getPhysicalPath()))
        return [r.getId for r in releases if r]

    security.declareProtected(permissions.View, 'getCurrentVersions')

    def getCurrentVersions(self):
        """To ensure PloneHelpCenter integration works, return the versions
        which are supported, by looking at the versions found in the releases
        and subtracting the ones listed in unsupportedVersions.
        """
        allVersions = self.getVersionsVocab()
        unsupported = self.getUnsupportedVersions()
        return [v for v in allVersions if v not in unsupported]

    security.declareProtected(permissions.View, 'haveHelpCenter')

    def haveHelpCenter(self):
        """Test to see if PloneHelpCenter is installed
        """
        ttool = getToolByName(self, 'portal_types')
        if 'HelpCenter' in ttool.objectIds():
            return True
        else:
            return False

    security.declareProtected(permissions.View,
                              'getAvailableFeaturesAsDisplayList')

    def getAvailableFeaturesAsDisplayList(self):
        """Get list of Improvement Proposals in DisplayList form."""
        catalog = getToolByName(self, 'portal_catalog')
        projectPath = self.getPhysicalPath()
        if len(projectPath) > 1 and projectPath[-1] == 'portal_factory':
            projectPath = projectPath[:-2]

        search = catalog.searchResults(portal_type='PSCImprovementProposal',
                                       path='/'.join(projectPath))
        lst = DisplayList()
        for i in search:
            title = i.Title
            if len(title) > 40:
                title = title[:40] + '...'

            lst.add(i.UID, title)
        return lst

    def _distUtilsNameAvailable(self, ids):
        current_id = self.getId()
        sc = self.getParentNode()
        existing_projects = get_projects_by_distutils_ids(sc, ids)

        # make sure the names are not in another project already
        for project_id in existing_projects:
            if project_id != current_id:
                return False
        return True

    def getCompatibility(self):
        '''Get the compatibility of the product by getting
        the compatabilities of the LATEST release. This is
        used primarily by the index.
        '''
        compatabilities = []
        release = self.getLatestRelease()
        if release:
            for release_compatability in release.getCompatibility:
                compatabilities.append(release_compatability)
        compatabilities.sort(reverse=True)
        return set(compatabilities)

    def getLatestRelease(self):
        """Get the most recent final release brain or None if none
        can be found.
        """
        releaseFolder = self.getReleaseFolder()

        res = None

        if releaseFolder:
            catalog = getToolByName(self, 'portal_catalog')
            res = catalog.searchResults(path='/'.join(
                releaseFolder.getPhysicalPath()),
                                        review_state='final',
                                        sort_on='Date',
                                        sort_order='reverse',
                                        portal_type='PSCRelease')

        if not res:
            return None
        else:
            return res[0]

    def mayBeUnmaintained(self):
        """Return True if there hasn't been a release in over a year"""
        lastRelease = self.getLatestReleaseDate()
        if not lastRelease:
            return False

        if DateTime.DateTime() - lastRelease > 360:
            return True

        return False

    def getLatestReleaseDate(self):
        """
        Return the effective date of the last release. This is currently used for index
        and catalog data.
        """
        latest = self.getLatestRelease()
        if latest:
            return latest.effective
        return None

    security.declareProtected(permissions.ModifyPortalContent,
                              'setDistutilsSecondaryIds')

    def setDistutilsSecondaryIds(self, names):
        if not self._distUtilsNameAvailable(names):
            raise Unauthorized
        self.getField('distutilsSecondaryIds').set(self, names)
        self.reindexObject()

    security.declareProtected(permissions.ModifyPortalContent,
                              'setDistutilsMainId')

    def setDistutilsMainId(self, name):
        if not self._distUtilsNameAvailable([name]):
            raise Unauthorized
        self.getField('distutilsMainId').set(self, name)
        self.reindexObject()
Example #3
0
class TemplateUploadCenter(folder.ATFolder):
    """A Center to upload templates to a Plone site"""
    implements(ITemplateUploadCenter)

    archetype_name = 'Template Center'
    meta_type = "TemplateUploadCenter"
    immediate_view = default_view = "templateuploadcenter_view"
    suppl_views = ()

    global_allow = 1
    filter_content_types = 1
    allowed_content_types = ('PSCProject', )
    schema = TemplateUploadCenterSchema
    _at_rename_after_creation = True

    security = ClassSecurityInfo()

    typeDescription = "A container for software projects"

    if NEEDS_UPDATE:  # pre Plone3/GS-based install
        actions = updateActions(ATCTMixin, (
            {
                'id': 'local_roles',
                'name': 'Sharing',
                'action': 'string:${object_url}/sharing',
                'permissions': (permissions.ManageProperties, ),
            },
            {
                'id': 'view',
                'name': 'View',
                'action': 'string:${folder_url}/',
                'permissions': (permissions.View, ),
            },
        ))

    # Vocabulary methods
    security.declareProtected(permissions.View,
                              'getAvailableTopicsFromClassifiers')

    def getAvailableTopicsFromClassifiers(self):
        """Get categories in DisplayList form, extracted from
        all classifiers that starts with 'Topic'"""
        field = self.getField('availableClassifiers')
        classifiers = field.getAsGrid(field)
        vocab = {}
        for id, title, trove_id in classifiers:
            if trove_id.startswith('Topic'):
                vocab[id] = (title, trove_id)
        return vocab

    security.declareProtected(permissions.View,
                              'getAvailableCategoriesAsDisplayList')

    def getAvailableCategoriesAsDisplayList(self):
        """Get categories in DisplayList form."""
        return self.getField('availableCategories').getAsDisplayList(self)

    security.declareProtected(permissions.View,
                              'getAvailableClassifiersAsDisplayList')

    def getAvailableClassifiersAsDisplayList(self):
        return self.getField('availableClassifiers').getAsDisplayList(self)

    security.declareProtected(permissions.View,
                              'getAvailableLicensesAsDisplayList')

    def getAvailableLicensesAsDisplayList(self):
        """Get licenses in DisplayList form."""
        return self.getField('availableLicenses').getAsDisplayList(self)

    security.declareProtected(permissions.View,
                              'getAvailableVersionsAsDisplayList')

    def getAvailableVersionsAsDisplayList(self):
        """Get versions in DisplayList form."""
        return DisplayList([(item, item)
                            for item in self.getAvailableVersions()])

    security.declareProtected(permissions.View,
                              'getAvailableVersionsAsDisplayList')

    def getAvailableSelfCertificationCriteriaAsDisplayList(self):
        """Get self-certification criteria in DisplayList form."""
        try:
            return DisplayList([
                (item, item)
                for item in self.getAvailableSelfCertificationCriteria()
            ])
        except:
            return DisplayList([('no', 'criteria')])

    # Mutator methods
    security.declareProtected(permissions.ModifyPortalContent,
                              'setProjectEvaluators')

    def setProjectEvaluators(self, value, **kw):
        orig = self.getProjectEvaluators()
        self.getField('projectEvaluators').set(self, value, **kw)

        usersToDemote = [id for id in orig if id not in value]
        usersToPromote = [id for id in value if id not in orig]

        for id in usersToDemote:
            roles = list(self.get_local_roles_for_userid(id))
            while 'PSCEvaluator' in roles:
                roles.remove('PSCEvaluator')
            if not roles:
                self.manage_delLocalRoles([id])
            else:
                self.manage_setLocalRoles(id, roles)
        for id in usersToPromote:
            roles = list(self.get_local_roles_for_userid(id))
            if 'PSCEvaluator' not in roles:
                roles.append('PSCEvaluator')
            self.manage_setLocalRoles(id, roles)

    security.declareProtected(permissions.View, 'getFileStorageStrategyVocab')

    def getFileStorageStrategyVocab(self):
        """returns registered storage strategies"""
        return getFileStorageVocab(self)

    security.declareProtected(permissions.ModifyPortalContent,
                              'setStorageStrategy')

    def setStorageStrategy(self, value, **kw):
        """triggers an event before changing the field"""
        # the event will raise an error if any
        # project failed to migrate from one storage
        # to another
        old = self.getStorageStrategy()
        if old != value:
            event.notify(StorageStrategyChanging(self, old, value))
        self.getField('storageStrategy').set(self, value, **kw)